objective-c runtime安全措施之一:反调试
<<O'Reilly.Hacking.and.Securing.iOS.Applications>>读书笔记
反调试:检查是否有debugger在trace游戏进程 (预防动态调试进程)
方法1: 检查进程的状态是否为 P_TRACED
原理:当进程被调试的时候,内核自动设置进程选项为P_TRACED。因此可以通过检查该标记来确认是否被调试
例子1:check_debugger()
#include <unistd.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <string.h>
static int check_debugger( ) __attribute__((always_inline));
int check_debugger( )
{
size_t size = sizeof(struct kinfo_proc);
struct kinfo_proc info;
int ret, 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 (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;
}
【注意】
1. 为了让程序以inline方式编译,需要设置编译器的优化选项,-0z(函数以inline方式编译),-fast(加快编译速度)
2. 为了避免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( ) {
ptrace(PT_DENY_ATTACH, 0, 0, 0);
...
}
iOS系统中
int main( ) {
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函数会提高应用的安全性
作者 danqingd
补充:综合编程 , 安全编程 ,