通过一道题目学习安卓的动态调试与反反调试
- 2015阿里&看雪移动安全挑战赛-第二题 https://blog.csdn.net/scoronepion/article/details/51340137
工具:jadx、ida、雷电模拟器
启动雷电模拟器,安装程序
adb install ./AliCrackme_2.apk
拿到AliCrackme_2.apk,首先jadx反编译一波,查看MainActivity类,程序在native方法securityCheck()进行验证

找到加载的动态链接库,对应的文件即是libcrackme.so

解压apk,把AliCrackme_2\lib\armeabi\libcrackme.so拖进ida,静态调试
找到Java_com_yaotong_crackme_MainActivity_securityCheck,这个函数就是MainActivity类声明的native方法
F5反编译,分析代码,关键部分如下:

对应的汇编代码:

作用:输入的字符串与off_B5F628Cb比较,相等则返回1
查看off_B5F628Cb的值

flag到手?

验证失败,说明寄存器的值在程序运行时会发生动态改变。因此使用动态调试看看程序运行时发生了什么
动态调试
安卓开启监听
首先查看手机的cpu架构
adb shell uname -a
到ida dbgsrv目录下把对应cpu架构的远程调试服务器上传到模拟器
adb push .\android_server64 /data/local/tmp/
给权限
adb shell
cd /data/local/tmp
chmod 777 *
启动远程调试,指定监听端口
.\android_server64 -p1314
手机没有联网,无法使用ip访问,将安卓本地端口映射到远程(windows本机)端口
开启另一个终端
adb forward tcp:1314 tcp:1314
在ida连接到远程调试,程序运行时进行连接

attach到apk运行的进程
**这里有个小坑,受到SElinux的限制,只有root用户才能查看所有进程。所以远程调试服务器要以root身份执行,否则能attach的进程只有寥寥几个,而且还不包括运行着的apk。

找到libcrackme.so,进入Java_com_yaotong_crackme_MainActivity_security函数入口,F2下断点

F9运行,程序奔溃
大概是程序做了反调试保护
反反调试
一般情况下反调试的机制
这是使用ida对程序进行动态调试时,程序进程的状态,可以看到TracePid为3537。

反调试保护时开启一个线程,检测TracePid是否为0,如果不为0,就认为程序处于调试状态,这个程序采取的处理措施是闪退!!
找出检测tracepid的线程并挂起,即可绕过反调试

可以看到此时程序没有闪退,函数顺利执行
如何跳到函数关键代码(静态调试与动态调试相结合)
如何跳到函数关键代码?即静态调试时进行比较的部分:

静态调试时,.so文件的基址地址是0x00000000,所以这里的地址不是程序运行时真正的内存地址。
使用动态调试.so文件的基址替换掉静态调试的基址,即可知道关键代码的真实地址0x0B5F12B0
![]()


jump到0x0B5F12B0,得到寄存器在运行时的值。拿到flag


总结