为什么入口点的地址不匹配 NT header?

Why the address of entry point doesn't match NT header?

我想找出一个windows程序的入口。据 MS documents 描述“ImageBase”:

When the linker creates an executable, it assumes that the file will be memory-mapped to a specific location in memory. ...

我使用 dumpbin 在 PE 中显示 ImageBase header,找到映射的位置:

>dumpbin /HEADERS my.exe
...
            13D0 entry point (00000001400013D0) mainCRTStartup
            1000 base of code
       140000000 image base (0000000140000000 to 0000000140006FFF)
...

所以入口函数 mainCRTStartup 映射到虚拟地址 0x00000001400013D0 ,但是当我 运行 程序和打印地址时:

with __ImageBase = 0x7ff771e60000
with mainCRTStartup = 0x7ff771e61390

程序打印的地址好像在用户space的底部(靠近windows dll),远离“图像库+入口点”。这是为什么?

我也尝试检查 0x00000001400013D0 处的内存,但似乎没有映射页面。

这是源代码(由 vs2019 构建,x64):

#include <Windows.h>
#include <stdio.h>

extern "C" const IMAGE_DOS_HEADER __ImageBase;
extern "C" int mainCRTStartup();

int main() {
    printf("with __ImageBase = 0x%llx\r\n", (HINSTANCE)&__ImageBase);
    printf("with mainCRTStartup = 0x%llx\r\n", mainCRTStartup);
    return 0;
}

假设您使用的是 Visual Studio 的最新版本,您的应用程序可能默认选择了 ASLR(地址 Space 布局随机化)。这是一项安全功能,旨在让 shell 代码(漏洞利用)更难找到锁定的位置。

尝试添加 /FIXED 链接器开关,这将阻止您的 .EXE 具有重定位信息,进而阻止 ASLR 在内存中重定位您的 PE。 /DYNAMICBASE:NO/FIXED 的较弱版本,您也可以尝试,尤其是对于 .DLL。