Linux 系统gdb等调试器,都是通过ptrace系统调用实现。Android加固中,ptrace自身防止调试器附加是一种常用的反调试手段。
调试时一般需要手工在ptrace处下断点,通过修改ptrace返回值过掉反调试。下面提供另一种思路,降低手工操作复杂度:
测试代码(反调试程序):
#include <stdio.h> #include <stdlib.h> #include <sys/ptrace.h> void a() { if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1) { printf("don't trace me !!\n"); exit(1); } // normal execution puts("hello girl."); } int main() { a(); return 0; }
编写辅助库:
/* Type of the REQUEST argument to `ptrace.' */ enum __ptrace_request { PTRACE_TRACEME = 0, #define PT_TRACE_ME PTRACE_TRACEME }; long ptrace(enum __ptrace_request request, unsigned long pid, void *addr, void *data) { return 0; }
gcc -shared -fPIC helper.c -o helper.so 编译动态库。
设置环境变量:
export LD_PRELOAD=$PWD/helper.so
测试:
(gdb) r Starting program: /home/kiiim/lab/a.out hello girl. During startup program exited normally.
以上,将helper.so放到APP的libs目录,并设置LD_PRELOAD环境变量,即可绕过所有ptrace的反调试。
也可以patch一些其它函数,如open函数我们需要patch后不影响其正常功能:
#define _GNU_SOURCE #include <dlfcn.h> typedef int (*_open)(const char *pathname, int flags); int open(const char *pathname, int flags, ...) { /* Some evil injected code goes here. */ _open fake_open; fake_open = (_open)dlsym(RTLD_NEXT,"open"); return fake_open(pathname,flags); }