(linux) 如何调试“调试器”?

逆向工程 数据库 反调试
2021-06-29 11:14:36

我试图理解一个程序。该程序实现了一种反调试技术。

据我目前所知,父亲ptrace是一个分叉的过程。

一个孩子会做这样的事情:

some code
Int 3
some code
Int 3
some code
Int 3

等等

我认为父亲实现了一种调试器,因为strace -i我看到了很多:

[77b7457c] waitpid(2468, [{WIFSTOPPED(s) && WSTOPSIG(s) == SIGTRAP}], __WALL) = 2468
[77b7457c] --- SIGCHLD (Child exited) @ 0 (0) ---
[77baf52c] ptrace(PTRACE_GETREGS, 2468, 0, 0x7fb68be4) = 0
[77baf52c] ptrace(PTRACE_SETREGS, 2468, 0, 0x7fb68be4) = 0
[77baf52c] ptrace(PTRACE_CONT, 2468, 0, SIG_0) = 0

它让我想起了这个文档http://www.alexonlinux.com/how-debugger-works在这里我们发现了相同的想法:一个子进程,发送 TRAP,通过 ptrace 调用被父进程捕获,将寄存器设置为正确的值,然后继续。

我现在的问题:如何调试这个“调试器”?

  • 如果我绕过 ptrace,孩子将得到它的 SIGTRAP 并停止。
  • 如果我离开 ptrace,我就不能使用 gdb
  • 如果我绕过 ptrace 并使用 gdb with set follow-fork-mode child,我将无法跟踪在父进程中捕获陷阱的方式和位置,因为 gdb 处理它。如果我发送signal SIGTRAP父亲检测到它(如何?这是我想了解的一件事)并终止。

我知道gdb不能同时跟随父子,那么有没有办法调试这个程序?

2个回答

您可以中断 ptrace,绕过它,设置它的返回值,就好像它被成功调用一样,使用两个 GDB 实例:一个用于孩子,一个用于父亲。

这个二进制文件受到一种叫做“纳米”的技术的保护。

父亲通过调试调用(linux下的ptrace,windows下的DebugActiveProcess)获取和设置其寄存器来驱动孩子。这是一种有效的反调试方法。

这是挑战的一部分,你可以在这篇文章中找到很多细节:http : //doar-e.github.io/blog/2014/10/11/taiming-a-wild-nanomite-protected-mips-二进制带符号执行无此类破解/