反编译是如何进行的?

问题描述 投票:0回答:3

我之前曾多次听说过“反编译”这个词,我开始很好奇它是如何工作的。

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

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

总结一下我的问题:反编译过程到底涉及什么?通常是如何完成的?过程有多复杂/容易?它能产生准确的代码吗?反编译器和反汇编器有什么区别?

decompiling
3个回答
31
投票

Ilfak Guilfanov,Hex-Rays Decompiler的作者,在一次会议上发表了关于他的反编译器的内部工作原理的演讲,这里是白皮书演示文稿。这很好地概述了构建反编译器的所有困难以及如何使其全部正常工作。

除此之外,还有一些相当古老的论文,例如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代码(或其他高级语言)。


6
投票

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

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


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.