两个“完全相同”的程序执行不同操作的小把戏
Marc Stevens 等人已经在破解 MD5 算法方面取得了不错的进展(见 http://www.win.tue.nl/hashclash/),他写出了两个输出不同字符串程序,它们的代码略有不同,但却拥有相同 MD5 值的。这显示了 MD5 算法的弱点。
即使搞不明白 Marc Stevens 高深的数学证明,我们也可以玩一些小把戏,让两个内容和 MD5 都完全相同的程序执行不同的操作。其实这里的猫腻就在于如何定义“完全相同”。文件有其内容(正文),也有元信息(文件名、日期、属性等)和物理位置等原始信息。一般定义的“完全相同”是指内容相同,MD5 等校验值也仅是针对内容计算的,与元信息、原始信息无关。但在程序中完全可以读取元信息和原始信息,根据它们的不同,让程序执行不同的操作。
通常元信息是容易修改的,用它玩这个把戏很容易被识破;原始信息难以自定义,也不便于移植。那用什么来玩呢?对!NTFS 文件系统有“流”(Stream)特性,可以给文件追加隐形的数据流。流本质上是一种自定义名称的元信息,与一般的元信息(甚至文件内容,这个名为“$DATA”的元信息)没什么区别,只是 Windows 默认不呈现给用户罢了。
由此,我写了一个小程序 StreamTricker,它在运行时读取自身可执行文件中名为“trick”的流,并将其内容显示出来。编译之后复制出 test-1.exe、test-2.exe 两个副本,使用命令行的 echo 命令给这两个文件追加不同的 trick 流,然后分别运行,就可以看到如图所示不同的输出。
| 发件人 blog |
拿这两个程序忽悠别人:看看,MD5 是相同的;用 fc 命令对比一下,内容完全一致,但运行结果就是不一样!把文件改名、复制(当然别复制到 FAT 分区)也不影响效果。有人可能想去反汇编了,那干脆把程序加个壳吧。但了解 NTFS 流特性的朋友可能很快就能识破其中的猫腻了。
当然,也可以把不同的可执行代码放在流中,实现一些更有趣的功能。不过,已经有人利用流特性来隐藏病毒了,这些事实都警告我们不要轻信 MD5 等校验和。
StreamTricker 源代码与可执行文件下载:
http://files.linjian.org/c_cpp/StreamTricker.rar
http://www.linjian.cn/files/c_cpp/StreamTricker.rar
(WinRAR 支持 NTFS 流的压缩。如果使用 WinRAR 解压,可以保留流特性;用其它解压软件解开之后流特性有可能丢失,可以使用 echo 命令手工加入 trick 流测试)




