在 Linux 可执行文件中跟踪字节的执行

逆向工程 二元分析 可执行 二进制 调用图
2021-06-19 12:17:22

给定一个二进制可执行文件(在这种情况下,一个编译的 C 文件可以找到 2 个数字的 gcd),是否有一个工具可以分析该文件的执行情况并可以生成该执行的某种调用图,特别是指令/字节被调用/访问(即该文件中指令/字节的位置列表)?

我知道ltracestrace工具分别跟踪库和系统调用,但我要求的是具体位于文件本身中的字节。

我尝试使用perf对 PC 进行采样,但我没有找到将其采样限制为文件本身或让它自己跟踪确切字节的方法。我还发现对于这么短的程序,它的采样速度不够快。oprofile似乎有类似的问题。

我使用 radare2生成可执行文件的调用图,但它创建了完整的调用图并且独立于任何参数/执行,也没有给出指令的确切位置。

我想用这个工具来比较两个二进制文件的执行,即显示 ./gcd 5 10 和 ./gcd 128 24 之间的执行差异

有这样的工具吗?

2个回答

看来您需要的是指令跟踪器来自英特尔的 PIN 是允许您制作跟踪工具的框架的一个示例。它使用动态二进制检测来实现合理的速度,您可以使用库附带的示例之一,只需很少或无需修改。许多调试器还支持指令跟踪记录(通常通过软件步进每条指令,这很慢但通常可靠)。有些甚至可能支持差异调试,它记录多次执行并显示它们之间的差异。

如果您有最新的 Intel CPU,则可以利用Intel 处理器跟踪 (PT)perf.

正如@IgorSkochinsky建议的那样,您可以使用动态二进制检测 (DBI)。

PIN 的一种替代方法是DynamoRIO

$ ./drbuild.sh  # build script (below)
$ gcc gcd.c -o gcd

# run one
$ $ ./dynamorio/build/bin32/drrun -t drcov -dump_text -- ./gcd 5 10
5

$ ls  # so we know which log is from our first run
drbuild.sh  drcov.gcd.18958.0000.proc.log  dynamorio  gcd  gcd.c

# run two
$ $ ./dynamorio/build/bin32/drrun -t drcov -dump_text -- ./gcd 128 24
8

现在我们已经用drbuild.sh、编译gcd.c、运行gcd和生成drcov.gcd.18958.0000.proc.log构建了 DynamoRIO drcov.gcd.18960.0000.proc.log,我们可以比较运行一 (2177) 和运行二 (2183) 的日志之间的“BB 表”字段,以立即看到更多基本块(计算重复性)由于while()in gcd_iter().

基本块按模块分组,并通过它们在该模块中的偏移量来标识。例如,module 0包含gcd二进制中的所有基本块包含的行module[ 0]: 0x0000043b表示module 0 start (0x08048000) + 0x0000043b遇到了基本块 at 这个 cfg,我们可以看到这0x0804843bgcd_iter()函数中的第一个基本块

如果 to 的第一个参数gcd_iter()是否定的,则执行将通过 to 0x08048444,从而否定该参数;否则,我们跳转到0x8048447前两次运行的日志(所有参数均为正)与此预期一致。

$ grep -F 'module[  0]:' drcov.gcd.18958.0000.proc.log
...
module[  0]: 0x0000043b,   9
module[  0]: 0x00000447,   6
...

gcd使用否定的第一个参数运行显示 DynamoRIO 的输出是如何动态的。

$ ./dynamorio/build/bin32/drrun -t drcov -dump_text -- ./gcd -5 10
$ grep -F 'module[  0]:' drcov.gcd.18970.0000.proc.log
...
module[  0]: 0x0000043b,   9
module[  0]: 0x00000444,   9
...