与一位朋友谈论了如何在PE文件中寻址。他告诉我,PE文件中的所有地址在通过relocation table
(.reloc
)加载时都会更改。我告诉他,我从未在PE文件中见过这些表,所有的寻址都是相对于可执行指令的。我相信我是对的,因为我不得不通过将lea
中的第二个操作数更改为相对于lea
地址到变量的偏移量来修补程序。
但经过一番研究,我发现这样的table确实存在。所以我有几个问题。
1.只是一笔遗产?我在IDA中打开了几个.exe x64
文件,但没有看到.reloc
段。
1.如果这种技术真的存在,为什么lea
在运行时每次都计算实际地址(通过添加IMAGE BASE
),如果我们可以在加载时将正确的地址放在任何地方?
1.如果它不是遗留的,那么如果x86/x64中存在相对寻址,为什么在真实的任务中需要它?
1条答案
按热度按时间afdcj2ne1#
重新定位表仍然存在。它们不需要在
.reloc
节中,重要的是“可选头”(对于可执行文件不是“可选”)中数据目录数组的Relocation Direction RVA条目指向它。但是,它通常位于.reloc
部分。只是一笔遗产?我在IDA中打开了几个.exe x64文件,但没有看到.reloc段。
我在notepad.exe,calc.exe(非常小的重定位部分),7z.exe,subl.exe,各种其他常用工具中找到了这样的部分。并不罕见我没有使用IDA,而是使用了CFF Explorer。
通常在x64上,为了表示相对于IMAGE BASE固定的地址,使用RIP相关
lea
(或一般而言RIP相关寻址),它将在其后面的字节地址(而不是IMAGE BASE)添加一个常量偏移。x64没有很多地方可以在指令中直接使用64位绝对地址(64位地址可以加载到寄存器中,与任何64位整数相同,或者用作地址,但仅在mov
中到rax/eax/ax/al
和从rax/eax/ax/al
使用),使得完全依赖于重定位变得不方便(尽管可能)。另一方面,重定位对于更新存储在数据段中的地址是有用的,这些地址通常是绝对地址(否则它们使用起来会不方便,使它们与RIP相关根本不起作用(RIP),并且放置原始RVA可以起作用,但需要在每次使用时手动添加IMAGE BASE)。对于ARM、MIPS、RISC-V等其他架构,重新定位可能更重要(也可能更复杂)。
与维基百科说的相反:
当在Windows Vista及以上版本上运行原生64位二进制文件时,ASLR是强制性的,因此编译器不能省略重定位部分。
如果不使用重定位,那么重定位部分当然可以省略,并且您可以创建这样的非平凡可执行文件。不要使用绝对地址。或者自己修补。