如何判断两个exe文件的代码是否相同?

5

有没有一种方法可以检测两个从VS.Net 2008编译的C++/MFC EXE文件之间是否没有任何代码级别的更改,即为了知道是否有语句更改。

这是为了合规目的,当我的供应商向我发运一个exe时,它明显没有对代码进行任何更改,自上次我们测试以来。

有没有工具可以检查是否如此?

谢谢!


1
如果你已经有代码并且测试通过,为什么不自己编译呢?他们为什么会发送另一个exe文件而没有更多可测试的代码呢? - Karl
2
@Karl:我在问题中看不出提问者是否拥有源代码。无论如何,对于大型组件化应用程序而言,新版本包含未经代码更改重新构建的组件并不一定是不寻常的。 - bk1e
7个回答

4
您可以使用反汇编器将可执行文件反汇编为汇编语言,并使用普通的文本对比工具进行比较。
但即使如此,也不会完全准确。编译过程并非无损的,当C++代码被编译时,许多信息会丢失或不可逆转化。
特别是,不同的编译器设置可以从完全相同的源代码生成截然不同的机器码。不同的编译器甚至是同一编译器的不同版本或服务包/热修补级别可以从相同的源文件产生截然不同的机器码。
另一个问题是,为什么他们要把“没有做任何改动”的exe发送回给您?如果是这样,为什么不使用您最初拥有的那个?

如果他们无法证明更新的必要性,那么继续使用经过测试/认证的版本。 - Ben Voigt
如果该EXE的供应商是微软,根据最终用户许可协议,您不能使用反汇编器。 - Kirill V. Lyadvinsky
@Kirill:“为了合规目的”意味着有法律义务,通常优先于合同条款。Microsoft EULA 不能强迫您违法。 (本人非法律专家,请咨询当地合规专家) - MSalters

2

您可以对可执行文件执行MD5sum。这并不能告诉您它们是否在逻辑上等效或不同,仅表明存在差异。

我不确定这是否解决了您的问题,因为您可能正在寻找一种逻辑比较工具。


使用MD5始终会生成不同的校验和,即使我们编译相同的项目。我猜链接器正在将一些时间特定的内容添加到exe文件中。 - yumcious

2
自动化你的测试,使测试可以快速重新运行。
尽管这只是一个简短的陈述,但这是一个艰巨的任务。

有时候供应商会把错误的资源(版本、版权等)发送给我们进行测试。然后他们在我们完成验收测试之后才“突然”想起需要更正这些问题。我们只需要一个机制来证明这个供应商没有在生产使用中悄悄地插入任何代码。 - yumcious

2
对于二进制审计,你必须拥有的最佳工具之一是交互式反汇编器,也称为IDA ProIDA Pro)。当您需要在没有源代码访问权限的情况下进行审计时,它是必不可少的。熟练使用IDA Pro的人将能够告诉您,以合理的信心,是否对源代码进行了超出表面更改的任何更改。在这种情况下,表面更改将包括源文件中的变量重命名或更改变量、函数或类声明和定义的顺序。他们将能够告诉您,组成可执行文件的基本代码块之间是否存在足以被标记为可疑的差异,因此很有可能这些差异是源级别差异的指示。
我说“大体上”,因为从完全相同的源树生成的两个可执行文件之间仍然可能存在微妙或偶尔不那么微妙的差异。影响可执行文件生成的因素包括:
  • 编译器优化设置
  • 可执行文件链接的不同版本的库
  • 头文件更改,这些头文件是在编译步骤之前由C ++预处理器包含的,而这些头文件并不属于用于构建可执行文件的源代码树的外部文件
  • 一个可执行文件在运行时操作其自身的代码,这可能包括将自身的某些部分解压缩或解密到可以跳转到的某个内存区域中。

这个列表可以继续下去。

您建议的二进制审计是否可行?是的,有足够知识和技能的人可以做到这一点。黑客们经常这样做。如果进行分析的人足够好,他们将能够告诉您他们对其评估的信心程度。

最终问题变成了可行性的问题。您愿意在这个审计上花费多少钱?雇用或承包能够做到这一点的人可能会超出预算,是否有足够的资金来完成这项工作?您正在测试的软件有多复杂?您与供应商的关系的性质是什么?

最后一个问题很重要,因为如果通过此次审计符合他们的最佳利益,并且他们意识到这一点,他们可能愿意在一定程度上协助您。这可以采取调试符号、编译器选项列表或其他构建过程的工件形式,他们愿意披露。由于某种原因,如果源代码不可用于分析目的,则以上内容都可以对任何分析非常有帮助。如果可以访问源代码以进行此类目的,则分析变得更加容易。
如果您想自己追求这方面的事情,我会推荐两本书:IDA Pro Book:全球最流行的反汇编器的非官方指南(作者:Chris Eagle)和Shellcoder's Handbook:发现和利用安全漏洞(作者:Chris Anley、John Heasman、Felix Linder 和 Gerardo Richarte)。
最后,为了帮助你进行分析所开发的技术和工具仍然是非常活跃的研究领域。你的问题可能比你意识到的更深入,或者可能被我误解了。即使只从实际角度出发,忽略与之相关的理论,对你的问题进行全面的处理也需要填写许多书籍。
我希望你能从中找到至少一部分有用的信息。祝你好运!

1
与供应商的关系并非完全信任,因为这是一个金融支付系统。在部署之前需要通过一套测试。如果他们“忘记”添加适当的版本信息资源等内容,我们不希望重新进行所有的测试。如果代码有变更,那么我们有权拒绝新的可执行文件,或者对供应商进行惩罚。 - yumcious

1

如果您掌控源代码,只需不发布没有与之关联的适当版本信息的exe文件。

如果由于某种原因他们自己构建exe文件,我建议设置一个构建步骤,要求将版本控制修订号嵌入到版本信息中。

如果他们不使用您的构建步骤(您可以检测到),那么您就认为它们是不同的。

大多数版本控制系统(例如SVN)都允许您设置一个构建步骤,以确定代码是否处于修改状态。您可以将此信息嵌入到exe文件的嵌入式资源字符串中,然后只需提取该资源即可。

因此,确保所有构建都从您的自定义构建脚本中进行。


情境如下。该应用程序应是语言无关的,即使用资源来处理字符串(在我们看来不算逻辑)。在初始测试中,我们使用英文,而供应商将稍后交付其他语言版本,但嵌入为字符串资源。我们只需要确保在他们将新exe交付给我们时没有代码更改。如果注释有更改(无论如何不在exe中),或资源,则我们可以接受。 - yumcious
@yumcious:使用类似gettext的工具来标记你的字符串。然后使用它创建语言文件并交付给客户端。你的客户端将会把翻译好的语言文件发送回给你。这样你就可以独立于语言文件进行开发,而他们只需要针对每个唯一的字符串进行一次翻译即可。 - Brian R. Bondy

1

从现在开始,添加一个后期构建步骤,将生成源文件的MD5并将其添加到版本资源中(这样您就可以在exe属性中看到它)。
这将耗费您2到3个人日。


1

在十六进制比较程序中加载exe文件(BeyondCompare非常好用!)。

如果有任何非微不足道的更改(假设编译器设置没有更改),它们应该很容易被发现。如果只是时间戳等问题,那么可能很明显。

这绝对不是万无一失的,但这将是我的第一步。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接