这年头,apk 全都是加密啊,加壳啊,反调试啊,小伙伴们表示已经不能愉快的玩耍了。静态分析越来越不靠谱了,apktool、ApkIDE、jd GUI、dex2jar 等已经无法满足大家的需求了。那么问题就来了,小伙伴们真正需要的是什么?好的,大家一起呐喊出你内心的欲望吧,我们的目标是——"debug apk step by step"。
先来说说那些不靠谱的工具,就是今天吭了我小半天的各种工具,看官上坐,待我细细道来。
2.1 IDA pro
IDA pro6.6 之后加入了 dex 动态调试功能,一时间普天同庆、喜大普奔。兴奋之后你才会发现 IDA 这东西在动态调试方面真的是很挫,就算他是静态反编译之王,我也不得不说他的动态调试功能还非常需要加强。先说说使用 ida 调试 dex 的方法。
IDA pro 调试 dex 流程:
- 1.用apktool反编译apk,添加android:debuggable="true",重打包apk并签名
- 2.从apk文件中扣出class.dex文件,不管你用什么方法,7zip、unzip…whatever
- 3.用ida打开这个dex文件,直到output window窗口显示"xxxx finished"
- 4.设置debugger选项,debugger->debugger options->set specific options,按如图1所示进行设置,然后一路确定返回
- 5.找到要下断点的位置,光标移到要下断点的那一行,按f2下断点
- 6.手机开启调试选项,链接usb到电脑
- 7.选中IDA pro窗口,按f9走起,不出意外的话应该会出现如图2的画面,成功啦~
- 图 1 ida debug配置
- 图 2 ida动态调试apk
- 触发断点,在watch view和Locals窗口都能看到内存变量的值,简直就是画美不看啊,是不是有点小兴奋?!我只能说高兴的太早了,小伙伴们还是太天真了,仔细观察下,就算你勾选了"Hex display",你还是无法以hex格式显示变量的值,就是说不可显示字符你都看不到值是什么,而且我找了很久也没找到类似windbg、od、vc6、gdb、lldb那样以各种姿势或者命令直接查看某内存地址值的功能,然后就出现了如图3的画面……WTF!我特么忙活了半天居然还不如直接logcat来得痛快!
- 图 3 Locals窗口
2.2 apktool+eclipse
其实小生一直还是很支持 eclipse 的,毕竟伴我度过了无数不眠之夜和懵懂的年华(当然苍老师和 windbg 可能占的更多),可是这次我真的有点小失望哈。由于使用 apktool+eclipse 和 apktool+ studio 的调试方法跟 apktool+idea 一样,调试方法后面一起说,这里我就先纯吐槽了。
当小伙伴们成功设置调试选项,带着嗨翻的心情进入调试界面的时候,我们看到了如图 4 的画面,细细观察和各种尝试之后,我保证你的心里一定有一万头草泥马奔腾而过!!!。
- 图 4 eclipse单步调试apk
我们都看到了啥:
1.debug 窗口表示命中第 30 行的断点
2.variables 窗口没有任何本地变量的值,寄存器的值也没有
3. 单步步入、单步步过等调试按钮都是灰色的,快捷键 F5678 都没反应
我就想知道这你让我怎么 debug,难道我要设无限个断点,拼命 f9 来调试?就算是这样,我该去哪儿看变量的值?
android studio 这个东西本来是蛮不错的,就是稍微有点卡,习惯了也还好。其实 android studio 本身就是用 idea 改的,但是好像给改挫了。调试方法还是后面再说,直接上成功挂载到调试界面的图,如图 5。
- 图 5 android studio单步调试apk
这次情况是这样的:
1. 可以看到现在程序停在哪一行,虽然不明显
2. 本地变量能看到,但是寄存器还是木有啊
3. 单步按钮还有单步快捷键都能用了,看起来好多了啊
我还是想说,问题是寄存器的值还是没法直观的看到啊,对于有强迫症的我还是无法接受这种设定啊,想当年 vc6、od、windbg、gdb、lldb 是多么的给力,多么的好用!
0×03 apktool+idea
正菜来了,apktool 2.0bete9 版本推出了 - d 选项,专门用来重打包 apk 进行单步调试的,给力!apktool+idea 无源码 debug apkstep by step 简直不要太好用,这也是我跟小波请教之后才弄好的,这个选项也是小波等人建议 apktool 作者这样做的,不禁感叹一句,波神你为何这么屌!
3.1 调试基础
[CCG] 的文章,原文链接:
根据 android 的官方文档,如果要调试一个 apk 里面的 dex 代码,必须满足以下两个条件中的任何一个:
由于正常的软件发布时都不会把 android:debuggable 设置为 false(当然也不排除某些很 2 的应用偏偏就是 true),所以要达成条件 1 需要对 app 进行重新打包,这不仅每次分析一个 apk 都重复操作,而且很多软件会对自身进行校验,重打包后执行会被检测到,所以想办法满足第 2 个条件是个一劳永逸的办法。
由于 default.prop 是保存在 boot.img 的 ramdisk 中,这部分每次重新启动都会重新从 rom 中加载,所以要到目的必须修改 boot.img 中的 ramdisk 并重新刷到设备中。修改步骤如下(我没试过,有兴趣的倒腾下):
- 1.从Google官方网站下载到boot.img
- 2.使用工具(abootimg,gunzip, cpio)把boot.img完全解开,获取到default.prop
- 3.修改default.prop
- 4.把修改后的文件重新打包成boot_new.img
- 5.使用fastboot工具把boot_new.img刷入设备(fastboot flash boot boot_new.img)
3.2 调试方法
这里我们还是用第一种方法来进行:
1. 下载 apktool2.0b9 版本,下载地址:
2. 使用 apktool 反编译 apk:
- java -jar apktool_2.0.0b9.jar d -d xxx.apk -o out
加上 - d 选项之后反编译出的文件后缀为.,而不是. smali,每个. java 文件立马都伪造成了一个类,语句全都是 "a=0;" 这一句,smali 语句成为注释,小伙伴们自己看看打开就知道了,做这些都是为了后面欺骗 idea、eclipse、androidstudio 这些 ide 的;
3. 加入 android:debuggable="true" 选项;
4. 重打包 apk,一定记得也使用 - d 选项:
- java -jar apktool_2.0.0b9.jar b -d out -o debug.apk
5. 对 apk 进行签名并安装 apk 到调试设备(这个不用我说怎么操作吧);
6. 下载安装并打开 idea,新建一个空的 java 项目,本例中项目名为 "DebugOnly",将 apk 反编译后的 smali 目录下的所有文件拷贝到刚才新建的 java 项目的 src / 目录下,刷新,如图 6;
- 图 6拷贝文件
- 7.打开androiddevice monitor(终端下敲命令monitor或者ddms),终端下运行命令:adb shell am start -D -n {Package Name}/.{Activity},运行效果如图7;
- 图 7命令运行效果
- 此时在调试设备上会显示等待调试器接入:
- 图 8调试设备状态
- 8.从androiddevice monitor上发现需要调试的程序已经显示在列表里面了,记下端口号,本例中为8700;
来源: