重定位图像时如何前进到下一个内存块

how to advance to next block of memory when relocating image

基本上我只是想了解这是如何工作的我看到几个人使用 current_base_relocation = reinterpret_cast<PIMAGE_BASE_RELOCATION>(reinterpret_cast<uint64_t>(current_base_relocation) + current_base_relocation->SizeOfBlock); 推进到第二个 PIMAGE_BASE_RELOCATION 结构(或第二个重定位块),其中 current_base_relocation是指向 PIMAGE_BASE_RELOCATION 基本结构的指针,基本上他添加了结构本身 + 另一个结构和条目大小并到达第二个内存块但是有人可以解释如何吗?例如,为了在映射时修复 pe 文件中的导入,我可以使用 ++struct 简单地前进到内存中的第二个结构,以转到数组中的第二个结构,但我不明白它是如何工作的。

您问为什么在处理 PE 文件的 IMAGE_DIRECTORY_ENTRY_BASERELOC 目录时,以下代码可以前进到下一个 IMAGE_BASE_RELOCATION 块:

current_base_relocation = reinterpret_cast<PIMAGE_BASE_RELOCATION>(reinterpret_cast<uint64_t>(current_base_relocation) + current_base_relocation->SizeOfBlock);

IMAGE_BASE_RELOCATION结构是一个header的块,并不代表整个块。如果结构确实代表了整个块,您可以使用 current_base_relocation++ 推进它。这就是为您提供 size 成员 (current_base_relocation->SizeOfBlock) 的原因。请注意,此大小包括 header 结构 (IMAGE_BASE_RELOCATION) 和后面的数组的大小,以字节为单位。获得WORD-sized数据数组的指针计算将是IMAGE_BASE_RELOCATION结构(header)之后的第一个位置,可以这样获得:

word* pCurBlockEntry = (word*)((byte*)current_base_relocation + sizeof(*current_base_relocation))) 

现在回答你的问题。您提供的计算很可能是您在循环 body 中看到的,在它按照您指出的方式处理了第一个块之后。它以指向 IMAGE_BASE_RELOCATION 结构的当前指针开始。然后将指针转换为 64 位无符号整数,这样当您向其添加字节大小时 (current_base_relocation->SizeOfBlock) 您可以按字节数而不是 IMAGE_BASE_RELOCATION 结构(那将是一个严重的错误)。任何无符号整数都可以。使用 64 位无符号整数是因为它与指针的整数大小相同(对于 64 位代码),否则可以使用 32 位无符号整数。

例如,如果没有转换并假设 current_base_relocation->SizeOfBlock 恰好是 32,pointer-arithmetic 指示您的指针将前进 32 IMAGE_BASE_RELOCATION 结构而不是 32 字节到下一个块(在此示例中,这将包括当前的 IMAGE_BASE_RELOCATION 结构和 12 个 16 位条目的尾随数据数组)。实际上,我认为这些块都是 4k,至少根据 PE 规范是这样。

就我个人而言,当我想将指针前进一个字节大小时,我更喜欢在算术之前将其转换为字节* 而不是无符号整数。这只是防止在整数和指针之间切换,从而避免在编译为 C++ 时出现编译器警告。但是,这两种方法都可以工作并获得相同的结果,因此您的代码没有问题。

通过正确的字节数将值适当地提前,结果被强制转换回 IMAGE_BASE_RELOCATION 指针,因为它现在应该指向下一个块的开头(下一个 IMAGE_BASE_RELOCATION结构)。

顺便说一句,当您有一个 current_base_relocation->SizeOfBlock 为零的条目时,您就会知道您已经到达块的末尾。