25

我之前曾多次听说过“反编译”这个词,我开始对它的工作原理非常好奇。

我对它的工作原理有一个非常大致的了解;对应用程序进行逆向工程以查看它使用了哪些功能,但除此之外我不知道太多。

我也听说过“反汇编器”这个词,反汇编器和反编译器有什么区别?

所以总结一下我的问题:反编译过程到底涉及什么?通常是怎么做的?一个过程有多复杂/简单?它可以产生确切的代码吗?反编译器和反汇编器有什么区别?

4

2 回答 2

26

Hex-Rays Decompiler的作者 Ilfak Guilfanov在某个骗局中就他的反编译器的内部工作发表了演讲,这里是白皮书演示文稿。这很好地概述了构建反编译器的所有困难以及如何使其全部工作。

除此之外,还有一些相当古老的论文,例如Cristina Cifuentes 的经典博士论文

至于复杂性,所有“反编译”的东西都取决于二进制文件的语言和运行时。例如,反编译 .NET 和 Java 被认为是“完成”,因为有可用的免费反编译器,具有非常高的成功率(它们产生原始源)。但这是由这些运行时使用的虚拟机的特殊性质引起的。

至于真正的编译语言,如 C、C++、Obj-C、Delphi、Pascal,......任务变得更加复杂。详细阅读上述论文。

反汇编器和反编译器有什么区别?

当您有一个二进制程序(可执行文件、DLL 库等)时,它由处理器指令组成。这些指令的语言称为汇编(或汇编程序)。在二进制文件中,这些指令是二进制编码的,因此处理器可以直接执行它们。反汇编程序获取此二进制代码并将其转换为文本表示形式。这种翻译通常是一对一的,这意味着一条指令显示为一行文本。这个任务很复杂,但很简单,程序只需要知道所有不同的指令以及它们在二进制文件中的表示方式。

另一方面,反编译器的任务要困难得多。它采用二进制代码或反汇编程序输出(基本相同,因为它是一对一的)并生成高级代码。让我给你看一个例子。假设我们有这个 C 函数:

int twotimes(int a) {
    return a * 2;
}

当你编译它时,编译器首先为该函数生成一个汇编文件,它可能看起来像这样:

_twotimes:
    SHL EAX, 1
    RET

(第一行只是一个标签而不是真正的指令,SHL执行左移操作,快速乘以 2,RET表示函数完成)。在结果二进制文件中,它看起来像这样:

08 6A CF 45 37 1A

(我编的,不是真正的二进制指令)。现在您知道了,反汇编程序将您从二进制形式带到汇编形式。反编译器将您从汇编形式带到 C 代码(或其他一些高级语言)。

于 2012-04-25T07:43:38.967 回答
4

反编译本质上是编译的逆过程。也就是说 - 获取目标代码(二进制)并尝试从中重新创建源代码。

反编译取决于留在目标代码中的人工制品,这些人工制品可用于确定源代码的结构。

使用 C/C++ 并没有太多可以帮助反编译过程的东西,因此非常困难。然而,使用 Java 和 C# 以及其他以虚拟机为目标的语言,反编译会更容易,因为该语言在目标代码中留下了更多提示。

于 2012-04-25T07:32:07.323 回答