首页 > 解决方案 > 替换现有 Win32 .exe 中的 PE 存根

问题描述

我有一个现有的 Win32 .exe,开头有一个 PE 存根,我有另一个 PE 存根存储在一个单独的文件中。这个单独的 PE stub 大于 20 KiB,原始 PE stub 最多为 512 字节。我没有源代码,所以我无法重新编译或重新链接。如何替换 Win32 .exe 中的 PE 存根?

可能我需要一个工具来更新节文件偏移量。但这还不够:根据输出的差异objdump -x file.exe,还必须更新:AddressOfEntryPoint、BaseOfCode、BaseOfData、SizeOfImage、SizeOfHeaders、数据目录中的偏移量、重定位修复中的地址。

标签: windowsstubportable-executable

解决方案


TL:DR使用pe-setstub中的 Perl 脚本替换 PE .exe 中的 DOS 存根。

带有大存根(甚至大于 100 000 字节)的 Win32 PE .exe 文件可以在各种 Windows 版本上运行,但有一个要求:每个部分的 VirtualAddress 不得小于标头大小(包括存根、PE标题和 PE 部分表)。因此,如果一个程序用一个更大的存根替换存根,该程序还必须增加每个部分的 VirtualAddress。这听起来像是一个非常复杂的操作,因此不太可能有现成的工具。

FYI 在 Win32s 上,还有一个额外的要求:PE 标头(以最后一节标头的最后一个字节结尾)必须适合 0x800(2048)字节。

即使有这些要求,也可以添加长存根,而无需触及部分的 VirtualAddress 或 ImageBase。PE .exe 看起来像这样:

  1. 32 字节的 DOS .exe 标头(包括末尾的几个字节的填充),以 . 开头MZ。偏移量 8 处的头字段指向 DOS 存根代码 (#3)。
  2. 大约 368 字节的 PE 头(包含 4 个节头,每个 40 字节),以 开头PE,以最后一个节头结束。
  3. 其余的 DOS 存根代码将被加载到内存并由 DOS 运行。这可以小到 32 字节,也可以大到几百 KiB。
  4. 一些填充字节将第一部分对齐到 0x200 的倍数。
  5. 节数据,每个对齐到 0x200 的倍数。

我已经在pe-setstub中实现了这样的存根替换和拆分作为 Perl 脚本。

它之所以有效,是因为#3 的大小没有(小)上限。


推荐阅读