模拟器检测 & 反调试
1 模拟器检测
具体参考:检测Android虚拟机的方法和代码实现
简单列举一下:
- 根据特征检测
- Device ID
- Default Number
- IMSI
- Buid类
- 运营商名称
- QEMU驱动
- QEMU文件
- Genymotion文件
- QEMU管道
2 反调试
2.1 IDA端口检测
远程调试会占据一些固定的端口号
/proc/net/tcp
查找IDA所用的端口23946
,如果发现说明进程正在被IDA调试在
netstat -apn
结果中搜索23946
1 | void CheckPort23946ByTcp() { |
2.2 调试器进程名称检测
调试的时候会在手机中运行特定的进程 如:
android_server
gdbserver
gdb
做法:遍历进程名,找到则说明调试器在运行
1 | void SearchObjProcess() { |
如果不是使用apk附加调试,而是单独写一个程序,加载so文件进行调试
2.3 父进程检测
那么,程序的父进程名称和正常启动apk的父进程名称是不一样的。
- 正常启动的apk程序父进程名称都是
zygote
- 调试启动的apk父进程也还是
zygote
- 附加调试的apk程序父进程是
zygote
- vs远程调试可执行文件加载so 父进程名为
gdbserver
2.4 自身进程检测
名字不是
com.xxxx
2.5 apk 线程检测
正常apk线程个数比较多
自写可执行程序线程单一
/proc/{pid}/task
2.6 apk进程fd文件检测
根据
/proc/pid/fd
下文件个数的差异,判断进程的状态
2.7 安卓系统自带调试函数检测
检测调试:
1 | public static boolean isBeingDebugged() { |
2.8 ptrace检测是否有程序跟踪:
进程下status
第6行不为0
1 | private static String tracerpid = "TracerPid"; |
2.9 函数hash值检测
so文件中函数的指令是固定,但是如果被下了软件断点,指令就会发生改变(断点地址被改 写为bkpt断点指令),可以计算内存中一段指令的hash值进行校验,检测函数是否被修改或被下断点
2.10 断点指令检测
可以在函数体中搜索bkpt指令来检测软件断电。
2.11 系统源码修改检测
2.12 单步调试陷阱
原理:
调试器调试下断点到执行断点过程如下:
保存: 保存目标处指令
替换: 替换目标处指令为断点指令
执行中断: 引发中断
调试器收到信号之后,执行调试器注册的信号处理函数
- 恢复:调试器处理函数恢复保存的指令
- 回退:回退PC寄存器
- 控制权回归程序
反调试方案:
在代码中注册断点信号处理函数
在非调试状态下:
进入自己注册的函数,NOP掉断掉指令,回退PC后正常指令
在调试状态下:
进入调试器的断点处理流程,会恢复目标指令失败,回退PC进入死循环
2.13 利用IDA先截获中断特性的检测
IDA会首先截获信号,导致进程无法接收到信号,导致不会执行信号处理函数。将关键流程 放在信号处理函数中,如果没有执行,就是被调试状态
2.14 执行时间检测
正常情况下:在a地点获取执行时间,运行一段时间后,在b处获取时间,然后求时间差,这个差会比较小。
调试状态下: 如果存在调试,那么这个时间差会比较大
2.15 进程信息结构检测
/proc/pid/status
/proc/pid/task/pid/status
TracerPid != 0
statue字段写入了t(tracing stop)
/proc/pid/stat
proc/pid/task/pid/stat
第二个字段为t
/proc/pid/wchan
/proc/pid/task/pid/wchan
ptrace_stop