控制流图重构项目

逆向工程 拆卸 二元分析 静态分析 控制流图
2021-06-16 04:49:22

我正在寻找从二进制文件提供重建控制流图同时支持多个平台(例如 x86、x64、arm)的项目。例如,考虑这个简短的汇编程序:

.global main
.intel_syntax noprefix

.extern getchar
.extern printf

.section .data
jmpTable:
    .long _stub0
    .long _stub1
    .long _stub2
fmt: .asciz "%x\n"


.section .text

main:
    call getchar
    mov dl, 4
    imul dl
    add eax, offset jmpTable
    jmp [eax]
    .long 3851
_stub0:
    mov eax, 0
    jmp end
    .long 3851
_stub1:
    mov eax, 1
    jmp end
    .long 3851
_stub2:
    mov eax, 2
    jmp end
    .long 3851
end:
    push eax
    push offset fmt
    call printf
    add esp, 8
    ret

我考虑过的项目:

  • IDA(迄今为止最好的,提取痛苦)
  • BARF(天真、有限的方法)
  • Angr(容易中断或永远计算)
  • Radare2(是否有任何api可以导出cfg数据?)
  • JakStab(仅限于 x86)

相当明显的选择,不过,导出一个过程间 CFG 仍然很痛苦。此外,虽然它能够找到此示例的所有基本块,但它会遗漏所有间接边。

这些项目应该提供一些 API 来提供 cfg。我知道仅用静态分析解决这个问题可能是不可行的。我正在寻找一种尽力而为的方法。

4个回答

使用radare2提取JSON中的控制流图:

$> python
import r2pipe
r2 = r2pipe.open("/bin/ls")
r2.cmd("aaa") # See radare.today/posts/analysis-by-default/
cfg = r2.cmdj("agj")

https://github.com/radare/radare2-bindings/tree/master/r2pipe/python

目前,实践中最有效的方法似乎遵循符号执行原则这种技术最初是为了根据给定的源代码自动构建一组测试用例而开发的,最近已在二进制分析中使用,以发现和(部分)恢复分析的二进制程序的 CFG。

大多数时候,如果要处理多种汇编语言,则需要对程序使用中间表示。目前,已经有很多这样的通用模型,但没有一个真正获得了超越其他模型的优势。然而,最受欢迎的似乎是 LLVM 的中间表示(许多工具都使用它),第二受欢迎的似乎是 VEX,Valgrind 中使用的中间表示(如 Angr 中使用的)。QEMU 或 RREIL 语言也可能是一种选择,但它们不太常用。但是,大多数项目都有自己的中间表示。

那么,构建一个基于符号执行的CFG-recovery程序需要以下模块:

  • 加载器:该模块负责获取您的二进制程序(它可能是可执行文件或库)并模拟本机加载器的工作,以构建加载过程完成后所获得内容的真实内存映像。

  • 解码器:该模块负责将在象征性地执行程序时找到的本地程序集翻译成您自己的中间表示。这是一段相当冗长(而且痛苦)的代码来实现!因此,在这样做时要准备好受苦。

  • 符号执行引擎:通常基于使用逻辑 QF_AUFBV (Quantifier Free / Arrays / Uninterpreted Function / Bitvectors) 的 SMT 求解器,如果你天真地编码,符号执行引擎真的会成为性能瓶颈,因为 CFG 的恢复将使用它很多。在这里,拥有一个好的公式简化(或切片)模块才是真正的关键。

除了这三个模块之外,您还可以通过添加更高级的分析来改进您的工具,并开始编写一个抽象的解释框架,该框架可以添加到您的中间表示之上,只是为了有机会揭开 CFG 的某些无法实现的部分只是通过 SMT 求解器的强大功能发现的。

此外,性能确实是使您的工具真正可用的关键。因此,能够捕获变量的确切范围或检测二进制代码中的函数或模块/对象的能力有助于减少您必须立即考虑的代码的大小。

现在,我可以给你很多关于这个主题的指导和文章,但我缺乏一点时间。稍后我可能会回来写一个广泛的列表,但希望上面已经给出了总体思路。希望这可以帮助你。

Angr(容易中断或永远计算)

如果您仍然对寻找解决方案感兴趣,您可能想再试一次 angr。您应该跳上我们的 slack 频道(angr.slack.com,请从http://angr.io获得邀请),以便我们可以一起解决任何 CFG 恢复问题。

我相信 angr 为您提供了您提到的所有解决方案中最好的灵活性,而无需陷入符号执行地狱。

免责声明:我是 angr 的核心开发者。

我认为Radare2的'agj'命令只提取函数调用图,这与CFG(节点代表基本块的控制流图)不同。