初步意见:
反编译
1. 重要的是能够引用反编译的正确定义,以便对它的含义有所了解
如前所述,与“反编译”标签相关的定义是不正确的。这里是:
用结构化编程语言(如 C)翻译从二进制文件中提取的汇编代码的过程。
我们可以将此定义与学术文献中提供的正确定义进行比较:
反编译器是一种程序,它读取用机器语言(源语言)编写的程序,并将其翻译成用高级语言(目标语言)编写的等效程序。反编译器或反向编译器试图逆转编译器将高级语言程序翻译成二进制或可执行程序的过程。1
更直接:
从表面上看,反编译是仅在给定二进制文件的情况下恢复程序的源代码。在下面,反编译由一系列抽象恢复机制组成,例如间接跳转解析、控制流结构化和数据类型重建,这些机制恢复了二进制形式不容易获得的高级抽象。2
可以根据正确的定义做出某些推论:
- 反编译器的输入应该是目标代码,而不是 ASCII 文本或通过助记符的目标代码再现。错误地建议汇编代码(机器代码的符号语言表示)是预期的输入是一个严重的概念错误。这就是需要更改标签定义的原因,因为此错误可能会导致混淆或误解
- 反编译的目的是通过二进制编码的操作的高级语言作为目标代码创建语义近似。为了创建一个可接受的准确度的近似值,需要使用多种方法来补偿编译过程中发生的信息丢失。换句话说,关于抽象恢复的原则越少,反编译的源文本作为编码二进制目标代码的信息的近似值就越不准确
2. 反编译使用中间表示而不是汇编语言文本来创建 HLL 输出
以下是大致涉及的内容:
另一个例子:
控制流图恢复 第一阶段解析输入二进制文件的文件格式,反汇编二进制文件,并为每个函数创建一个控制流图 (CFG)。在高层次上,控制流图是一种程序表示,其中顶点表示基本块,边表示块之间可能的控制流转换。(有关更多详细信息,请参见第 2.1 节。)虽然在可执行文件中精确识别二进制代码是已知的在一般情况下很难,当前的算法已被证明在实践中运行良好 [4, 5, 24, 25]。已经有成熟的平台实现了这一步。我们使用 CMU 二进制分析平台 (BAP) [10]。BAP 将 CFG 中的顺序 x86 汇编指令提升为一种称为 BIL 的中间语言,其语法如表 1 所示(参见 [10])。正如我们将看到的,2
CMU 的 Phoenix 反编译器所采取的步骤顺序与 Cristina Cifuentes 的“反向编译技术”(她的反编译器名为dcc)的图表中描绘的顺序略有不同:Phoenix 为二进制文件创建了一个 CFG,然后将其转换为中间文件语言,而不是相反。
另一个例子,来自No More Goto: Decompilation Using Pattern-Independent Control-Flow Structuring and Semantics-Preserving Transformations:
从第一句话可以明显看出,DREAM 的输入是二进制的。与 Phoenix 使用BAP 中间语言作为中间表示不同,DREAM 使用自己未指定的中间表示形式。
最后一个例子——基于Decompilers 和白皮书之外对 Hex-Rays 反编译器的过时讨论,一般的反编译过程如下所示:
- 微码生成
- 局部优化
- 全局优化
- 局部变量分配
- 结构分析
- 初始伪代码
- 伪代码转换
- 类型分析
简而言之,Hex-Rays 反编译器将目标代码从二进制转换为微代码,创建 CFG,使用 CFG 创建伪代码(一些未指定的,可能是专有的,中间表示),然后输出转换后的伪代码。
当检查这些不同的反编译器时,会出现一些清晰的模式。
编译器和反编译器都使用中间表示作为翻译过程的一部分有几个很好的理由。主要原因是 IR 可以独立于语言和体系结构,同时保留以源语言编码的信息。IR 的这一方面完全消除了对通用汇编语言到伪代码转换器的等效物的需要。CFG 到 IR 的二进制方法非常优越且成熟。
来源:普林斯顿 CS320 中级表示讲义
对各种评论的回应
看来我需要的是基本DREAM反编译算法的实现;我无法找到将文本格式的 CFG 作为输入的简单实现。
不存在这样的实现。如前所述,DREAM 从二进制文件中包含的解析目标代码构建 CFG。
我已经有了自己的反汇编程序。使用以二进制作为输入的工具将是一种浪费。
将目标代码作为输入并生成汇编语言 ASCII 文本作为输出的工具与反编译无关。重新发明轮子将是一种浪费。顺便说一下,所有上述反编译器都将二进制文件作为输入。
我的观点是重构控制流结构实际上独立于架构。我可以将输入提高一步:如果有一个由“if (condition) goto”和“goto”连接的不透明基本块的图形,则应该可以恢复原始的 if-then-else 语句和循环,并且一个可以做到这一点的工具不需要任何反汇编能力
CFG 是通过目标代码分析生成的,以便尽可能多地保留信息。更多保留的信息=更准确的反编译。目标代码格式直接取决于体系结构。
1.反向编译技术
2.使用语义保留结构分析和迭代控制流结构的原生 x86 反编译