本文方法来自看雪和52大佬的几个帖子,在理解其方法原理的基础上我做了一点总结,放在博客加深记忆,温故知新。
部分方法由于安卓系统的安全性更新已经无法使用,但是可以找到替代办法。
一、检测常用调试端口
思路:部分调试器对真机进行调试时会与特定端口建立连接(如IDA会连接23946),因此检测到端口被占用就认为手机正在被调试。
Android 10后/proc目录用户无法读取,因此旧版本*问/proc/net/tcp的方法失效。替代办法是直接借助InetAddress查找特定端口是否被占用即可。
示例代码如下:
注解:IDA调试端口是可以更改的,因此该方法只能作为初步判断法。
二、调试进程名检测
思路:遍历进程名,若找到特定的进程,则认为调试器正在运行。比如android_server,gdb_server,frida_server等等。
三、父进程名检测
思路:该方法是针对so文件调试的。若调试者不采用启动app附加进程调试,而是直接编写一个.out可执行文件加载so文件运行,这样父进程名是zygote而非正常启动app的父进程。读取/proc/pid/cmdline,查看内容是否为zygote。
由于安全性更新无法访问此目录:/proc/pid/cmdline。这里感谢pareto的指正,app层在真机下是只能访问自身/proc/pid下的文件,并非完全无法访问,这使得我们可以通过检查Tracerpid这个属性进行反调试
四、APK线程检测
正常apk进程一般会有十几个线程在运行(比如会有jdwp线程),但是自己编写的可执行文件加载so一般只有一个线程,可根据线程数量差异来进行调试环境检测。示例代码:
注解:可以先测试自身app产生的线程数目,再判断是否被调试,如果线程数目显著大于测试得到的结果,那可以认为遭到了注入或者调试。
五、ptrace检测
Android系统限制,每个进程同一时刻只能被1个调试进程ptrace,主动ptrace本进程可以使得其他调试器无法调试。
六、签名校验
app被重打包之后签名就会出现改变,可以检测签名防止重打包。示例代码:
注解:签名校验的效果很强,但是市面上已经有很多过签名的通用方法了(参考np管理器,mt管理器)