最近在解决某解密加固后的app对模拟器的检测问题,每次打断点分析,应用都会执行一个 strcmp 函数,其中一个参数是空,导致段错误退出
对比Android_x86项目能正常运行,又在网上查了些资料,经过不断调试尝试,发现该框架实现的反调试手段如下
Native(gdb)调试
1 检查/proc/$pid/status 文件
如果该文件下存在 TracerPid:\t${num}\n 行,并且${num}所代表的数字非0,则代表被ptrace追踪,进程自杀: 关键函数 fopen fgets
2 检查函数执行时间,在特定的函数安插gettimeofday函数,判断函数执行前后的时间,如果太长,则可能是被断点中断引起,进程自杀: 关键函数gettimeofday
3 设置SIGCONT 信号处理函数,gdb调试的过程是遇到断点发送SIGTRAP,然后检查是否命中断点,如果命中发送SIGSTOP使程序背上该信号,不能从内核中返回。
当用户执行下一步或者释放断点后发送SIGCONT信号,恢复程序运行,爱加密采用设置SIGCONT信号处理函数,如果ptrace发送SIGCONT则落入自己设置的信号处理函数执行,
该函数执行的操作是进程自杀 :关键函数 signal bsd_signal sigaction
4 /proc/$pid/wchan 查看睡眠状态是不是由于ptrace_stop引起的
5 在库加载的时候设置信号, 之后再设置信号,比对返回的旧信号值是否一致
对于上述三种方案采取的绕过措施
1 TracerPid 重写libc fgets函数,替换TracerPid的值
2 gettimeofday 重写libc, 在特定条件下重写时间. 另外值得注意的是会使用一个for循环执行多次gettimeofday函数,如果每次mock的时间比较长是不能绕过的
3 signal 替换应用设置的信号参数为SIGUSR2
4 同1
5 sysctl(name, sizeof(name) / sizeof(*name), &info, &info_size, NULL, 0); 返回值中有一位表示是否被ptrace
jdwp调试
Debug.isDebuggerConnected() 函数返回true表示已经调试器已经连接
这个绕过就太简单了
检测/data/dexname DexHunter目录
检测hook 遍历maps表,查看子串是否存在“apk@classes.dex”的字符串,若存在获取该模块的startAddr和endAddr, 然后检验此odex的头部是否为真正的dex文件。
/proc/$pid/wchan 查看睡眠状态是不是由于ptrace_stop引起的
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2020-12-11 11:17
被ermei编辑
,原因: