调试器状态检测
根据android的官方文档,如果调试一个APK,必须满足以下两个条件中的任何一个:
1 APK的AndroidManifest.xml
文件中的Application标签包含android:debuggable="true"
2 /default.prop
中的ro.debuggable=1
根据Android SDK提供的android.os.Debug.isDebuggerConnected()
方法可以进行判断程序是否被调试器调试了。
因此,当程序被设定为禁止调试时通过修改android:debuggable="true"
来进行反反调试就行不通了,此时只能进行修改boot.img等方法来进行反反调试了。
调试器端口检测
调试器远程调试时,会占用一些固定的端口号,如23946。因此可进行读取/proc/net/tcp进行查看,若发现23946端口正在被使用,则说明程序在被调试。
可以在启动调试程序时修改端口,如使用命令./android_server -p12345
以及adb forward tcp:12345 tcp:12345
进行反反调试。
调试器进程名检测
要远程调试则需要在手机中运行android_server、gdbserver等进程。因此可以通过读取ps进行遍历进程,查找固定的进程名,若能找到则说明程序在被调试。
可以修改android_server、gdbserver等程序名称来进行反反调试。
Tracerpid检测
当程序未被调试时,/proc/pidxxx/status
中的Tracerpid字段会为0。若程序在被进行调试,则Tracerpid字段的值就会改变。因此可以对Tracerpid字段进行检测,从而判断程序是否被调试。
ptrace检测
每个进程同时刻只能被1个调试进程ptrace。因此,当程序被调试器进行调试后,如果程序再对自己进行ptrace就会失败,从而知晓程序在被调试。亦或者直接进行ptrace自己,从而让调试器无法进行附加调试,而且此时Tracerpid字段肯定不为0。如果使用修改系统源码再重新编译的方法对Tracerpid检测反调试进行绕过,则此时Tracerpid字段会为0,从而知道源码被修改了。
断点检测
调试器从下断点到执行断点的过程:
1 保存:保存目标处指令及数据
2 替换:目标处指令替换为断点指令
3 命中断点:命中断点指令(引发中断或者说发出SIGTRAP信号)
4 收到信号:调试器收到SIGTRAP信号后,执行调试器注册的信号处理函数。
5 恢复:调试器处理函数恢复保存的指令
6 回退:回退PC寄存器
7 回归:控制权回归原程序
因此可对so中的在可执行segment进行遍历,查看是否出现ARM、Thumb以及Thumb2的断点指令即可判断程序是否被调试。