FreeBSD上的gdb和follow-fork-mode child

逆向工程 数据库 开发 调试 多进程
2021-06-15 09:11:10

很久以前我注意到使用

设置follow-fork-mode child

在 FreeBSD 上的 GDB 中实际上不起作用。在各种夺旗比赛中遇到一些挑战时,经常会出现此问题。例如,服务器将产生一个处理连接的子进程。子代码有一个我想调试的漏洞,但 gdb 只是从不跟踪子代码的执行,我无法真正观察到被触发的漏洞。

到目前为止,我已经通过两种方式解决了这个问题:

  1. 建立连接,等待子节点生成,然后将 GDB 附加到它。

    这是有效的,因为生成的孩子有它自己的 PID,我可以附加到它,但相当痛苦,因为首先我必须从一个会话建立连接,在另一个会话中附加 GDB,然后发送有效负载/继续连接第一个.

  2. 在 fork 调用之后修补二进制文件以在父进程而不是子进程中继续执行。

    这也很痛苦,因为我必须重新启动整个父进程才能创建另一个调试会话。

还有一些其他技巧可以使用,但这些足以说明我的观点。

现在我知道 FreeBSD 过去在这方面有一些限制,但有什么改进吗?

有没有办法修补 GDB 以添加此功能?有没有关于更简单的方法来克服这个问题的建议?

2个回答

如果您想要父级和子级,请尝试在 fork 上设置一个捕获点。

set-follow-fork-mode ask 
catch fork 

关于你的第二点,我的.gdbinit(我相信最终源自 Tavis Ormandy)中有这个宏它在许多情况下都非常有用,包括您自己的情况。

define assemble
 # dont enter routine again if user hits enter
 dont-repeat
 if ($argc)
  if (*$arg0 = *$arg0)
    # check if we have a valid address by dereferencing it,
    # if we havnt, this will cause the routine to exit.
  end
  printf "Instructions will be written to %#x.\n", $arg0
 else
  printf "Instructions will be written to stdout.\n"
 end
 printf "Type instructions, one per line.\n"
 printf "End with a line saying just \"end\".\n"
 if ($argc)
  # argument specified, assemble instructions into memory
  # at address specified.
  shell nasm -f bin -o /dev/stdout /dev/stdin \
    <<< "$( echo "BITS 32"; while read -ep '>' r && test "$r" != end; \
                do echo -E "$r"; done )" | hexdump -ve \
        '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' \
            > ~/.gdbassemble
  # load the file containing set instructions
  source ~/.gdbassemble
  # all done.
  shell rm -f ~/.gdbassemble
 else
  # no argument, assemble instructions to stdout
  shell nasm -f bin -o /dev/stdout /dev/stdin \
    <<< "$( echo "BITS 32"; while read -ep '>' r && test "$r" != end; \
                do echo -E "$r"; done )" | ndisasm -i -b32 /dev/stdin
 end
end
document assemble
Assemble instructions using nasm.
Type a line containing "end" to indicate the end.
If an address is specified, insert instructions at that address.
If no address is specified, assembled instructions are printed to stdout.
Use the pseudo instruction "org ADDR" to set the base address.
end

我对此进行了深入研究,并通过 mrduclaw 在 SO 上发现了这个问题(原始文章中的链接已失效,但网络档案中有它)。他和我有完全相同的问题,寻找解决方案的动机也完全相同。

因此,我进行了更多研究,结果发现 freebsd 直到最近才在其 ptrace 中支持 fork。提交了一个补丁,但我真的不知道它是否被应用。将尝试自己应用它,然后看看它是否会开始工作。