我知道从二进制到源代码(例如C ++)的反向工程通常被认为是困难的或不可能的,但是有没有计算机科学家实际上“数学上”证明了不可能(或有可能)将(任何)二进制反向工程到源代码?反向工程是一个非常棘手的难题,还是那里的二进制文件根本无法通过手工还是通过反编译器进行反向?

注意:我知道答案可能是“这取决于平台和编程”语言”,因此我将假定使用的语言是C ++,因为通常认为它是无法反转的。

评论

总是有可能反转任何二进制文件,因为处理器最终必须理解并执行它。如果处理器可以,为什么不呢? (假设您有无限时间可支配)

绝对不认为不可能反转C ++二进制文件。

反向C ++应用程序绝对不是不可能。

#1 楼

实际上,答案有些微妙。

根据Barak等人的说法,混淆程序是不可能的。这意味着您将始终泄漏足够的信息,使攻击者可以重新构建程序的蓝图。作为输入(它来自赖斯定理,因为混淆过去是建立在程序中可以发现的非平凡属性上的)。

因此,最终不可能实现完美的混淆,但是完全自动化也不可行。这意味着人类(和直觉)是并且将继续是本科学的关键。

评论


“构建一个可以自动对任何程序进行反向工程的程序也是不可能的”您能否详细说明一下,或者至少可以向我指出正确的方向?谢谢!

–viv
2014年1月9日15:43



@viv,您可能会想像我们有一个“(A)uto(r)反向(E)ngineer”作为程序ArE,以便给定任何程序P作为ArE的输入,那么ArE将回答(即,反向)P是否是否具有一些非平凡的性质p。赖斯定理说,这种ArE在算法上不存在。

– Ta Thanh Dinh
2014年1月9日在18:28



@viv:tathanhdinh写了一个很好的解释,我只能建议您看一下赖斯定理。非平凡的属性可以是CFG的提取,变量类型的重构等。

–恐怖
2014年1月9日在23:23

无效链接。 -------

–user202729
18-09-30在16:07

#2 楼

似乎不同的答案对应于对该问题的不同解释。 C ++编译器从源代码创建二进制文件。 C ++反编译器将从二进制文件创建源代码。

通常,不可能重新创建源(注释,宏定义和局部变量名称,例如,最终二进制文件中通常不存在任何形式),因此

这样做的一种简单方法是逐条指令分解可执行二进制文件,为每条机器指令创建C ++等效代码。从字面上看,这样做是可行的,但是对于人类来说,结果将是完全无法使用的。请参阅Chen等人最近发表的题为“精巧的反编译器以生成具有高可读性的C代码”的论文。描述了反编译的目标和挑战。

评论


Afaik已经将此功能等效的源代码用于很多事情,例如在不同的体系结构/ OS上进行重新编译,或者以明显的二进制修改或挂接会更加困难的方式进行调试/修改其功能会更加容易。 。

–peterh-恢复莫妮卡
2015年9月13日在2:33



#3 楼

正如其他人所说,您总是可以编写模拟机器代码的C代码。但是,这并不总是有用的。通常,您不仅要学习如何运行程序的知识,还想了解如何以有用的方式对其进行修改。

研究人员仍在尝试弄清混淆的哪些定义是有用的。这篇著名的论文说,您不能一直隐藏所有秘密。他们将“秘密”定义为通过反复运行程序并分析输出无法获得的任何东西。最近的这篇论文演示了一种方法,该方法使得无法分辨出哪个等效源代码是原始源代码。他们的技术是“最大可能的”混淆,因为它隐藏了任何可以隐藏的秘密。

最早的成功混淆之一是针对点函数,当您键入一个点时,输出“是”。秘密密码。您可以通过编码密码的MD5哈希来混淆该程序(就像Unix登录功能一样)。您可以运行该程序,但不能破解密码。那算不算是“不可能逆转”的?

一段时间以来,人们已经知道软件静态分析的某些方面在形式上很难。例如,请参阅本文及其参考资料。

我不知道有任何专门研究以特定的可预测方式很难修改程序行为的研究。那会很有趣。

评论


@SteveMitchell,您好,欢迎来到reverseengineering.SE!您还可以使用Markdown将到您的源的链接内联。可以在此处找到有关该主题的帮助。您也可以使用编辑字段顶部的按钮。但是,我自己编辑帖子时遇到了一些奇怪问题,因此可能存在某种普遍性问题。

– 0xC0000022L♦
2014年1月10日,0:18



哦,没关系。刚刚注意到,由于信誉限制较低,您可能故意使链接无效以完全获得它们吗?

– 0xC0000022L♦
2014年1月10日,0:24

我会为此获得徽章吗?感谢您修复它们。

–史蒂夫·米切尔(Steve Mitchell)
2014年1月10日,0:47

