它被称为重定位
每个可执行文件都有一个名为 .reloc 的部分
此部分包含有关在图像库更改时需要修补的所有地址的详细信息
加载器使用这个部分来改变所有修改过的基地址
例如 win7 x86 32 位 calc.exe
从 cdb.exe 反汇编(随机图像库)
002616a3 ff15f4132600 call dword ptr [calc!_imp__LoadStringW (002613f4)]
从 dumpbin 反汇编(默认镜像库)
C:\>dumpbin /nologo c:\Windows\System32\calc.exe /disasm /range:0x10016A2,0x10016b1
010016A2: 50 push eax
010016A3: FF 15 F4 13 00 01 call dword ptr [__imp__LoadStringW@16]
如果您查看 .reloca 部分,您会注意到地址6A5的 HIGHLOW 条目
Offset(h) 00 01
000B9C00 00 10 ..
000B9C02 00 00 ..
000B9C04 B4 00 ´.
000B9C06 00 00 ..
000B9C08 41 36 A6
000B9C0A 52 36 R6
000B9C0C A5 36 ¥6 <<<<<
000B9C0E B3 36 ³6
所以加载器可以修补 RVA 处的地址(ImageBase + 节基址 + 地址)
imagebase = 0x1000000 + base of section = 0x1000 + HIGHLOW address = 6a5
= 0x10016a5
在这个地址 dumpbin 有F4 13 00 01 而 cdb 有f4 13 26 00
加载程序已根据映像库对其进行修补
我的这篇文章有更多关于修补内容的详细信息
更新wrt评论一些exe没有.reloc
是的,完全有可能在没有 reloc 的情况下使用 exe,
事实上如果通过,则有一个 msvc 链接器开关 /FIXED 会产生没有重定位的 exe
在大多数情况下,exe 无需重定位即可存活,因为它们是第一个加载到进程地址空间中的,
因此它们总是倾向于获得首选的 ImageBase
重定位对 Dll 最重要,尤其是那些动态加载或作为对另一个 dll 的依赖项加载的 dll
在这种情况下,可能会发生冲突,操作系统需要一种机制来重新定位有问题的二进制文件
如果 Windows 无法重新定位 dll,它会导致应用程序崩溃
C:\>cdb -c "!error c0000018;q" cdb | tail -n 3
0:000> cdb: Reading initial command '!error c0000018;q'
Error code: (NTSTATUS) 0xc0000018 (3221225496) - {Conflicting Address Range} The specified address range conflicts with
the address space.
quit: