安卓反调试与检测小结
本文方法来自看雪和52大佬的几个帖子,在理解其方法原理的基础上我做了一点总结,放在博客加深记忆,温故知新。
部分方法由于安卓系统的安全性更新已经无法使用,但是可以找到替代办法。
一、检测常用调试端口和文件
思路:常见调试器如IDA,gdb、Frida等进行调试时,手机存储中会存在掉时期的可执行文件,如android_server(IDA),frida-server(Frida)、gdb。同时,在调试期间手机会监听特定端口,与调试PC建立连接(如IDA会连接23946,Frida会连接27042)。
因此检测到相应的可执行文件,或特定端口被占用就认为手机正在被调试。
Android 10后/proc目录用户无法读取,因此旧版本上访问/proc/net/tcp来确定端口占用情况的方法已经失效。替代办法是直接借助InetAddress查找特定端口是否被占用即可。
示例代码如下:
注解:IDA、frida的手机端调试器的文件名和调试端口都是可以更改的。例如,以下命令可以让Frida在手机上以8888端口启动:
$ /data/local/tmp/fs1280arm64 -l 0.0.0.0:8888
显然文件名和端口都变了,因此该方法只能作为参考。
二、调试进程名检测
思路:遍历进程名,若找到特定的进程,则认为调试器正在运行。比如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管理器)