为什么可执行文件仍然 运行 尽管更改了校验和,或者更改了没有新校验和的数据部分?

Why does an executable still run despite changes to checksum, or changes to data section without new checksum?

我有一个使用 Flat Assembler 编译的 "Hello World" 控制台应用程序。可执行文件的大小为 2048 字节,校验和为 0x3797.

问题:

  1. 如果在保持相同校验和的同时对可执行文件的数据部分进行更改并对代码部分进行微小更改,这是否重要?

并没有真正改变操作码,只是插入不同的input.Length(数据部分中以空字符结尾的文本字符串的长度)

         push 0xfffffff5 // - 11
         call DWORD PTR ds:0x40304c // .idata [GetStdHandle]
         push 0x0
         push 0x401014
         push [input.Length]
         push 0x401000 // .data
         push eax
         call DWORD PTR ds:0x403050 // .idata [WriteConsole]
         push 0x0
         call DWORD PTR ds:0x0403048 // .idata [ExitProcess]
  1. 为什么即使我使用了不同的校验和,它仍然 运行?

例如,即使我将校验和更改为 0x995A 或 0x5A99,它仍然 运行。

我使用 ImageHlp.dll 来计算此 post 中总结的校验和。

PE 校验和记录在案 here。它只是作为 PE 文件格式的一部分的一个字段,对于普通用户模式应用程序来说被认为是可选的。 linker 通常将该字段默认为零,至少在从 Microsoft Visual C++ 构建时是这样。 Windows 在大多数应用程序中忽略该字段,您可以自由修改二进制文件而无需更新此值。

例外情况是校验和需要匹配驱动程序和关键系统进程。从 link 提供的 "all drivers, any DLL loaded at boot time, and any DLL that is loaded into a critical Windows process",你需要一个匹配的校验和,否则 Windows 将无法加载模块。

旁注:Windows 要求驱动程序除了匹配的校验和之外还需要嵌入式代码签名证书,以便该模块在 Windows AFTER XP 版本(即 Vista 和向上)。有关详细信息,请参阅 Authenticode specification.

您可以计算正确的校验和并将其存储到您的 PE 文件中(许多工具也可以为您完成此操作),因为如果您希望对可执行文件进行基本的完整性检查,您可以选择编写逻辑以在运行时验证此值修改 - 但这是可选的。如果您想在 PE 文件的末尾嵌入代码签名证书,可以通过 WinTrust API 访问更强大的完整性检查(参见上面的 Authenticode link)。