IDA动态调试
配置:
#把本地文件推送进手机目录(我的nexus是64位的)
#注意注意!!!!这里不是Frida的server是ida自带的server!!
adb push android_x86_server(cpu型号要对应 模拟器是x86) /data/local/tmp/
#进入手机shell
adb shell
#真机要使用 su 命令 切换到root用户,模拟器不用
#进入手机tmp目录
cd /data/local/tmp/
#修改权限
chmod 777 android_server
#运行
./android_server
#在本地执行adb 做端口转发
adb forward tcp:23946 tcp:23946
等待加载
ctrl + s 找到要调试的so文件 选择用X字样(可执行的)
按键盘G键, 输入绝对地址,跳转到要调试的函数处
如何计算要调试函数的绝对地址:
绝对地址 = so文件的基地址 + 该函数的偏移量
so文件的基地址在哪儿找:
快捷键 ctrl + s 找到目标so文件 Start 那一项就是 基地址
函数的偏移量在哪儿找:
以静态方式打开so文件,函数列表里
得到函数的绝对地址,按g进行跳转
跳转到目标函数后,在此处设置断点(快捷键F2 或 fn+F2 或右键)
断点设置好后,点击左上角三角形运行,等待APP运行到此断点处,就会停止,此时即可调试
F7单步调试,要进入函数
F8单步调试,不进入函数(一般情况用这个)
so反调试
IDA调试原理 是利用Linux系统 ptrace 来实现
当应用被调试时,应用内存里的TracerPid 字段就不为0
进入设备查看ptrace字段:
//进入设备
adb shell
//获得APP的进程ID
ps | grep 包名
//打印该APP里内存状态信息
cat /proc/pid(进程ID)/status
TracerPid为0代表没有被调试,不为0代表在被调试。
反调试,既检测TracerPid是否被占用
so文件反调试的手段就是:
新建一个线程 不停的检测TracerPid这个字段是否不为0, 不为0,就立即退出程序。
//linux中创建进程的函数
pthread_create()
反反调试
动态调试,找到检测TracerPid的代码,不执行此代码
方法:
根据so文件的加载顺序,此检查代码一般在.init_arra 和 JNI_OnLoad两处
在JNI_OnLoad函数出打断点调试,找到检测TracerPid的代码,不执行此代码
如何在JNI_OnLoad函数打断点:
so文件在加载阶段会执行JNI_ONLoad,此后不再执行,要在so文件加载阶段才能给JNI_OnLoad打断点
-
修改APP AndroidMenifest.xml文件, APP加上可调试权限,android:debuggable=“true”,重新打包APP,签名,安装
扫描二维码关注公众号,回复: 13120777 查看本文章 -
检查flags中是否有应许debug项
adb shell dumpsys package com.yaotong.crackme
-
以调试模式启动APP APP此时会挂住
adb shell am start -D -n 包名/.类名
adb shell am start -D -n com.yaotong.crackme/.MainActivity
- DebuggerOptions里勾选 Suspend on thread start/exit | Suspend on library load/unload,因为JNI_OnLoad函数是lib刚加载时就会执行,必须要在lib载入时就让程序停下来,才能调试JNI_OnLoad
- 点击运行按钮
- 在设备里查看APP的进程ID
要adb shell先进入设备运行如下命令,过滤出该应用信息
ps | grep 应用包名(可以是一部分,用来过滤)
ps | grep cra
- 使用JDB命令让APP 恢复运行
adb forward tcp:8700 jdwp:27556(APP的PID)
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
- 在so文件被加载时,IDA会停止住,使用ctrl+s 查看目标so文件是否加载,没有的话点击绿色运行,然后继续查看是否被加载。找到后进行的JNI_OnLoad的绝对内存位置计算,按g进行位置跳转。按一下绿色开始然后F8单步调试(pthread_create也是关键字眼)
- 用UltraEdit打开so文件,把上面37 FF 2F E1的汇编指令数值改成00 00 00 00,重新打包签名然后安装,解决反调试的问题
解决反调试的问题之后继续在securityCheck打断点,再点击左上角绿色运行让程序执行
然后因为这里是通过APP输入密码后才触发,所以输入密码,成功断上
上面按F5也能知道是运行到那
成功!
动态调试libcrackme拿到密码:
- 分析出密码判断的函数是哪一个
- IDA静态分析此函数,理清脉络(变量重命名会有帮助,一些语句判断)
- IDA动态调试,在此函数处下断点调试
- 单步调试,观察指令执行流程
- 密码不对时,指令会跨越执行,不再顺序执行
- 动态调试时,在关键指令处按F5,把指令转成c代码辅助分析
- 动态调试时鼠标移动到寄存器上,会显示该寄存器里的值
- 动态调试时,把指令转换成C代码,把鼠标移动到C代码的变量上,会显示该变量的值