在gdb

时间:2015-11-11 08:45:27

标签: c assembly gdb

如果程序使用ptrace来检测它是否在调试器中运行,我发现了以下技巧:

catch syscall ptrace
commands 1
set ($eax) = 0
continue
end

有人可以解释一下它是如何工作的吗?我试图在i r eax之后插入commands 1,但我不明白我得到的负面价值:

Catchpoint 1 (call to syscall ptrace), 0x00007ffff778af1e 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.
eax            0xffffffda   -38

Catchpoint 1 (returned from syscall ptrace), 0x00007ffff778af1e in ptrace (request=PTRACE_TRACEME) at ../sysdeps/unix/sysv/linux/ptrace.c:45
45  in ../sysdeps/unix/sysv/linux/ptrace.c
eax            0xffffffff   -1

1 个答案:

答案 0 :(得分:0)

ptrace系统调用允许一个进程跟踪另一个进程。我的猜测是你的应用程序(试图检测调试器)产生一个子进程(或者可能是线程),然后使用ptrace附加到这个子进程,就像调试器一样。

问题是只有一个进程可以跟踪另一个进程,如果第二个进程尝试附加ptrace,则第二个ptrace将失败,返回-1并设置{{1}到errno。如果您在调试器下运行,那么调试器将首先进入并附加EPERM,因此当应用程序本身尝试与ptrace连接时,此调用将失败。

因此,在您的示例中,当从syscall ptrace中的 return 触发catchpoint时,您可以看到ptrace设置为-1,表示系统调用失败(注册eax成立) x86-64上的返回值。

现在,如果您正在调试的应用程序中的代码不是很好,并且只检查eax是否返回成功,那么强制ptrace的值为0(其中0表示eax成功可能足以欺骗应用程序认为它没有在调试器下运行。

显然,可以在应用程序中编写更复杂的代码,以便更广泛地使用ptrace,这样就可以更难(尽管不是不可能)来解决这个问题检测