配置环境
一台已root手机
- IDA pro6.6
- Android SDK
准备工作:
- 把Android SDK添加到环境变量中
- 把已root手机的系统中关键so拖到本地,必要时可以静态读取,获取系统函数的偏移地址。 例如把手机系统的
system/lib的文件拖到本地debugging文件夹中。adb pull /system/lib .\debugging\lib - 在IDA pro6.6中找出
android_server,并把android_server放到手机system/bin中。push的时候没有root权限,可以如下操作:1
2
3
4adb push android_server /data/local/tmp
adb shell
su
cp /data/local/tmp/android_server /system/lib
环境启动
由于需要调试程序启动加载的so,所以步骤比较多。
- 进入
adb shell,在手机中执行android_server。1
2
3adb shell
su
android_server - 进行端口转发
adb forward tcp:23946 tcp:23946 - 使用调试模式启动程序,
adb shell am start -D -n 包名/类名,以上一篇博文的dexunshellram为例,dexunshellram动态加载了crackme0201,启动命令如下:adb shell am start -D -n com.droider.dexunshellram/com.droider.crackme0201.MainActivity - 打开IDA6.6,打开需要调试的so,然后选择
Debugger->Select debugger,选择Remote ARM Linux/Android debugger。
然后选择Debugger->Debugger options,勾选所有logging和Events里的Suspend on thread start/exit和Suspend on library load/unload。
然后选择Debugger->process options,在Hostname中填写127.0.0.1,端口默认为23946。
然后选择Debugger->attach a process,选择com.droider.dexunshellram。
然后可能出现如下图所示,需要add map,由于之前把手机系统的system/lib复制到电脑中,这样可以指定到电脑的相应文件夹中,这样就可以静态调试系统so。如果你觉得你用不着调试系统函数,可以不用指定。
- 在Android SDK中找出
ddms.bat,双击打开,为了后面执行jdb。 - 在IDA中点击运行或者按F9,然后在cmd中运行一下命令启动jdb
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700 - IDA在linker中停下了,然后在path中找到相应调试的
libunshellram.so,选择函数Java_com_droider_dexunshellram_unshellram_loadDex,这里是内存动态加载dex的地方。在else语句之前进行断点,就是loc_前一行插入断点,按F2,然后再运行程序,按F9。
dump内存
如下图所示,R0寄存器BE8F9144-48保存着dex文件的地址。
可以看出寄存器保存的地址为0x7653E008
查看0x7653E018地址可以看出存储的就是dex文件,dex文件是dex.035开头的。而0x7653E038-3B存储着是dex文件的长度25C5BC
把以下脚本保存成dump.py,通过在file->Script File,选择dump.py。然后输入0x7653E018,输入长度0x25C5BC,最后输入保存的文件C:\\classes.dex。
1 | import struct |
把dex文件dump到C盘中,由于是crackme0201的classes.dex,如果把dex放回之前博文的crackme0201的apk中,可以正常启动应用。