不映射偏移量 0 处的 Win32 可移植可执行映像的可能原因是什么



我最近一直在研究 Window 的 PE 格式,我注意到在大多数示例中,人们倾向于将optional header中的ImageBase偏移值设置为不合理的高值,例如0x400000

什么会使以偏移0x0映射图像不利?

首先,这不是 Windows 或 PE 文件格式的默认值,它是链接器的/BASE 选项的默认值,当您使用它来链接 EXE 时。 DLL 的默认值为 0x10000000。

选择/BASE:0这将是糟糕的选择,没有程序可以在该基址上运行。 地址空间的前 64 KB 是保留的,永远无法映射。 主要是为了捕获空指针取消引用错误。 并扩展到 64KB,以捕获以 16 位开始运行并重新编译为 32 位的程序中的指针错误。

为什么0x40000而不是0x10000是默认值也是一个历史事故,至少可以追溯到Windows 95。 它为"16 位/MS-DOS 兼容性竞技场"保留了地址空间的前 4 兆字节。 我不记得太多了,Windows 9x有一个与NT非常不同的16位VM实现。 您可以在这篇古老的知识库文章中阅读更多相关信息。 如今,它肯定不再相关,64位操作系统将很容易在0x010000和0x400000之间的空间中分配堆内存。

更改 EXE 的/BASE 选项没有任何意义。 但是,将其更改为 DLL 有很多意义。 如果它们不重叠,因此不必重新定位,它们不会占用分页文件中的任何空间并且可以在进程之间共享,则它们会更有效。 甚至还有一个SDK工具,因此您可以在构建,变基后进行更改.exe

实际上,将/BASE 设置为 0 的影响取决于图像的地址空间布局随机化 (ASLR) 设置(该设置也由链接器 -/DYNAMICBASE:NO) 放置)。

您的图像是否应具有/BASE:0并且 ASLR 处于打开状态 (/DYNAMICBASE:YES),那么您的映像将启动并运行,因为加载程序会自动将其加载到"有效"地址。

您的图像是否应具有/BASE:0并且 ASLR 已关闭 (/DYNAMICBASE:NO),那么您的图像将不会启动,因为加载程序不会将其加载到所需的基于地址(如上所述,该地址无效/保留)。

如果将其映射到地址 0,则意味着代码期望从地址 0 开始运行。

对于操作系统,地址零是NULL,这是一个无效的地址。
(不是"从根本上",但对于现代操作系统来说,它是

此外,出于多种原因,通常您不希望内存的较低 16 MiB(甚至是虚拟)中的任何内容。

但是还有什么选择呢?它必须映射到某个地方,所以他们选择了0x400000......该特定地址可能没有特别的原因。这可能只是方便。

Microsoft选择该地址作为链接器指定的默认起始地址,PE 文件将映射到该链接器。链接器采用此地址,并可以使用该假设优化可执行文件。当文件在该地址内存映射时,可以运行代码而无需修改任何内部偏移量。

如果由于某种原因无法将文件加载到该位置(另一个exe/dll已加载到该位置),则需要在可执行文件运行之前进行重新定位,这将增加加载时间。

通常

假定较低内存地址包含低级系统例程,并且通常单独保留。对 ImageBase 地址的唯一实际要求是它是0x10000的倍数。

推荐阅读:

  • http://msdn.microsoft.com/en-us/library/ms809762.aspx

相关内容

最新更新