在反汇编的二进制文件中HIGHLOW的含义是什么?

时间:2014-07-18 09:42:21

标签: c++ windows assembly x86 dumpbin

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

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

我很好奇这个术语代表什么。我没有在Google或Stackoverflow上找到任何关于它的内容。

2 个答案:

答案 0 :(得分:5)

  

要应用修正,会计​​算 delta 之间的差异   首选基地址,以及图像实际所在的基础   加载。

基本的想法是,在某个地址进行修正时,我们必须知道

  1. 必须更改的内存(“偏移”字段)
  2. 其重定位所需的值(“delta”值)
  3. 要使用的重定位数据和delta值的哪些部分(“type”字段)
  4. 以下是“type”字段的一些可能值

    • HIGH - 在“offset”处向16位值添加更高字(16位)的delta
    • LOW - 将delta的较低字添加到“offset”的值
    • HIGHLOW - 在“offset”
    • 处为32位值添加完整增量

    换句话说,HIGHLOW类型告诉程序它正在对此重定位块*的页面偏移“偏移”进行修复,并且有一个需要按顺序修改的双字有正确的可执行文件。

    *所有重定位条目都被分组为块,每个块都有一个应用其条目的页面

    假设你的代码中有这条指令:

    section .data
    message: "Hello World!", 0
    
    section .code
    ...
    mov eax, message
    ...
    

    你运行汇编程序,然后运行反汇编程序。现在您的代码如下所示:

    mov eax, dword [0x702000]
    

    您现在好奇为什么它是0x700000,当您查看文件转储时,您会看到

    ImageBase:      0x00700000
    

    现在您了解此号码的来源,并准备好运行可执行文件。 将可执行文件加载到内存并为它们创建地址空间的Loader发现,内存0x700000不可用,需要将该文件放在其他位置。它决定0xf00000可以,并在那里复制文件内容。

    但是,您的程序仅与0x700000上的数据相关联,并且链接器无法知道其输出将被重定位。因此,装载机必须发挥其魔力。它

    1. 计算 delta 值 - 旧地址(图片库)为0x700000但它需要0xf00000(首选地址)。它会相互减去一个,并得到0x800000
    2. 转到文件的.reloc部分
    3. 检查是否还有其他页面(4KB数据)需要重新定位。如果不是,它继续调用文件的入口点。 4.对于当前页面的每次重定位,
    4. 以重定位偏移量获取数据
    5. 添加delta值(作为类型字段状态的方式)
    6. 将新值置于重定位偏移量
    7. 继续第3步
    8. 还有更多类型的重定位条目,其中一些是特定于体系结构的。要查看完整列表,请阅读“Microsoft可移植可执行文件和通用目标文件格式,第6.6.2节”修复类型“

答案 1 :(得分: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的内存中。然后必须用0x50012345替换0x20012345。

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