rtld_db_dlactivity
,函数指针,非调试状态下为空指针,调试状态下指向断点;非导出函数,遍历内存中的 /system/bin/linker
的符号表得到符号地址android.os.Debug.isDebuggerConnected()
,返回当前的调试器的附加状态方法 | 效果 |
---|---|
TracerPid | 得到调试器PID |
子进程调试 | 占据调试名额,防止非法调试器附加 |
rtld_db_dlactivity | 得到调试器附加状态 |
Debug 类 | 得到调试器附加状态 |
理论上这几种反调试单独使用都能取得不错的效果,但容易被绕过。因此通常状况下都是联合使用,增长反反调试的成本,同时还能够应对不一样的场景。android
如使用 SDK 方式分发安全模块,则不能影响手游项目的正向开发。正常的开发环境下,调试器和游戏进程在同一个用户组中,这种状况下只能使用检测 TracerPid 的方式。取出调试器的 GID 和游戏进程的 GID 看是否在同一个用户组中,便可判断出是否为合法调试器。xcode
ptrace(PT_DENY_ATTACH,0,0,0)
来禁止调试器附加,ptrace
函数在 iOS 下没有对应的头文件函数声明,须要经过 dlsym
或 extern int ptrace(int,pid_t,cadrr_t,int)
的形式得到sysctl
查询当前进程是否有 P_TRACED
标识,该标志存在则标识进程正在被调试// 禁止附加 extern int ptrace(int, pid_t, caddr_t, int); void DisablePtrace() { ptrace(PT_DENY_ATTACH, 0, 0, 0); }
// 检测跟踪标识 int IsPflagExist() { size_t size = sizeof(struct kinfo_proc); struct kinfo_proc info; int name[4]; memset(&info, 0, sizeof(struct kinfo_proc)); name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_PID; name[3] = getpid(); if (!sysctl(name, 4, &info, &size, NULL, 0)) { return (info.kp_proc.p_flag & P_TRACED) ? 1 : 0; } return 0; }
在 App 发布时使用这两段代码能够有效阻止攻击者进行调试。iOS 的反调试功能应由项目组添加,不应由第三方模块提供。安全
### 禁止注入(已过期)iOS 下的注入大多数是经过环境变量 DYLD_INSERT_LIBRARIES
来实现,如 Cydia Substrate、Cycript 和 dumpdecrypted 等等。若是 App 的 Mach-O 文件中存在 函数Section(__RESTRICT/__restrict)
,那么在 App 启动时,dyld
会和忽略加载 DYLD_INSERT_LIBRARIES
环境变量指向的动态库。使得攻击者没法直接使用 dumpdecrypted
进行脱壳。
方法:在 xcode 的 指针Other Linker Flags
中添加参数 -Wl,-sectcreate,__RESTRICT,__restrict,/dev/null