我最近一直在研究Window的PE格式,我注意到在大多数例子中,
人们倾向于将ImageBase
中的optional header
偏移值设置为不合理的高0x400000
。
在偏移0x0
处映射图像会有什么不利不?
答案 0 :(得分:3)
首先,这不是Windows或PE文件格式的默认值,当您使用它链接EXE时,它是链接器/ BASE选项的默认选项。 DLL的默认值为0x10000000。
选择/ BASE:0将是不好的选择,没有程序可以在该基地址运行。地址空间的前64 KB是保留的,永远不能映射。主要是捕获空指针解除引用错误。并扩展到64KB以捕获以16位开始生命并重新编译为32位的程序中的指针错误。
为什么0x40000而不是0x10000是默认的,也是一个历史性事故,并且至少会回到Windows 95.这为“16位/ MS-DOS兼容性竞技场”保留了前4兆字节的地址空间。我不记得太多,Windows 9x与NT有一个非常不同的16位VM实现。你可以在这个古老的KB article中阅读更多关于它的内容。它当然不再相关,64位操作系统将很容易在0x010000和0x400000之间的空间中分配堆内存。
更改EXE的/ BASE选项没有任何意义。但是,有一个点的批次更改它的DLL。如果它们不重叠并且因此不必重新定位它们会更有效,它们不会在页面文件中占用任何空间并且可以在进程之间共享。甚至还有一个SDK工具,因此您可以在构建rebase.exe之后对其进行更改
答案 1 :(得分:2)
实际上,将/ BASE设置为0的影响取决于图像的Address Space Layout Randomization (ASLR)设置(链接器也放置了/DYNAMICBASE:NO)。
如果您的图像有/ BASE:0并且ASLR已打开(/ DYNAMICBASE:YES),那么您的图像将启动并运行,因为加载程序会自动将其加载到“有效”地址。
如果您的图像有/ BASE:0且ASLR关闭(/ DYNAMICBASE:NO),那么您的图像将无法启动,因为加载程序不会将其加载到所需的基地址(如上所述,无效/保留的)。
答案 2 :(得分:1)
如果将其映射到地址0,则表示代码期望从地址0开始运行。
对于操作系统,地址零为NULL
,这是一个无效的地址
(不是“从根本上”,但对于现代操作系统来说,它是。)
另外,一般来说,由于种种原因,你不需要内存较低的16 MiB(甚至是虚拟内容)。
但是替代方案是什么?它必须映射某处,因此他们选择0x400000
...可能没有特定原因。它可能只是方便。
答案 3 :(得分:1)
Microsoft选择该地址作为PE文件将在内存映射的链接器指定的默认起始地址。链接器假定此地址,并且可以使用该假设优化可执行文件。当文件在该地址处进行内存映射时,可以运行代码而无需修改任何内部偏移。
如果由于某种原因无法将文件加载到该位置(已经加载了另一个exe / dll),则需要在可执行文件运行之前进行重定位,这将增加加载时间。
通常假设较低的内存地址包含低级系统例程,并且通常不加考虑。 ImageBase地址的唯一真正要求是它是0x10000的倍数。
推荐阅读: