反汇编程序应产生二进制程序的可读格式。但是,最著名的技术:线性扫描和递归遍历(请参阅此注释以了解更多信息)很容易被特定的技巧误导。一旦被欺骗,他们将输出永远不会由真实程序执行的代码。

认为存在一些新技术和新工具,这些新技术和新工具更加关注正确性(例如Jakstab,McVeto等),这一概念据我所知,对于反汇编程序,输出的正确性从未得到正确定义。您会根据此更正定义对现有的反汇编程序进行分类吗?

评论

在我看来,您实际上是在回答问题。除此之外,您的正确性指标可能完全是主观的。由于您无法进行精确的反编译,因此您只能从那里进行反编译。

这看起来更像是博文,而不是问题:)

是的,请分成一个问题和一个答案。您可以回答自己的问题,这不是问题。另外,末尾的问题与标题不符。

@Emmanuel:请先将问题的答案拆分开,然后再将其关闭。

做完了(为一团糟感到抱歉)。希望会有更好的答案...

#1 楼

我是rdis的作者,并对这个问题进行了一些思考。如果您在此之后还有其他疑问,我建议您看一下我的博客。

我还将推荐您参阅Andrew Ruef的博客文章Binary Analysis Is Not。关键要解决的是,我们经常尝试在编译器的上下文中理解我们的程序,而不必仅仅是指令的连续体。他创造了“编译器输出分析”一词,这或多或少是我们试图在反汇编程序中实现的。

术语和定义

首先,您要定义拆卸通用术语。我们有数据或状态,可以由内存,寄存器和所有好东西组成。我们有代码,这是一个标签,适用于我们希望机器执行的数据(我们将返回代码)。我们有一个程序,该程序是一种编码在数据中的算法,当由机器解释时,该程序会导致以某种方式对数据进行操作。我们有一台机器,将一个状态映射到另一个状态。为了我们的目的,我们有一条指令存在于单个时间点,并且由控制机器操作数据方式的特定数据组成。

通常我们认为目标是转型代码,我们希望机器将执行的数据分解为可读的反汇编。我相信我们这样做是因为我们在控制流分析(代码)和数据流分析(数据)之间划分了程序分析。在程序分析中,我们的代码是无状态的,而我们的数据是有状态的。实际上,我们的代码只是数据,全部都有状态。

程序恢复

相反,我们的目标应该是通过观察或预测机器来恢复程序。换句话说,我们不希望将数据转换为可读的反汇编,而希望发现将由我们的机器解释的指令。

此外,我们对程序的表示应与数据的无状态表示分开存储,数据的无状态表示通常是我们的可执行文件(ELF / PE / MACH-O / etc)提供给我们的初始内存布局。确实,它应该存储在有向图中。当我看到带有标记为指令的多个位置的内存的线性表示时,我会关闭。您还不知道!

我相信拆卸的下一步就是通过允许在拆卸过程中改变状态来更好地预测机器的过程。我相信我们将同时模拟反汇编和抽象反汇编。有些人或多或少已经在执行此操作,尽管我不确定是否有人明确地这样做是为了创建可用且可理解的“程序恢复”。

您可以看到一个示例递归反汇编与模拟反汇编之间的区别。

什么是正确的反汇编?

所以,现在回答您的问题,“什么是反汇编?正确的反汇编程序?”我相信正确的反汇编程序可以清楚地定义其程序恢复过程的行为并遵守此定义。一旦我们得到执行该操作的反汇编程序,则更好的反汇编程序将是其定义最能预测其为其恢复程序的计算机的行为的反汇编程序。

#2 楼

什么是反汇编程序?

我将反汇编程序分解为两部分,首先是一个采用十六进制代码并输出汇编指令的解码器(如果汇编语言具有可变性,则可能具有解码指令的长度)长度说明)。然后,一个反汇编算法将使用解码器浏览可执行代码。

我谦虚地认为,反汇编程序的总体目标是恢复所有可以构建的运行

反汇编中的问题

反汇编程序在分解二进制程序时会遇到很多问题。最困难的方法之一是处理自修改代码。确实,直到现在,还没有真正好的人类可读的自修改程序表示。因此,所有反汇编程序在遇到自修改代码时都无法输出清楚可理解的内容。

阻止反汇编程序的第二个问题是二进制程序有时会跳转到另一个地方执行一些代码(函数调用,if-then-else,开关等)。而且,如果这些跳转中的大多数是静态的(跳转的地址被静态编码到代码中),则有一些跳转取决于执行的上下文。我们通常将这些跳转称为动态跳转(与静态跳转相对)。这些动态跳转迫使反汇编程序不仅要跟踪指令的语法,还要跟踪其语义,以便在遇到指令时不会丢失。

最后一个问题是,不能假定所有二进制程序都遵循精确的ABI(应用程序二进制接口),从而为函数调用或处理数据结构的方式定义了精确的接口。确实,有些二进制程序是手工制作的,或者是经过修饰的编译器,它们会误导反汇编程序。因此,反汇编程序将必须通过其语义而不是仅通过语法来识别函数调用。

反汇编程序的正确性

如我们先前所述,最终的目标反汇编程序是从二进制程序重建所有可能的执行痕迹。当然,在大多数情况下,这非常困难,因此我们可以定义三种反汇编程序:



精确反汇编程序:假设,它应该发出所有正确的跟踪信息可以在二进制程序上运行,并且只能在这些迹线上运行。 />逼近的反汇编程序:此汇编程序的输出应包含在可能的跟踪中,但不要提供任何不可行的跟踪。

现有技术及其分类方法

对于现在,两种最流行的技术是线性扫描和递归遍历(有关更多详细信息,请参见此处)。

无数反向工程人员都在野外广泛使用了两者。但是,实际上,这些技术都不是精确的,也不是过高的,也不是过低的。他们俩都输出了我们以前从未见过的东西(有时他们会发明一条永远无法到达的道路,有时他们会忘记另一条道路)。

更先进的技术引起更多关注存在正确性的信息(例如Jakstab,McVeto,McVeto的自修改代码,...),但要实现精确恢复肯定是遥不可及的。

因此,要在反近似值与过近似值之间进行选择取决于反汇编程序输出的用途。