篇幅有限
完整内容及源码关注公众号: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