5

我有一个版本控制下的程序,它已经经历了多个版本。今天出现了一种情况,有人以某种方式设法指向该程序的旧副本,因此遇到了已修复的错误。我想返回并删除该程序的所有旧副本(保留它们是公司的一项政策,该政策可以追溯到版本控制很普遍并且不再需要)但我需要一种方法来验证我可以生成完全相同的可执行文件,这比说“旧的来自这个提交,所以这个应该是一样的”要好。

我最初的想法是简单地对可执行文件进行 MD5 哈希,将哈希文件存储在源代码管理中,然后完成它,但我遇到了一个我什至无法解析的问题。

似乎每次生成可执行文件(方法:Open Project.File > Make X.exe)它的哈希值都不同。我注意到每次以看似随机的方式打开项目时,Visual Basic 都会弄乱文件,但我认为这不会使其成为可执行文件,我也没有任何证据表明确实发生了这种情况。为了防止这种情况发生,我尝试在同一个 IDE 会话中多次生成可执行文件并检查哈希值,但它们每次都不同。

所以那是:

  1. 生成可执行文件
  2. 生成 MD5 校验和:md5sum X.exe > X.md5
  3. 验证当前可执行文件的 MD5:md5sum -c X.md5
  4. 生成新的可执行文件
  5. 验证新可执行文件的 MD5:md5sum -c X.md5
  6. 验证失败,因为计算的校验和不匹配。

我不了解 MD5 或 VB 6 生成可执行文件的方式,但我也没有接受使用 MD5 的想法。如果有更好的方法来验证两个可执行文件确实相同,那么我会全力以赴。

在此先感谢您的帮助!

4

2 回答 2

13

这几乎是不可能的。请继续阅读以了解原因。

编译器将赢得这场比赛,每次......

连续两次编译同一个项目,即使不对源代码或项目设置进行任何更改,也总是会产生不同的可执行文件。

造成这种情况的原因之一是 Windows 用于 EXE 文件的 PE(可移植可执行文件)格式包含一个时间戳,该时间戳指示构建 EXE 的日期和时间,每当您构建项目时,VB6 编译器都会更新该时间戳。除了整个 EXE 的“主”时间戳之外,EXE 中的每个资源目录(图标、位图、字符串等存储在 EXE 中的位置)也有一个时间戳,编译器在构建新的时也会更新该时间戳。 EXE文件。除此之外,EXE 文件还有一个校验和字段,编译器会根据 EXE 的原始二进制内容重新计算该字段。由于时间戳更新为当前日期/时间,因此每次重新编译项目时,EXE 的校验和也会发生变化。

但是,但是……我发现了这个非常酷的 EXE 编辑工具,它可以撤销这个编译器的诡计!

有 EXE 编辑工具,例如PE Explorer,声称能够将 EXE 文件中的所有时间戳调整为固定时间。乍一看,您可能认为您可以将两个 EXE 副本中的时间戳设置为相同的日期,并最终得到等效的文件(假设它们是从相同的源代码构建的),但事情比这更复杂:每次编译代码时,编译器都可以自由地以不同的顺序写出资源(字符串、图标、文件版本信息等),并且您无法真正阻止这种情况的发生。资源存储为独立的数据“块”,可以在生成的 EXE 中重新排列,而不会影响程序的运行时行为。

如果这还不够,编译器可能会在未初始化的内存区域中构建 EXE 文件,因此 EXE 的某些部分可能包含编译器运行时内存中的点点滴滴,从而创建更多差异。

至于MD5...

您没有误解 MD5 散列:给定相同的输入, MD5 将始终产生相同的散列。这里的问题是这种情况下的输入(EXE 文件)不断变化。

结论:源代码控制是你的朋友

至于解决您当前的困境,我将留给您:将特定的 EXE 与特定版本的源代码相关联更多的是一个政策问题,必须以某种方式强制执行,而不是其他任何事情。试图在没有任何上下文的情况下弄清楚 EXE 来自哪个版本是不可靠的。您需要借助其他工具进行跟踪。例如,确保每个构建为您的 EXE 生成不同的版本号,并且该版本可以轻松地与您的版本控制系统中的特定修订/分支/标签/任何内容配对。为此,一些开发人员使用源代码控制,而其他开发人员使用“我保留在我的网络文件夹中的 1997 年源代码的副本,因为它是我的代码无论如何,源代码控制都是为娘娘腔的”不会帮助使这变得更容易。我会让每个人都喝源代码控制 Kool-Aid 并遵守立即创建构建的标准政策。

每当我们构建项目时,我们的构建服务器(我们使用Hudson)确保编译的 EXE 版本被更新以包含当前构建号(我们使用版本号插件和自定义构建脚本来执行此操作),以及当我们发布构建,我们在 Subversion 中创建一个标签,使用版本号作为标签名称。构建服务器存档发布构建,因此我们始终可以获得提供给客户的特定 EXE(和安装程序)。对于内部测试,我们可以选择从构建服务器中提取存档的 EXE,或者只是告诉构建服务器从我们在 Subversion 中创建的标签重新构建 EXE。

我们也永远不会从构建服务器以外的任何机器向 QA 或客户发布任何二进制文件。这可以防止“在我的机器上工作”的错误,并确保我们总是从源代码的“已知”副本编译(它只提取和构建我们的 Subversion 存储库中的代码),并且我们总是可以关联给定的具有创建它的代码的确切版本的二进制文件。

于 2010-05-15T08:26:04.737 回答
0

我知道已经有一段时间了,但是由于有 VB De-compiler 应用程序,您可以考虑批量反编译 vb6 应用程序,然后将反编译结果提供给各种代码库上的 AI/统计异常检测。鉴于您面临的问题没有确切的解决方案,结果不太可能 100% 准确,但随着您提供更多数据,检测应该会变得越来越准确

于 2020-01-30T23:02:13.647 回答