文章目录
一、IDA server安装
1、把本地IDA server文件推送进手机目录
adb push android_server(cpu型号要对应 模拟器是x86) /data/local/tmp/
2、进入手机shell
adb shell
3、修改权限运行server
真机要使用 su 命令 切换到root用户,模拟器不用
#进入手机tmp目录
cd /data/local/tmp/
#修改权限
chmod 777 android_server
#在本地执行adb 做端口转发
adb forward tcp:23946 tcp:23946
#运行
./android_server
二、了解反调试策略
策略之一:检查自身status中的TracerPid字段,防止被其他进程附加调试
IDA调试原理 是利用Linux系统 ptrace 来实现
当应用被调试时,应用内存里的TracerPid 字段就不为0
进入设备查看ptrace字段:
//进入设备
adb shell
//获得APP的进程ID
ps | grep 包名
//打印该APP里内存状态信息
cat /proc/pid(进程ID)/status
D:\反编译APP\platform-tools>adb shell
shell@le_x6:/ $ su
root@le_x6:/ # ps | grep crack
1|root@le_x6:/ # ps | grep crack
u0_a111 7498 598 1206204 92396 SyS_epoll_ 00f6ed2d34 S com.yaotong.crackme
root@le_x6:/ # cat /proc/7498/status
Name: yaotong.crackme
State: S (sleeping)
Tgid: 7498
Pid: 7498
PPid: 598
TracerPid: 0 // 当前app没有被调试
Uid: 10111 10111 10111 10111
Gid: 10111 10111 10111 10111
root@le_x6:/ # cat /proc/7498/status
Name: yaotong.crackme
State: t (tracing stop)
Tgid: 7498
Pid: 7498
PPid: 598
TracerPid: 6031 // 当前app正在被调试中
Uid: 10111 10111 10111 10111
Gid: 10111 10111 10111 10111
反调试,既检测TracerPid是否被占用。
so文件反调试的手段就是:新建一个线程 不停的检测TracerPid这个字段是否不为0, 不为0,就立即退出程序。
linux中创建进程的函数pthread_create()
更多反调试策略:https://bbs.pediy.com/thread-223460.htm
三、反调试处理方法
动态调试,找到检测TracerPid的代码,不执行此代码
方法:
此检查代码一般在.init_arra 和 JNI_OnLoad两处
在JNI_OnLoad函数出打断点调试,找到检测TracerPid的代码,不执行此代码
IDA调试反调试小经验
如何找到反调试代码: 结合IDA静态时的代码,观察程序逻辑 指令一般会整过执行完,直到函数末尾。
在IDA调试中,如果指令在中途某个地方退出了,说明该处就是反调试指令。
如何在JNI_ONLoad函数打断点
so文件在加载阶段会执行JNI_ONLoad,此后不再执行,要在so文件加载阶段才能给JNI_ONLoad打断点。
System.loadLibrary()加载so文件流程?
1)先读取so文件中的.ini_arry段(快捷键Ctrl+S)
2)在执行JNI_ONLoad函数(JNI_ONLoad是.so文件初始化函数)
3)然后在调用具体native方法
1、给app加上可调式权限
反编译APP,修改APP中的AndroidMenifest.xml文件, 给APP加上可调试权限, android:debuggable="true"
,重新打包APP,签名、安装
2、检查flags中是否有允许debug项
adb shell dumpsys package com.yaotong.crackme
3、以调试模式启动APP APP此时会挂起
adb shell am start -D -n 包名/.类名
adb shell am start -D -n com.yaotong.crackme/.MainActivity
app处于挂起状态
4、IDA设置
正常连接目标进程
Debugger — DebuggerOptions里勾选
Suspend on thread start/exit
Suspend on library load/unload
JNI_OnLoad函数是lib刚加载时就会执行,必须要在lib载入时就让程序停下来,才能调 试JNI_OnLoad
5、点击运行按钮
6、在设备里查看APP的进程ID
要adb shell先进入设备运行如下命令,过滤出该应用信息
ps | grep 应用包名
7、使用JDB命令让APP 恢复运行
adb forward tcp:8700 jdwp:873(APP的PID)
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
8、定位反调试代码
在so文件被加载时,IDA会停止住,使用ctrl+s 查看目标so文件是否加载,目标so文件没有被加载就点击运行。
若加载点选目标so文件,计算JNI_OnLoad的绝对地址
静态调试方式打开目标so文件查看JNI_OnLoad函数的地址00001B9C
计算JNI_OnLoad的绝对地址
按G键跳转到JNI_OnLoad 出设置断点,恢复APP执行。
程序在调试的过程中没有正常执行完JNI_ONLoad函数,而在中途异常退出,判断在当前退出位置即为反调试函数所在位置。
启动线程
最终程序终止运行。由此可以判断R7这里的指令就是在做反调试检测。
找到反调试代码处,pthread_create()
;
如何找到反调试代码处?(关键地方,可按f5,把汇编代码转成C语言辅助);
反复按F8单步执行,程序退出处(前面),既为反调试处 ;
9、 如何让反调试代码不执行?
- 让该指令变为空指令,既 NOP,NOP指令的16进制是 00 00 00 00
- 记住反调试处的汇编指令,同时以静态方式再打开一个IDA(也叫双开IDA 以动态 和静态方式各打开一个IDA )
- 打开so文件,在静态ida里查找到此汇编指令,鼠标选中后面寄存器,然后切换到 Hex View,会显示该指令的16进制
复制该16进制,再用一文本工具打开目标so文件,找到该16进制处,替换成 00 00 00 00 ,既空指令。既不执行反调试代码,保存so文件,再重新打包APP,签名,重新安装APP。
编辑器:UltraEdit 专业文本/十六进制编辑器 (x64)
10、 开始正式调试APP
以上操作都是针对反调试进行的操作,目的就是绕过反调试,让我们可以使用IDA调试APP。
1、如何计算要调试函数的绝对地址:
- 绝对地址 = so文件的基地址 + 该函数的偏移量
so文件基地址
函数偏移量
2、按键盘G键, 输入绝对地址,跳转到要调试的函数处
函数名右键打断点–并运行程序
3、在APP中触发securityCheck函数
怎么触发securityCheck函数呢?
- 就是在我们输入密码后点击登陆就会触发该函数的执行,函数一旦执行我们就可以在IDA中进行调试。
结合之前静态调试时分析的
程序在执行过程中没有顺序执行结合指令CMP(比较),该段代码就是在判断输入的密码是否正确,我们随便输入的1234,判断错误所以代码不会顺序执行
R0的值为1234并赋给R1,即R3为原密码。
动态调试时也可以按F5直接将汇编代码转换为C代码,转换后可以查看变量的值