gdb 调试 catchpoint

1. 让 catchpoint 只触发一次

使用 tcatch 命令设置 catchpoint 只触发一次。如下:tcatch fork

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// code
int main(void) {
pid_t pid;
int i = 0;
for (i = 0; i < 2; i++) {
pid = fork();
if (pid < 0) {
exit(1);
} else if (pid == 0) {
exit(0);
}
}
printf("hello world\n");
return 0;
}

// gdb 调试
(gdb) tcatch fork
Catchpoint 1 (fork)
(gdb) r
Starting program: /data/code/cpp/test/gdb_test/main

Temporary catchpoint 1 (forked process 30230), 0x00007ffff7ac67cc in __libc_fork () at ../sysdeps/nptl/fork.c:135
135 ../sysdeps/nptl/fork.c: No such file or directory.
(gdb) c
Continuing.
hello world
[Inferior 1 (process 30226) exited normally]

程序只在第一次调用 fork 时暂停

2. 设置 catchpoint

使用 catch 设置 catchpoint,比如:catch fork。每次调用 fork 都会暂停

3. 为系统调用设置 catchpoint

使用 catch syscall [name | number] 为系统调用设置 catchpoint。

比如:catch syscall mmap。或者也可以是系统调用的编号。

4. 通过为 ptrace 调用设置 catchpoint 破解 anti-debugging 的程序

1
2
3
4
5
6
7
8
9
10
11
#include <sys/ptrace.h>
#include <stdio.h>

int main() {
if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
printf("Gdb is debugging me, exit.\n");
return 1;
}
printf("No debugger, continuing\n");
return 0;
}

有些程序不想被 gdb 调试,就会在程序中调用 “ptrace” 函数,一旦返回失败,就证明程序正在被 gdb 等类似的程序追踪,就直接退出。

1
2
3
4
5
6
7
8
9
10
11
(gdb) start
Temporary breakpoint 1 at 0x68e: file main_01.cpp, line 5.
Starting program: /data/code/cpp/test/gdb_test/main

Temporary breakpoint 1, main () at main_01.cpp:5
5 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
(gdb) n
6 printf("Gdb is debugging me, exit.\n");
(gdb) n
Gdb is debugging me, exit.
7 return 1;

为了破解这种做法,可以为 ptrace 调用设置 catchpoint,通过修改 ptrace 的返回值,达到目的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(gdb) catch syscall ptrace
Catchpoint 1 (syscall 'ptrace' [101])
(gdb) r
Starting program: /data/code/cpp/test/gdb_test/main

Catchpoint 1 (call to syscall ptrace), 0x00007ffff7af961f in ptrace (request=PTRACE_TRACEME) at ../sysdeps/unix/sysv/linux/ptrace.c:45
45 ../sysdeps/unix/sysv/linux/ptrace.c: No such file or directory.
(gdb) c
Continuing.

Catchpoint 1 (returned from syscall ptrace), 0x00007ffff7af961f in ptrace (request=PTRACE_TRACEME) at ../sysdeps/unix/sysv/linux/ptrace.c:45
45 in ../sysdeps/unix/sysv/linux/ptrace.c
(gdb) return 0
Make ptrace return now? (y or n) y
#0 0x00005555555546ac in main () at main_01.cpp:5
5 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
(gdb) n
9 printf("No debugger, continuing\n");