篇幅有限
完整内容及源码关注公众号:ReverseCode,发送 冲
样本
来自阿里聚安全的Crackme,自毁程序密码_1.0原版.apk

随机输入密码后报错验证码校验失败,通过jadx-1.2.0搜索后发现调用了校验逻辑在SO层的securityCheck中

SO分析
解压该apk后IDA打开自毁程序密码_1.0原版\lib\armeabi\libcrackme.so,搜索java找到securityCheck导出函数

通过F5将汇编转成伪C代码,分析大致逻辑后点击v3通过JNIEnv*还原指令


或者通过Y修改参数类型
int __fastcall Java_com_yaotong_crackme_MainActivity_securityCheck(JNIEnv *a1, jobject a2, jstring a3)
还原后使用/添加注释,n修改别名为易读变量,输入的字符串和密码逐位对比,


动态调试
将IDA中的D:\IDA 7.0\dbgsrv\android_server拷贝到真机/data/local/tmp下
1 | adb push android_server /data/local/tmp |
新建IDA的Instance,打开该app后以attach附加调试



ctrl+s找到需要调试的so,ctrl+f搜索so名,找到第一个带x权限的so文件双击进入

函数在内存中绝对地址=so文件基地址+函数地址偏移量,即EF0DD000+11A8=EF0DE1A8


g跳转到该函数的内存地址中EF0DE1A8,进入该函数中右键加上断点,F8单步不进入函数调试,F7单步进入函数调试


F8单步调试或者点击左上角绿色三角按钮,闪退并报错FFFFFFFF,目测加了反调试。

一般检测是否可调试的技术方案是通过linux系统的ptrace实现,当当应用被调试时应用内存里的TracerPid字段就不为0,只要是不为0的时候,就会直接的退出程序,达到反调试的目的。端点调试报错FFFFFFFF后该TracerPid变成了0。

反反调试
附加调试
System.loadLibrary()加载so文件流程
- 先读取so文件的.init_array段
- 再执行JNI_OnLoad函数
- JNI_ONLoad是.so文件的初始函数
- 然后调用具体的native方法
程序的so文件在加载阶段会先执行JNI_OnLoad,之后就不再执行,在程序的so文件加载阶段才能给JNI_OnLoad打断点调试即可,首先需要将app回编译添加可调试权限。
修改回编译打包
1 | apktool b 青青草视频/ 回编译 |
或者配置Android Killer

在application中添加**android:debuggable=”true”**,保存后编译生成新apk,卸载原apk后重新安装

1 | adb shell |



1 | adb shell ps | findstr com.yaotong.crackme 找到进程id为14383 |
Debugger-Debugger options 点击左上角启动

1 | jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700 转发8700端口,继续运行程序 |
寻找JNI_Onload
内存计算
点击左上角运行,直到ctrl+s找到so被加载的时候,找到crackme.so的第一个可执行时机,双击进入找到该so的偏移量

通过静态分析的JNI_OnLoad地址,相加得到JNI_Onload的内存地址=EF09AB9C


g跳转到JNI_OnLoad地址EF09AB9C,F2打断点,F8单步执行,鼠标一到寄存器R值可以显示字符串的值

IDA搜索
Modules中搜索crack,进入so后搜索JNI找到EF09AB9C


SO修复

通过下一步反复调试发现在图中断点出BLX R7的位置跳出报错FFFFFFFF,期间ctrl+s可以不断尝试看libcrackme.so是否出现,此处应该就是就是反调试检测位置了

双击或者右侧打开R7寄存器,出现pthread_create新建一个线程不停的检测TracerPid这个字段是否不为0, 不为0,就立即退出程序。

我们可以通过修改R7为00 00 00 00直接nop掉该指令,因为删除的话so文件有固定格式,多段内容的偏移值容易发生错乱。
在静态调试页面中找到BLX R7位置,进入Hex View-1,修改指令




或者ultraedit直接修改保存即可,将修改后的so替换原Android Killer中的so,并重新签名打包安装。

破解密码
1 | ./as7.0 |
启动好该app后,获取该app的进程id并进程转发
1 | adb shell ps | findstr com.yaotong.crackme |



进入断点后,在Modules中搜索crack,直接找到securityCheck函数并g定位到该函数的具体地址EF0DF1A8


结合静态分析,找到判断的位置并打上断点,这个R3相比就是真实的密码了

点击左上角启动,输入onejane确认后R0就是我们输入的密码

F5进入C伪代码后鼠标悬浮查看v6 = off_EF0E428C密码为aiyou,bucuoo。

重新输入密码完成So层的逆向。

总结
利用Android Killer回编译,IDA逆向SO层转汇编为伪C代码进行动静态分析调试,SO修复反反调试等手段完成该Crackme的逆向。
01:17

