章节大纲

  • 在上一个任务中,我们成功创建了两个具有相同 MD5 哈希值的程序,但是它们的行为不同。但是,它们的区别仅在于打印出的数据。他们仍然执行相同的指令序列。在此任务中,我们希望做一些更明显且有意义的事。

    假设你已经做了一个有用的软件,你将软件发送给受信任的机构进行认证。该机构对你的软件进行了全面的测试,并得出结论,你的软件确实没问题。权威机构将向你提供证书,说明你的程序是好的。为了防止你在获得证书后更改程序,证书中还包括了程序的 MD5 哈希值。如果你更改了程序的内容,证书将无效。

    你想让你的恶意软件获得授权机构的认证,但是如果你只是将恶意软件发送给授权机构,则不太可能得到认证。但是,你已经注意到,授权机构使用 MD5 生成哈希值。你有个想法,你计划准备两个不同的程序。一个程序将始终执行正常指令,而另一个程序将执行恶意指令。你想办法让这两个程序有相同的 MD5 哈希值。

    然后,你将正常的版本发送给认证机构。由于此版本只做正常的操作,它将通过认证,你将获得一个包含该程序的哈希值的证书。由于你的恶意程序具有相同的哈希值,因此该证书也对你的恶意程序有效。这样,你就成功地为你的恶意程序得到了一个有效证书。如果其他人信任颁发机构颁发的证书,他们将信任地下载你的恶意程序。

    此任务的目标是发起上面描述的攻击。即,你需要创建两个有相同 MD5 哈希值的程序。但是,一个程序将始终执行正常指令,而另一个程序将执行恶意指令。在你的工作中,执行什么指令并不重要,只要证明这两个程序执行的指令是不同的就足够了。

    实验指导。创建两个有相同 MD5 哈希值且完全不同的程序非常困难。 md5collgen 生成的两个有相同哈希值的程序需要有共同的前缀。此外,从上一个任务可以看出,如果我们需要在 md5collgen 产生的输出中添加一些有意义的后缀,则添加到两个程序中的后缀也必须相同。这些是我们使用的 MD5 碰撞生成程序的局限性。尽管还有其他更复杂,更高级的工具可以克服某些限制,例如接受两个不同的前缀,但它们需要更多的算力,因此不在本实验的范围之内。我们需要找到一种方法来在有限的范围内生成两个不同的程序。

    有多种方法可以实现上述目标。我们提供一种方法作为参考,但鼓励学生提出自己的想法。教师可以考虑给用自己想法的学生一些奖励。在我们的方法中,我们创建两个数组 X 和 Y。我们比较这两个数组的内容。如果相同,则执行正常代码。否则,执行恶意代码。请参见以下伪代码:
    Array X;
    Array Y;
    
    main()
    {
      if(X's contents and Y's contents are the same)
          run benign code;
      else
          run malicious code;
      return;
    }

    我们可以使用一些值来初始化数组 X 和 Y ,这些值可以帮助我们在二进制可执行文件中找到它们的位置。我们的工作是更改这两个数组的内容,这样我们可以生成两个不同的却拥有相同 MD5 哈希值的版本。在一个版本中, X 和 Y 的内容相同,因此执行正常代码。在另一个版本中, X 和 Y 的内容不同,因此将执行恶意代码。我们可以使用类似于任务 3 中使用的技术来实现此目标。下图展示了两个版本的区别。
     
     

    从图中,我们知道只要相应地生成  P 和 Q,这两个二进制文件就具有相同的 MD5 哈希值。在第一个版本中,使数组 X 和 Y 的内容相同,而在第二个版本中,使它们的内容不同。因此,我们唯一需要更改的就是这两个数组的内容,而无需更改程序的逻辑。