为了应用修正,delta 被计算为
首选基址,以及图像实际所在的基址
已加载。
基本思想是,在某个地址进行修复时,我们必须知道
- 必须更改哪些内存(“偏移”字段)
- 重定位需要什么值(“delta”值)
- 要使用重定位数据和增量值的哪些部分(“类型”字段)
以下是“类型”字段的一些可能值
-
HIGH - 将增量的高位字(16 位)添加到“偏移”处的 16 位值
-
LOW - 将 delta 的低位字添加到“偏移”处的值
-
HIGHLOW - 在“偏移”处将完整的增量添加到 32 位值
换句话说,HIGHLOW 类型告诉程序它正在从这个重定位块*的页面的偏移量“偏移量”上进行修复,并且需要修改一个双字才能拥有正常工作的可执行文件。
* 所有的重定位条目都被分组到块中,每个块都有一个页面,在该页面上应用其条目
假设您的代码中有这条指令:
section .data
message: "Hello World!", 0
section .code
...
mov eax, message
...
您运行汇编程序,然后立即运行反汇编程序。现在您的代码如下所示:
mov eax, dword [0x702000]
你现在很好奇为什么是0x700000,当你查看文件转储时,你会看到
ImageBase: 0x00700000
现在您了解了这个数字是从哪里来的,并且您已经准备好运行可执行文件了。
将可执行文件加载到内存并为其创建地址空间的加载程序发现内存0x700000 不可用,它需要将该文件放在其他地方。它决定0xf00000 可以,并将文件内容复制到那里。
但是,您的程序被链接为仅使用 0x700000 上的数据,并且链接器无法知道其输出将被重新定位。正因为如此,装载机必须发挥它的魔力。它
- 计算 delta 值 - 旧地址(图像库)是
0x700000,但它需要0xf00000(首选地址)。它从另一个中减去一个并得到0x800000 作为结果。
- 进入文件的
.reloc 部分
- 检查是否还有另一个页面(4KB 的数据)要重新定位。如果不是,它会继续调用文件的入口点。
4.对于当前页面的每次重定位,它
- 在重定位偏移处获取数据
- 添加增量值(以类型字段状态的方式)
- 将新值放在重定位偏移处
- 继续第 3 步
还有更多类型的重定位条目,其中一些是特定于架构的。要查看完整列表,请阅读“Microsoft Portable Executable and Common Object File Format, section 6.6.2. Fixup Types”。