Android逆向⼯具篇—反编译⼯具的选择与使⽤
作者 | 天天记⼩本⼦上的lilac 来源 | CSDN
今天给⼤家介绍⼀下Android App 在Java层的逆向⼯具。
逆向⼯具的介绍
在过去,当我们想要了解⼀个 app 内部运作细节时,往往先通过 ApkTool 反编译 APK,⽣成 smali 格式的反汇编代码[1],然后⼤佬和⽼⼿直接阅读 smali 代码,适当的进⾏修改、插桩、调试,经过⼀定的经验和猜想,理解程序的运⾏逻辑和加解密细节,⽐如如下的 smali 代码。
smail
java源代码加密我们只要先这样,再那样,最后再这样,对对对,就这样,⼀个程序的加密就被破解出来了。是不是迫不及待想来⼀次App的逆向之旅了?
事实上,这种⽅式对⼩⽩实在不友好,有没有更加友好的⽅式呢?当然是有的,如果你百度或者 google 搜索逆向相关的教程和分享,很容易就会发现下⾯这三个⼯具。在介绍⼯具之前,我们先补充⼀下APK结构的知识,我们以伊对这个社交 Apk 为例。
APK ⽂件其实是⼀种特殊的 zip 格式,我们可以直接⽤ 360 压缩或者别的压缩⼯具打开。
为了满⾜⾃⾝的功能和设计,⼏乎每⼀个都会在基础的⽂件结构上添加不少东西,但有六个部分是不变的,我们罗列和称述⼀下。
⽂件或⽬录作⽤
META-INF/描述apk包信息的⽬录,主要存放了签名信息,配置信息,service注册信息
res/存放apk资源⽂件的⽬录,⽐如图⽚、图标、字符串、样式、颜⾊
assets/同样是存放apk资源⽂件的⽬录,但和res有差异,和我们关系不⼤
resources.arsc资源索引,包含不同语⾔环境中res⽬录下所有资源的类型、名称与ID所对应的信息
lib/存放so⽂件,越来越多的应⽤由C/C++编写核⼼代码,以SO⽂件的形式供上层JAVA代码调⽤,以保证安全性,这个⽬录是逆向解密关注的重点
classes.dex(⼀个或数个)Android程序运⾏在Dalvik虚拟机上,⽽dex就是Dalvik虚拟机的可执⾏⽂件, 相当于Windows平台中的exe⽂件,通过反编译dex,可以获得apk源码(这个说法不很准确,但⽅便理解)
接下来我们介绍以下反编译⼯具,看⼀下反编译⼯具的作⽤
⼯具作⽤
ApkTool解析resources.arsc,l等⽂件,反编译dex⽂件为smali源码
Dex2jar将dex⽂件转化为jar⽂件
Jd-gui反编译jar,查看java源码
⽐如使⽤ Dex2jar+Jd-gui, 最终得到这样的结果。
是不是感觉友好很多?只需要cmd敲七⼋⾏命令就可以得到java源代码。[2]
这样做肯定没问题,但能不能更加简单⼀些呢?能不能直接将Apk拖到什么软件⾥,然后电脑屏幕发亮,蓝底⿊字,⽇志和指令不停流淌,过⼀会⼉完整的java代码和apk结构就显现出来?
前⼈种树后⼈乘凉,真的有不少这样的⼯具,通过这⼀类⾼集成度的逆向⼯具,我们可以⽅便快捷对Apk进⾏逆向分析。
这⾥介绍⼏款:JADX,JEB,Android Killer,GDA。
1.1 Android Killer
⾸先说⼀下Android killer,这也是我接触的第⼀个反编译⼯具,开场界⾯⾮常酷。
它集成了Apktool,Jd-Gui等⼯具实现了拖拽式反编译,功能强⼤,并且可以安装插件,使⽤android killer进⾏smali⼀键插桩⾮常的畅爽。但由于更新慢,逐渐⽼旧,使⽤它反编译apk越来越⼒不从⼼,⽽且它只可以在windows平台使⽤,所以我们这边不做过多介绍,但不可否认它有⼀些⾮常棒的功能。
1.2 GDA
GDA是国⼈制作的⼀款反编译神器,功能强⼤,灵活⾄极。我们先说⼀下它的优点,仅2.6M⼤⼩,简直不可思议,⽽且它不需要JDK环境,测试时反编译七⼋⼗兆⼤的apk也不会卡死,除此之外,它还附带有反混淆,查壳等功能……
接下来我们说⼀下它的缺点:
⼀、反编译出来的java代码展⽰性不够友好,变量名不够友好,⼤多是v0, v1, p1等(更像是原⽣寄存器的命名法)。
⼆、⼯具的⽂档和⽂章不算充分,在搜索逆向⼯具教程时,⽐较难到其相关介绍。
三、只能在windows平台运⾏和使⽤,不⽀持mac等其他平台,这很遗憾。
四、单论反编译效果,JADX太好⽤了………………
1.3 JADX vs JEB
JADX:免费,开源,强⼤,更新快
优点:反编译能⼒强,代码结构好,变量名合理,⽀持多平台,完全就是个和我⼀样完美的靓仔,是我⼼中逆向分析APK的第⼀⼯具。[3]
缺点:⽐较吃内存,⼀个50M⼤⼩的APK,使⽤JADX反编译就需要占⽤4G左右内存。
JEB:收费,可动态调试
优点:可以动态调试,⽽且JEB吃内存⽐较少,反编译同等⼤⼩的APK,JEB只要Jadx⼀半内存就可
以搞定。同时,端⼝⾃动转发带来了舒适⽅便的动态调试体验。
缺点:反编译出来的java伪代码展⽰性不够友好,变量名不够友好,⼤多是v0, v1, p1。
我们测试对⽐⼀下GDA,JEB,JADX三个软件的反编译效果如图:HttpRequestEntity这个构造⽅法[4]反编译效果的对⽐
可以看出,JADX反编译的结果最为接近正常的java代码,在后续使⽤过程中,你还会发现它全局搜索功能的便捷和舒适。
你可能会困惑,上⾯花了不是不少时间,分析和⽐较了⼏个软件的优缺点,⼜⽤证据说明了JADX是像你⼀样的靓仔,那我们肯定毫不犹豫选择你啊,呸,选JADX啊。为什么要三个都装呢?
原因很简单,在技术娴熟和精通之前,APP逆向是门不折不扣的⽞学,既然是⽞学,就会有很多不可控、随机、稀奇古怪的状况。当JADX 中⼀个变量模糊不清的时候,你就需要去JEB中看⼀下它的反编译结果,或者使⽤JEB进⾏动态调试。当使⽤JEB 遇到头疼的APK混淆时,就可以试⼀下开启JADX的反混淆功能。因为这⼏个软件的逆向原理是不同的,所以在分析具体APK时各有优势,它们的功能可以互补。多个⼯具结合使⽤可以⼀定程度弥补个⼈能⼒的不⾜,只需要⼏百M空间放它们即可,何乐⽽不为呢。
1.4 JADX的配置和使⽤
直接下载,个合适的地⽅解压即可,按照⾃⼰的操作系统打开相应的⽂件即可。
可能出现的两个问题:
为什么双击jadx-gui.bat 出现控制台⼀闪⽽过,没有正确出现界⾯因为你的JAVA_HOME环境变量没有正确配置,但也不排除是JDK版本的问题。
反编译卡死、闪退 Apk超过50M就很容易出现OOM(OutOfMemoryError),在win中,它默认使⽤4G内存,可以查看界⾯底部居中部分。
如果你的window系统是8G或者更⾼运⾏内存,我们可以修改参数进⾏扩容。⽂本模式打开jadx-gui.bat,将被框出的内容数值改为8g或者更⼤,如果电脑运⾏内存更⼤,也可以改成更⾼的数值。100M以内的App,8G内存⾜够了。
接下来重新打开JADX,内存就已经更改了。
如果你的windows系统只有4G运⾏内存,我们依然有很多办法使⽤jadx,实战中再说。
接下来说⼀下mac中的扩容,⽂本模式打开jadx-gui这个⽂件,到和上述类似的位置,更改为更⼤的值即可。
JADX的使⽤和快捷键
1. 搜索代码、类、⽅法——Ctrl+N,建议不要使⽤左上⾓的搜索类/搜索⽂本,因为图标太⼩,很容易按错,如果你第⼀次搜索⽤搜索
类,第⼆次搜索时选择搜索⽂本,那第⼀次的搜索内容和设置是不会记录下来的。所以不如直接看⼀下⼯具栏中的快捷键,只⽤⼀个。
2. ⽂件-⾸选项中,如果内存够⽤,我建议勾选“⾃动进⾏后台反编译”,因为Jadx默认只有在你展开内容或者搜索内容时,才会开始反编
译。不要勾选Unicode⾃动转义,否则代码中的中⽂会被转成unicode,不⽅便识别和搜索。
3. Ctrl+⿏标左键,可以跳转到⽅法内部,⼏乎所有的代码编辑器都是这样。
4. 别的⼀些可以修改的地⽅我放在了下图红框⾥,⽐如反编译线程数,线程数越多,反编译越快,但占⽤内存也越多,建议根据电脑性
能调整,不调整也OK。反混淆⼀般不⽤开。
1.5 JEB的配置和使⽤
同样直接下载,个合适的地⽅解压,按照⾃⼰的操作系统打开相应的⽂件即可。我们同样要进⾏JEB的扩容,默认为1.8G,我们需要进⾏更改。
更改前
更改后
Windows中JEB的扩容
将整个红框内容替换如下
:startjeb
set JEB="%~"
if exist %JEB% goto :runlauncher
%JAVA% -jar -Xmx4g -Xms4g "%~dp0bin\app\jebc.jar" %*
exit 0
:runlauncher
%JEB% %*
exit 0
mac如何扩容我了解不多,如果遇到问题可以和我探讨。
1.6 GDA的配置和使⽤
只有windows可以⽤,exe直接点开即可,以后会⽤到,到时候再说
[1]: Smali是dex⽂件反编译的结果,可以说,smali语⾔是Dalvik的反汇编语⾔,下⽂会介绍DEX
[2]: 我们这⼀个系列的教程针对的是⽆壳App,⽽当你⾃⼰拿到⼀个未知的App时,第⼀步要做的⼀定⼀定得是查壳。
[3]: 得到的并不是Java源代码,这是个错误的说法,但对初学者来说⽐较容易理解。不管你通过什么⼯具反编译apk,得到的java代码都和Apk开发时的源代码相差甚远。我们能得到的仅仅是⼀种伪代码,
它可能存在错误的逻辑、奇怪的变量名、各种各样的error,但代码总体上是靠谱的。
[4]: 为了阅读和讲解的循序渐进,我们这⾥并没有把IDA考虑进来,IDA是神器,在后⾯是避免不了的。
[5]: 这条注释针对没有JAVA基础的⼩伙伴,构造函数在JAVA中⾮常常见,JAVA是⼀门⾯向对象的语⾔,构造函数是⼀种特殊的函数。其主要功能是⽤来在创建对象时初始化对象,构造函数与类名相同。如果听不懂也没关系,知道是个函数即可,后续也会慢慢补充JAVA知识。