前言
逆向某app时,想用frida进行hook分析其执行流程,遇到了frida的反调试。这里记录一下出现问题的情况和反调试的实现.
环境
Android8
frida12.11.18
windows10
frida 注入
使用frida -U注入app
frida -U com.shark.tracerpidapp
结果如下
____
/ _ | Frida 12.11.18 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://www.frida.re/docs/home/
Failed to spawn: ambiguous name; it matches: com.shark.tracerpidapp (pid: 9802), com.shark.tracerpidapp (pid: 9847)
这里有两个com.shark.tracerpidapp名称的进程
我们直接进入adb查看进程
sailfish:/ # ps -A | grep com.shark
u0_a129 9802 671 2251940 73376 SyS_epoll_wait 72493ca5d0 S com.shark.tracerpidapp
u0_a129 9847 9802 2231280 34092 hrtimer_nanosleep 72493cafd8 S com.shark.tracerpidapp
可以看到确实有两个进程,frida分不清你要注入哪个进程所以报出如上错误。
我们选择父进程进行注入
(venv) D:\FridaTest>frida -U 9802
____
/ _ | Frida 12.11.18 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://www.frida.re/docs/home/
Failed to attach: unable to access process with pid 9802 due to system restrictions; try `sudo sysctl kernel.yama.ptrace_scope=0`, or run Frida as root
叫我们用root去执行,这里是没有用的。我们到adb看看这个父进程的TracerPid信息就知道了
至于为什么看TracerPid请移步文章TracerPid反调试
sailfish:/ # cat /proc/9802/status | grep TracerPid
TracerPid: 9847
可以看到父进程已经被子进程ATTACH,而frida也依赖于ptrace所以这里肯定注入不进去
解决方案
我们不要让frida注入,而是使用frida启动app,使用-f选项,我们告诉Frida注入Zygote并开始启动应用程序
(venv) D:\FridaTest>frida -U -f com.shark.tracerpidapp
____
/ _ | Frida 12.11.18 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://www.frida.re/docs/home/
Spawned `com.shark.tracerpidapp`. Use %resume to let the main thread start executing!
[Pixel::com.shark.tracerpidapp]-> %resume
还有一种打补丁的方式,在下面参考中有。这里就不再赘述。
反调试实现原理
这个反调试其实就是用了TracerPid反调试的原理,但是在这里有一些不一样。
1:这里是子进程ATTACH父进程
2:在Android8中ptrace(PTRACE_TRACEME, 0, 0, 0); 虽然返回的不是-1但是无法成功
PTRACE_ATTACH
所以我们这里要使用ptrace(PTRACE_ATTACH, parent, 0, 0)来实现。
PTRACE_ATTACH参数
ptrace(PTRACE_ATTACH,pid)
跟踪指定pid 进程。pid表示被跟踪进程。被跟踪进程将成为当前进程的子进程,并进入中止状态
PTRACE_CONT参数
ptrace(PTRACE_CONT, pid, 0, signal)
继续执行。pid表示被跟踪的子进程,signal为0则忽略引起调试进程中止的信号,若不为0则继续处理信号signal
先使用PTRACE_ATTACH进行附加,这时候被附加进程会阻塞。再使用PTRACE_CONT继续执行被附加的进程。为了确保PTRACE_CONT能被执行我们在PTRACE_ATTACH完后要马上wait阻塞当前线程。当附加成功后wait阻塞解除就能执行到PTRACE_CONT了
代码
void readStatus() {
FILE *fd;
char filename[128];
char line[128];
pid_t pid = syscall(__NR_getpid);
LOGI("PID : %d", pid);
sprintf(filename, "/proc/%d/status", pid);//读取/proc/pid/status中的TracerPid
pid_t ppid = fork();
if (ppid == 0) {
pid_t parent = getppid();
//parent是被跟踪的进程 异步操作
int pt = ptrace(PTRACE_ATTACH, parent, 0, 0);
int status = 0;
// ATTACH成功前停下 为了保证下面的PTRACE_CONT操作能够执行到 这样被ATTACH的进程就不会一直进入中止状态
wait(NULL);
//让被调试的进程重新恢复运行
if (ptrace(PTRACE_CONT, parent, NULL, 0) < 0) {
perror("ptrace_cont");
return;
}
if (pt == -1)
exit(0);
while (1) {
sleep(CHECK_TIME);
}
} else {
LOGE("fork error");
}
}