windows - PE 中的重定位表是遗留的吗?

标签 windows assembly x86 x86-64 portable-executable

与 friend 讨论 PE 文件中的寻址如何工作。他告诉我,PE 文件中的所有地址在通过重定位表 (.reloc) 加载时都会发生变化。我告诉他我从未在 PE 文件中见过这些表,所有寻址都与可执行指令相关。我确信我是对的,因为我必须通过将 lea 中的第二个操作数更改为相对于我的变量的 lea 地址的偏移量来修补程序。

但是经过一番研究,我发现这样的表确实存在。所以我有几个问题。

  1. 这只是一个遗产?我在 IDA 中打开了多个 .exe x64 文件,但没有看到 .reloc 段。
  2. 如果这项技术真的存在,如果我们可以在任何地方放置正确的地址,为什么lea在运行时每次都会计算真实地址(通过添加IMAGE BASE)加载时?
  3. 如果它不是遗留的,如果 x86/x64 中存在相对寻址,为什么在实际任务中需要它?

最佳答案

重定位表仍然存在。它们不需要位于 .reloc 部分,重要的部分是“可选头”(对于可执行文件不是“可选”)中数据目录数组的重定位方向 RVA 条目指向它。但是,它通常位于 .reloc 部分中。

It's just a legacy? I have opened several .exe x64 files in the IDA and don't see the .reloc segment there.

我在例如 notepad.exe、calc.exe(非常小的重定位部分)、7z.exe、subl.exe 以及各种其他常见工具中找到了这样的部分。这并不罕见。不过我没有使用 IDA,我使用的是 CFF Explorer。

通常在 x64 上,要引用相对于 IMAGE BASE 固定的地址,使用 RIP 相对 lea(或一般的 RIP 相对寻址),这会向紧随其后的字节的地址(不是图像库)。 x64 没有很多地方可以在指令中直接使用 64 位绝对地址(64 位地址可以像任何 64 位整数一样加载到寄存器中,或者用作地址,但只能在 >mov 往返于 rax/eax/ax/al),使得完全依赖重定位变得不方便(尽管可能)。

另一方面,重定位对于更新存储在数据段中的地址很有用,这些地址通常是绝对地址(否则它们使用起来会很不方便,使它们相对于 RIP 根本不起作用(其中 RIP ),并且放置原始 RVA 可以工作,但需要在每次使用时手动添加 IMAGE BASE)。对于 ARM、MIPS、RISC-V 等其他架构,重定位可能更重要(也可能更复杂)。

顺便说一下,与维基百科所说相反:

When running native 64-bit binaries on Windows Vista and above, ASLR is mandatory[citation needed], and thus relocation sections cannot be omitted by the compiler.

如果不使用重定位,那么重定位部分当然可以省略,并且您可以创建这样的重要可执行文件。只是不要使用绝对地址。或者自己修补它们。

关于windows - PE 中的重定位表是遗留的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76494223/

相关文章:

assembly - x86 和 x64 中的 ret 指令有什么区别?

c++ - windbg中 "Internal"输出中的 "!heap -h"是什么意思?

windows - 资源脚本 (.rc) 中的主窗口

ios - "Signing Key Required"- 是否可以在 Windows 上使用 DreamWeaver CS6 Extended/PhoneGap 创建 iOS 应用程序?

汇编 x86 MASM 循环分析

c - 用于优化给定 CPU 架构的 GCC 选项

assembly - 如何通过OllyDbg查看位于DS段的值

c++ - 静态库缺少 `__imp_` 符号

c - (C 中的内联汇编)有趣的内存段错误

c - 这个movl指令有必要吗?