Android初探反编译

Android初探反编译

本文记述反编译的初级手段。(其余的属于专业的逆向开发人员)
  反编译属于****中的一种,其有很多高级的手段和工具。当我们对别人开发好的应用感兴趣时,我们就可以通过这种技术手段将别人打包好的apk进行反编译,继而可以看到我们感兴趣的内容,比如我们想拿到目标apk的图片素材资源和源代码等。

本文主要记述以下内容:

1.使用dex2jar和jd-gui来反编译apk的方式。
2.使用apktool来对apk进行二次打包的方式。


一. 3个工具的准备:

  1. apktool:
    作用:资源文件获取,可以提取出图片文件和布局文件进行使用查看。
    下载地址:https://bitbucket.org/iBotPeaches/apktool/downloads/
  2. dex2jar:
    作用:将apk反编译成java源码(classes.dex转化成jar文件)。
    下载地址:https://sourceforge.net/projects/dex2jar/files/
  3. jd-gui:
    作用:查看apk中classes.dex转化成出的jar文件,即源码文件。
    下载地址:http://java-decompiler.github.io/
    Android初探反编译
    注: 建议将这3个工具放在同一个文件夹下,并解压后方便使用。

解压后:
Android初探反编译


二. 准备待反编译的apk

将待反编译的apk文件放入到上面的工具路径下。
Android初探反编译


三. 使用apktool反编译apk得到图片、XML配置、语言资源等文件:

  cmd,然后切换到上面图中所示的工具路径:
Android初探反编译
Android初探反编译
  运行apktool_2.4.0.jar,文件来将apk文件进行反编译。

在java中,运行可执行jar包的命令是:
java -jar jar包名.jar

例如我这里输入:java -jar apktool_2.4.0.jar d -f app-release.apk -o MyApk

上述命令讲解:
apktool_2.4.0.jar:是下载的apktool工具的名称。
d:表示解包
-f:表示如果当前目录已经存在,那么直接覆盖它。
app-release.apk:表示待反编译的apk的文件名称
-o:表示输出,即output
MyApk:是文件夹名,代表输出路径文件夹,没有则自动新建。

Android初探反编译
上面如果没有Error则代表反编译成功,且我们还可以看见输出的目录:

Android初探反编译
Android初探反编译
在上面的文件夹中,我们所关心的就是res和AndroidManifest.xml.
  想查看哪个xml文件就使用文本编辑器打开看看吧,反正全部都可以看到了。以上就是使用apktool这个工具将一个apk反编译得到图片、XML配置、语言资源等文件的过程。


四. 使用dex2jar反编译apk得到Java源代码:

  将要反编译的APK后缀名改为.rar或者 .zip,并解压,得到其中的classes.dex文件(它就是java文件编译再通过dx工具打包而成的)
Android初探反编译
改后缀名后,我们需要的是classes.dex文件:
Android初探反编译

将解压后的classes.dex放入到dex2jar-2.0文件夹中,因为前面说过,dex2jar的作用是将apk反编译成java源码(classes.dex转化成jar文件)。
Android初探反编译

Android初探反编译

然后cmd,切换到dex2jar-2.0文件夹路径下:
Android初探反编译
然后输入命令:d2j-dex2jar classes.dex
Android初探反编译
然后我们会在dexjar下看到classes-dex2jar.jar文件:
Android初探反编译


五. 使用jd-gui.exe查看上面生成的classes-dex2jar.jar文件:

  JD-GUI虽然可以将class反编译成java源代码,但是对于一些被混淆过的class,反编译的效果就不是那么理想了,被混淆过的class反编译后的效果图(类文件名称以及里面的方法名称都会以a,b,c…之类的样式命名)
Android初探反编译
然后将classes-dex2jar.jar拖进来:
Android初探反编译

好了,以上就是传统的方式来反编译APP,但不是所有的APP都能反编译…


扩展:

  1. 使用dex2jar和jd-gui反编译apk:
    Dex2jar和jd-gui在很多操作系统上都可以使用。Dex2jar是一个将dex文件转换为jar包的工具,它在Windows和Linux上都有对应的版本,dex文件来源于apk,将apk通过zip或者rar包的方式解压缩即可提取出里面的dex文件。有了jar还不够,因为jar包其实都是class文件。所以还需要jd-gui将jar包进一步转换为java代码,jd-gui仍然支持windows和Linux。不管是dex2jar还是jd-gui,他们在不同的操作系统中使用的方式都是一致的。
    Dex2jar是命令行工具,它的使用方式:

Windows:dex2jar.bat classes.dex
Linux(Ubuntu): ./dex2jar.sh classes.dex

