如何使用 Python gdb 获得完整的执行跟踪?

逆向工程 拆卸 数据库
2021-07-05 11:13:31

在尝试回答另一个问题时,我尝试设置一个 Python 脚本来自动提取程序集执行跟踪。但是,我真的对这个脚本不满意,我想知道如何改进它。

首先,这是脚本:

import gdb

gdb.execute('break main')
gdb.execute('run')

while (True):
    gdb.write (gdb.execute('x /i $pc', to_string=True).rstrip('\n'), gdb.STDOUT)
    gdb.execute('stepi', to_string=False)
    gdb.flush ()

然后,只需执行:

$> gdb -x ./script.py ./main 1> log.txt

我想解决的问题如下:

  • 首先,while(True)肯定是不尽如人意的。当达到断点或退出时,我想停止或暂停循环。

  • 此外,我们将指令列表导出到外部的gdb方式也不是很令人满意。将其保存到文件比必须重定向stdout到文件要好得多

  • 最后,能够与软件进行交互,通过它来馈送stdin也是我们想要的。

因此,如果您知道如何以任何方式改进此脚本,我会很感兴趣。

1个回答

您的问题似乎真的是“如何使用 GDB 获取指令跟踪”。使用Python的似乎是偶然的,除非你正在使用PythonGDB的。

GDB 通过record命令具有对指令跟踪的本机支持使用该命令record full将记录对进程状态的所有更改,甚至允许反向调试(即向后步进和重放)。

您可以在此处找到更多信息:https : //sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html

另外,如果您使用 Python-inside-GDB 执行单步执行和指令跟踪,最好的办法是使用Breakpoint该类并使用internal不会停止 UI 的断点。在具有可变宽度指令(i386、amd64)的体系结构上,您需要计算当前指令的大小。您还需要解析所有跳转和调用目标。

如果您查看 GDB 源代码,您将看到这一切在事件循环中是如何工作的,并且它没有暴露给 Python API。搜索STEP_OVER_NONE哪个用于stepi指令(步骤正好是一条机器指令)。

如果您愿意,可以在 GDB 中使用gdb.Breakpointgdb.FinishBreakpoint类型执行此操作但是,您最终需要解析指令宽度(在 x86 等可变宽度指令 ISA 上),并提取跳转和调用目标。GDB 的 Python API 不支持单步断点,也不支持解析下一条指令地址。您可以使用 Capstone 和 Unicorn 轻松完成这两件事。