Android IDA 动态调试so(过掉JNI_Onload调试检测)笔记

链接:https://pan.baidu.com/s/1oOH9RgukXJcXianq8jgYhg 
提取码:5lzf 
这个是我调试的样本APK,是阿里逆向前几年的一道题。

拿到APK,先用apktool 解包

apktool d ali.apk ,解包之后打开文件夹发现存在so文件,于是用JEB或者android killer打开APK

先查找入口主类,发现是com.yaotong.crackme.MainActivity 

然后看到android:bebuggable ="true"这个属性并没有在APK里面,想要动态调试APK的话,那么待会我就需要添加这段代码 。

先点开主类查看函数

 

主界面只有一个Button,所以button点击的函数事件就是检测密码,然后这个函数securityCheck()是注册在so文件里面的, 使用IDA 打开so文件,查看securityCheck()函数 

然后F5反汇编,其中这段代码是说输入密码和正确密码逐位对比,所以我们可以动态调试so输出正确密码

 

但是这题不可能有这么简单,CTRL+S查看init_array,没发现什么异常,再检测JNI_Onload,看到里面有一大堆代码,猜测应该是用来反调试用的(反调试手段不可能就只有个android:debuggable="false"或者不加这个属性这么简单,大多数情况会在init_array或者JNI_Onload开启线程检测TracePid或者端口23946之类的,因为程序启动的时候最先JNI_Onload和init_array是在主界面启动之前响应,所以在这里面加入反调试代码最好)

然后修改 AndroidManifest.xml添加android:debuggable="true",打包APK:apktool b ali -o ll.apk,使用签名工具对ll.apk进行签名,这里我用的是android killer进行签名,使用adb 命令将APK安装到手机 adb install C:\Users\a1046\Desktop\SecretJungle\ll_sign.apk

想要动态调试so文件,需要将IDA pro里面的android_server push 到手机 /data/local/tmp文件夹下,并赋予777权限

adb push XXXXX(路径)\android_server /data/local/tmp 

adb shell 

su 

cd /data/local/tmp

chmod -R 777 android_server,然后ls -al 查看,然后./android_server启动,重开一个cmd,输入adb forward tcp:23946 tcp:23946,然后以调试模式启动程序 adb shell am start -D -n com.yaotong.crackme/.MainActivity

打开IDA ,点击debugger->select debugger ,这样选择,然后确定

然后再Debugger->process options 进行如下设置

然后Debugger->attach to process ,找到目标进程 点击进去

 

接下来出现的选项点yes,然后Debugger->Debugger options进行如下设置

设置好了之后按F9,启动程序,打开ddmx(SDK tools 文件夹),打开cmd输入jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700,然后接着f9,直到jdb attach 住了(IDA出现的界面选项中 有yes点yes,有same 点same);

再linker加载进来之后ctrl+s搜索目标so ,看到so已经加载进来

cancel,然后再右侧moudules中搜索so 打开Jni_onload,下个断点,F9,出现选项点yes;

 

 

接着开始F7 F8单步调试。多次调试发现在运行玩BLX R7之后程序会退出,那么此处应该就是反调试检测机制了。

打开R7寄存器 出现pthread_create ,证明猜测正确

然后使用用IDA pro静态打开so 文件 找到汇编代码,产看blx R7 的十六进制,37 FF 2F E1

使用010 Editor或者win hex修改成 00 00 00 00 就是直接nop掉这条指令(直接删除指令的话,文件会发生错乱,因为so文件有固定的格式,比如很多段的内容,每个段的偏移值都是保存的,这样删除的话会影响偏移值)。

然后重新打包,签名,安装到手机,之后就是正常的动态调试了,启动程序,启动android_server ,转发端口

打开IDA->Debugger ->attach->Remote Armlinux/Android Debugger ,确定

找到com.yaotong.crackme进程点击进去。在modules查看crackme.so 打开SecurityCheck函数,下个断点,F9在手机上随便输入密码:crackSample,开始单步调试

调试到这的时候,点击R0寄存器查看 发现是我输入的密码

那么R2应该就是正确密码了,为aiyou,bucuoo(0x61为a)

打开程序检测 输入 ,正确 搞定

 

 

 

### 如何在 IDA 中处理 JNI_OnLoad 函数 #### 定位 JNI_OnLoad 函数 为了定位 `JNI_OnLoad` 函数,可以利用已知的偏移量来计算其实际地址。对于给定的例子,如果 `libcrackme.so` 文件中的 `JNI_OnLoad` 函数相对于起始位置有固定的偏移,则可以通过简单的加法运算找到该函数的具体地址[^3]。 例如,假设 SO 文件加载基址为 AA238000H 并且 `JNI_OnLoad` 的 RVA (Relative Virtual Address) 是 00001B9CH, 那么真实的内存地址将是: ```assembly AA238000H + 00001B9CH = AA239B9CH ``` 一旦获得了这个确切的位置,在 IDA Pro 中就可以通过按 G 键并输入上述地址来进行导航;接着使用 F2 设置断点以便于后续调试操作。 #### 动态调试准备 为了让动态调试更加顺利,建议先让应用处于等待状态直到连接上外部调试工具再继续运行。这通常涉及到修改 Android 应用启动参数使其支持远程调试模式[^4]。具体做法是在命令行中执行如下指令: ```bash adb shell am start -D -n com.example.app/.MainActivity ``` 这里的 `-D` 参数指示系统暂停应用程序直至有一个合适的调试器被挂载上去为止。 #### 调试过程中注意事项 值得注意的是,尽管 `JNI_OnLoad` 常用于初始化 Java Native Interface 扩展功能,但它并非总是最先被执行的部分。实际上,在某些情况下,操作系统可能会优先调用 ELF 文件内的 `.init` 或者 `.init_array` 段里的其他代码片段[^2]。这意味着仅依赖于 `JNI_OnLoad` 来部署保护机制可能不够安全可靠,开发者应当考虑更全面的安全策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值