反调试:检查是否有debugger在trace进程 (预防动态调试进程)
方法1: 检查进程的状态是否为 P_TRACED
原理:当进程被调试的时候,内核自动设置进程选项为P_TRACED。因此可以通过检查该标记来确认是否被调试
#include <unistd.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <string.h>
staticint check_debugger()__attribute__((always_inline));
int check_debugger()
{
size_t size = sizeof(structkinfo_proc);
struct kinfo_proc info;
int ret, name[4];
memset(&info, 0,sizeof(structkinfo_proc));
name[0] =CTL_KERN;
name[1] =KERN_PROC;
name[2] =KERN_PROC_PID;
name[3] =getpid();
if ((ret = sysctl(name,4, &info, &size, NULL,0))) {
return ret;/* sysctl() failed for some reason */
}
return (info.kp_proc.p_flag &P_TRACED) ? 1 :0;
}
【注意】
为了避免sysctl被替换,需要在调用该函数前验证其完整性(在思路二中会介绍如何验证sysctl函数完整性)
--------------------------------------------------------------------------------------------------------------------------------------------------
方法2:调用ptrace请求来检查进程是否被调试
原理,调用ptrace请求的PT_DENY_ATTACH方法。使用该方法后,下面两种情况都会导致调试器崩溃,应用退出。
(1)如果应用使用调试器来运行,调试器会崩溃;(下面以调试iTunes为例)
$ gdb -q /Applications/iTunes.app/Contents/MacOS/iTunes
Reading symbols for shared libraries .................................... done
(gdb) r
Starting program: /Applications/iTunes.app/Contents/MacOS/iTunes
Reading symbols for shared libraries ++++++++++++++++++++++++++++++....++++
+....................................................................................
............................................................... done
Program exited with code 055.
(gdb)
(2)如果应用运行中,使用调试器,调试器也会崩溃。
$ gdb -q -p 3933
Attaching to process 3933.
Segmentation fault: 11
Mac OS X系统中
#include<sys/ptrace.h>
int main(int argc,char *argv[])
{
ptrace(PT_DENY_ATTACH,0, 0,0);
@autoreleasepool {
returnUIApplicationMain(argc, argv, nil,NSStringFromClass([AppDelegateclass]));
}
}
iOS系统中
int main(int argc,char *argv[])
{
ptrace(31,0, 0,0); //因为PT_DENY_ATTACH只存在于iOS模拟器头文件中,所以用31来代替
...
}
【注意】
1. ptrace方法可以通过打断点的方法绕过,如下所示:
# gdb ?1 ./main
Reading symbols for shared libraries . done
(gdb) b ptrace
Function "ptrace" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (ptrace) pending.
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>return
>continue
>end
(gdb) run
Starting program: /private/var/root/main
Reading symbols for shared libraries .............................. done
Breakpoint 1 at 0x342afa98
Pending breakpoint 1 - "ptrace" resolved
Breakpoint 1, 0x342afa98 in ptrace ()
I'm doing something really secure here!!
2.由于可能被攻击者绕过该方法的调用,在应用的多处增加ptrace函数会提高应用的安全性