Jd-gui是一个图形化工具,直接双击打开通过菜单打开jar包或者直接将jar包拖进去即可查看jar包的源码。

通过dex2jar和jd-gui来反编译apk的总体流程:

1.将apk解压后提取出classes.dex文件
2.通过dex2jar来反编译classes.dex
3.通过jd-gui来打开反编译后的jar包
然后我们就可以看见和源代码比较接近的代码了。通过jd-gui左边的菜单还可以查看其他类的反编译结果。

  1. 使用apktool对apk进行二次打包:
    有些apk,我们可以直接改后缀名为zip.rar再解压得到资源文件。而dex2jar和jd-gui可以将一个dex文件反编译为java代码,但是他们无法反编译出apk中的二进制数据资源,但是采用apktool就可以做到,apktool的另一个常见用途就是二次打包,即常见的山寨版应用。
    apktool同样有windows和Linux版,其是一个命令行工具:

Linux(Ubuntu)中:
解包: ./apktool d -f xxx.apk 输出文件夹
二次打包: ./apktool b 输出文件夹 xxx-fake.apk
签名: java -jar signapk.jar testkey.x509.pem testkey.pk8 xxx-fake.apk xxx-fake-signed.apk

Windows中:
解压:apktool.bat d -f xxx.apk 输出文件夹
二次打包:apktool.bat b 输出文件夹 xxx-fake.apk
签名:java -jar signapk.jar testkey.x509.pem testkey.pk8 xxx-fake.apk xxx-fake-signed.apk

  上述中,Windows系统的兼容性问题,有时候会导致apktool.bat无法在Windows的一些版本上正常工作,这个时候可以安装Cygwin,然后采用Linux方式来进行打包即可。
  部分apk也可能会打包失败,听大佬们说,apktool在Linux上的打包成功率要比windows高。

命令参数解释:

  • 解包命令中:
    d:解包
    xxx.apk:待解包的apk
    输出文件夹:解包后的文件的存储路径
    -f:如果输出文件夹目录已经存在,那么直接覆盖它
  • 打包命令中:
    b:打包
    输出文件夹:解包后的文件的存储路径
    xxx-fake.apk:二次打包后的文件名

  通过apktool解包以后,可以查看到apk中的资源以及smali文件,smali文件是dex文件反编译(不同于dex2jar的反编译过程)的结果。Smali有自己的语法并可以修改,修改后可以被二次打包为apk,通过这种方式就可以修改apk的执行逻辑。
注:apk经过二次打包并不能直接安装,必须要经过签名后才能安装。这里我们可以联想到我们平常在android studio中运行自己写的代码然后安装到我们的手机上,貌似我们也没有签名啊。实则不然,其as背后的实际工作流程是AS会将程序代码打包成一个APK文件,然后将这个文件传输到这个手机上,最后再执行安装操作。安卓系统会将所有的APK文件识别为应用程序的安装包,类似于Windows系统上的.exe文件。但并不是所有的APK文件都能成功安装到手机上,Android系统要求只有签名后的APK文件才可以安装,因此还需要对生成的APK文件进行签名才行。而平常我们貌似没有执行签名操作,其实是因为AS使用了一个默认的keystore文件帮我们自动进行了签名。在as的右侧->Gradle->项目名->:app->Tasks->android,然后可以打开signingReport就可以看到默认的keystore文件了。总而言之,通过as来运行的程序都是使用这个debug.keystore文件来进行签名的。这个仅仅适用于开发阶段。当发布的时候就需要使用一个正式的keystore文件来进行签名,其可以使用as来生成或者gradle来生成。还可以生成多渠道的apk等。
  废话说多了,再看上面的签名命令中,采用的是signapk.jar完成签名,签名后的生成的apk就是我们俗称的“山寨apk”,其签名的过程中采用的签名文件不是官方的,最终xxx-fake-signed.apk就是二次打包形成的一个山寨版的apk。但是这种方式生成的apk和正版生成的apk还是有很大区别的。

  很多产品都i可以做签名校验,简单的二次打包所得到的山寨版的apk安装后无法运行。但还是可以通过修改smali的方式来绕过签名校验。
  逆向方面的专业书籍会有介绍关于smali的语法及其如何修改smali。


补充:

Android界有名的大神写关于Android反编译的博客:
(郭婶)http://blog.****.net/guolin_blog/article/details/49738023

(鸿洋大神)http://blog.****.net/lmj623565791/article/details/23564065

(主席任玉刚)http://blog.****.net/singwhatiwanna/article/details/18797493