我想不是,但这可能是合适的;)

– 0xC0000022L♦
2014年1月10日13:00

#4 楼

如果任何二进制意味着任意的二进制数据文件,那么答案是肯定的,这是不可能的。为了证明这一点,只需考虑一个带有单个字节的文件的情况。

如果将其限制为C / C ++,则当然可以将其反转。但是,不可能将其还原为原始源代码,因为机器代码与源代码之间没有1:1的关系。根据优化情况,即使源在语义上是相同的,其来源也可能看起来与原始版本完全不同。

#5 楼

是的,任何运行的应用程序都必须具有一些逻辑或代码才能执行。如果机器(转弯完成)可以跟随它;人类也可以(理论上如此,它有可能扭转一切)。事实显然取决于情况,例如,可能存在安全限制,以防止攻击者获得对系统内存或文件系统(例如某些嵌入式设备)上的可执行文件的访问。

#6 楼

这取决于逆向工程的定义和目的。

如果这个聪明的人脑没有时间限制,那么实际上聪明的人脑就能理解愚蠢的计算机能够执行的一切。

我所知道的唯一能以某种方式回答您的问题(衡量程序的可理解性以及程序转换的保密性和安全性保证)的研究方向就是混淆研究。这个领域有一些有趣的作品。
例如,您可以在这里找到该研究领域的一些有趣的摘要。

#7 楼

我试图给出关于反转的想法,而不是给出答案,因为我自己希望自己能找到答案,而且我非常确定,这里的任何专家都可以说我认为的事情是卑鄙的,但是我向社会表示慷慨。 br />
程序的“逆向工程”是为了验证程序是否具有某些属性,而不是从二进制代码逆向源代码(我们可以想象有一些属性可以轻易观察到)在源代码中而不是在二进制代码中),则“混淆”是为了防止程序进行这种算法验证。

在理想的(即理论上)世界中,一些非常笼统的结果断言了几件事。首先,赖斯定理(如@perror先前所述)和兰迪的更具建设性的结果。 W断言不存在通用验证程序,这意味着我们无法编写验证程序V,因此当我们给V赋予任意程序P和非平凡属性p时(平凡属性是所有程序中都存在的一个,例如魔术)在所有PE文件中都存在字节MZ是不重要的属性),V可以回答P是否具有p。因此,这意味着存在完美的混淆,答案是“不”,这是因为我们永远不需要如此强大的验证程序(为所有程序提供确定性答案),对于某些有用的程序类,我们仅需要验证程序即可。

其次,Barak等人(如前所述,@ perror也断言)产生了某种矛盾的结果:有些类别的程序无法混淆,即无论它们被混淆了什么,这都很容易编写验证程序来回答这些程序具有给定的属性p(或不具有)。实际上,这里没有矛盾,因为赖斯定理适用于“所有程序”的上下文,而巴拉克等人的结果适用于“若干程序”的上下文,的确,我们有:

第三,魏的结果。 H表示,给定一类名为点函数的特殊程序,我们总是可以隐藏(即混淆)某些属性。同样,这并不意味着一般情况下可能会产生混淆,因为此结果适用于“几个程序”的上下文。第四,Garg的结果。 S等人说,我们可以混淆任何程序,以使从混淆后的程序计算出的任何属性都是“琐碎的”。因此,这意味着存在完美的混淆器,如果存在,则与Barak等人的结果相矛盾,显然不是,因为这两个结果实际上使用了琐碎性的两个不同定义,在第一个中,如果它存在于所有具有相同语义的程序中(因此,此定义比第二个定义弱)。

在现实世界中,我经验不足,无法提供任何有用的信息理念。但是我怀疑游戏混淆器与反混淆器会以某些非常聪明的方式发展,并且我们仍然有很多空白需要解决(作为混淆器或反混淆器)。

#8 楼

不管使用哪种语言/编译器,都可以对任何二进制文件进行逆向工程,但是这取决于进行该工作的逆向工程师(或开发该工作的工具的开发人员)的知识。

#9 楼

您可以对任何东西进行反向工程。只要您掌握了资源(时间,金钱和技能)。当您购买汽车,程序,计算机,超级秘密芯片时。您可以获得操作它所需的一切。

鉴于此,您可以弄清楚它是如何工作的,然后对它进行反向工程。

评论


使用芯片或汽车可能会有所不同,因为它实际上可能能够自我毁灭。

–heinrich5991
2014年1月10日20:08

然后,您知道那可能会发生,然后您将获得另一辆精确的汽车。恶意软件也是如此,它在连接调试器时具有自我删除功能。

– Stolas
2014年1月11日下午13:19

但是您会发现这里有所不同。拥有该软件后,您可以随时任意获得其确切副本。这不适用于物理对象。

–heinrich5991
2014年1月11日14:51