题目链接
https://github.com/eternalsakura/ctf_pwn/blob/master/android逆向/AliCrackme_2.apk
反调试原理
ptrace
ptrace提供了一种使父进程得以监视和控制其它进程的方式,它还能够改变子进程中的寄存器和内核映像,因而可以实现断点调试和系统调用的跟踪。
在执行系统调用之前,内核会先检查当前进程是否处于被“跟踪”(traced)的状态。如果是的话,内核暂停当前进程并将控制权交给跟踪进程,使跟踪进程得以察看或者修改被跟踪进程的寄存器。
反调试
用fopen打开/proc/
TracerPid如果为0说明没有别的进程在调试这个进程,如果不为0说明有程序在调试
反调试程序执行时机
- .init_array是一个so最先加载的一个段信息,时机最早,现在一般so解密操作都是在这里做的
- JNI_OnLoad是so被System.loadLibrary调用的时候执行,它的时机要早于哪些native方法执行,但是没有.init_array时机早
动态调试
连接到实体机,打开监听
./android_server
这里开始监听设备的23946端口。
端口转发
如果要想让IDA和这个android_server进行通信,那么必须让PC端的IDA也连上这个端口
adb forward tcp:远端设备端口号(进行调试程序端) tcp:本地设备端口(被调试程序端)adb forward tcp:23946 tcp:23946
打开要调试的apk,找到入口
adb shell dumpsys activity top
打开monitor
启动apk
adb shell am start -D -n com.yaotong.crackme/.MainActivity
设备将处于一个Waiting For Debugger的状态
在要调试的函数下断点,这里我们在JNI_OnLoad下断。
设置IDA
attach进程
断在libc.so
tips:这里为什么会断在libc.so中呢
android系统中libc是c层中最基本的函数库,libc中封装了io、文件、socket等基本系统调用。所有上层的调用都需要经过libc封装层。所以libc.so是最基本的,所以会断在这里,而且我们还需要知道一些常用的系统so,比如linker
在控制台使用jdb恢复进程运行
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
按下F9执行程序
弹出窗口,这里是问apk里的so文件和我们正在调试的是否是同一个,当然是same
正常情况会出现:
报错处理:
- 打开ddms尝试.
- 检查调试的app配置文件中是否有android:debuggable=”true”,导致不能调试。若无则在清单文件的application中加上,重新打包即可.
JNI_OnLoad中单步调试找到check点
函数顺利断下
F8单步找到Check点
执行BLX R7
之后就跳入libc中断分析
反编译一下,找到BLX R7那行函数,这个函数就是pthread_create,它调用sub_16A4
进入sub_16A4,它调用sub_130C,在这里进行反调试,所以我们只需要把它nop即可
另外的一些分析
在module list里找到libc.so,再从中找到fopen函数
在fopen断下之后,查看hex窗口
(在这之前需要先设置hex数据与R0同步)
查看一下这个8358进程是什么,果然是我们的crack apk,再看看它的status,发现被trace了
这个trace的进程就是我们的android_server
patch so
arm中对应的nop指令是:00 00 00 00
我们可以选择nop掉BL sub_130C,或者直接nop掉BLX R7,这里我们nop后者
数据窗口中跟随,按F2去编辑
修改并保存
感觉IDA的patch并不是很好用,所以我们记下地址后用010editor打开修改更好
将原apk中的so文件替换为此so文件,重新打包签名安装,现在直接打开app调试就不会退出了. Success!
securityCheck
找到securityCheck函数下断
输入密码后断下
剩下的就是很简单的比较
直接找到密码,over~
flag是aiyou,bucuoo