如何验证VB 6可执行文件的2个副本来自相同的代码库?

时间:2010-05-14 14:01:24

标签: vb6 md5 hash md5sum binary-reproducibility

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

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

似乎每次生成可执行文件(方法:打开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. 验证失败,因为计算的校验和不匹配。
  7. 我不了解MD5或VB 6生成可执行文件的方式,但我也没有与使用MD5的想法结合。如果有更好的方法来验证两个可执行文件确实是相同的那么我就是全智能的。

    提前感谢您的帮助!

2 个答案:

答案 0 :(得分:11)

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

编译器每次都会赢得这场比赛......

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

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

但是,但是......我发现这个非常酷的EXE编辑工具可以撤消这个编译器的技巧!

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

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

至于MD5 ......

您并不误解MD5散列:MD5将总是在给定相同输入的情况下生成相同的散列。这里的问题是这种情况下的输入(EXE文件)不断变化。

结论:源代码管理是你的朋友

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

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

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

答案 1 :(得分:0)

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