2

我刚刚第一次使用 DUMPBIN,我在输出文件中反复看到术语 HIGHLOW:

BASE RELOCATIONS #7
   11000 RVA,       E0 SizeOfBlock
    ...
         3B5  HIGHLOW            2001753D  ___onexitbegin
         3C1  HIGHLOW            2001753D  ___onexitbegin
    ...

我很好奇这个词代表什么。我在 Google 或 Stackoverflow 上没有找到任何关于它的信息。

4

2 回答 2

6

为了应用修正,增量计算为首选基地址与实际加载图像的基地址之间的差异。

基本思想是,当在某个地址进行修复时,我们必须知道

  1. 必须更改哪些内存(“偏移”字段)
  2. 重定位需要什么值(“delta”值)
  3. 要使用重定位数据和增量值的哪些部分(“类型”字段)

以下是“类型”字段的一些可能值

  • HIGH- 将 delta 的高位字(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并且链接器无法知道其输出将被重新定位。正因为如此,装载机必须发挥它的魔力。它

  1. 计算增量值 - 旧地址(图像库)是0x700000但它想要0xf00000(首选地址)。它从另一个中减去一个并得到0x800000结果。
  2. 获取.reloc文件的部分
  3. 检查是否还有另一个页面(4KB 的数据)要重新定位。如果不是,它会继续调用文件的入口点。4.对于当前页面的每次重定位,它
  4. 在重定位偏移处获取数据
  5. 添加增量值(以类型字段状态的方式)
  6. 将新值放在重定位偏移处
  7. 继续第 3 步

还有更多类型的重定位条目,其中一些是特定于体系结构的。要查看完整列表,请阅读“Microsoft Portable Executable and Common Object File Format, section 6.6.2. Fixup Types”

于 2014-07-18T11:26:01.563 回答
2

您在此处看到的是 Microsoft Windows 可执行文件中“基本重定位表”的内容。

在 Windows 中,基本重定位表对于 DLL 文件是必需的,它们对于可执行文件是可选的;它们包含有关 EXE/DLL 文件中地址信息位置的信息,当知道 DLL 文件在内存中的实际地址时(将 DLL 加载到内存中时),必须更新这些信息。Windows 使用存储在此表中的信息来更新地址信息。

该表支持不同类型的地址,而命名是 Microsoft 特定的:ABSOLUTE (= dummy)、HIGH、LOW、HIGHLOW、HIGHADJ 和 MIPS_JMPADDR。

常量的全称是“IMAGE_REL_BASED_HIGHLOW”。

“ABSOLUTE”类型通常是插入的虚拟条目,以确保表的部分长度为 4(或 8)字节的倍数。

在 x86 CPU 上仅使用“HIGHLOW”类型:它告诉 Windows 文件中绝对(32 位)地址的位置。

一些背景资料:

在您的示例中,“Image Base”可能是 0x20000000,这意味着 EXE/DLL 文件已被编译为加载到地址 0x20000000。在地址 0x200113B5 (0x20000000 + 0x11000 + 0x3B5) 和 0x200113C1 有绝对地址。

假设位置 0x200113B5 的内存包含值 0x20012345,它是程序中函数或变量的地址。

也许地址 0x20000000 的内存无法使用,Windows 决定将 DLL 加载到 0x50000000 的内存中。那么 0x20012345 必须替换为 0x50012345。

Windows 使用基本重定位表中的信息来查找所有必须替换的地址。

于 2014-07-18T11:45:12.087 回答