gpt4 book ai didi

c - 如何反转 R_X86_64_JUMP_SLOT 重定位?

转载 作者:行者123 更新时间:2023-12-04 03:36:23 26 4
gpt4 key购买 nike

我正在构建一个 ELF 二进制文件,它需要能够在运行时处理和反转其自身的重定位。 (显然,反转将发生在单独的缓冲区中,而不是原始代码页中。)这样做的目的是内存中的模块内容可以进行 HMAC 运算,并与从磁盘上的模块计算出的已知良好值进行比较,以确保没有发生腐败。我知道这有点不寻常,但这是我们必须遵守的标准要求。

我已经能够反转二进制中的所有重定位,除了发生在全局偏移表中的R_X86_64_JUMP_SLOT 重定位。 .使用 readelf -a mylib.so 查看我的测试模块的 .rela.plt 部分中的重定位条目,我看到了这些重定位:

Relocation section '.rela.plt' at offset 0x968 contains 20 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000005018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 printf + 0
000000005020 002000000007 R_X86_64_JUMP_SLO 0000000000001ac5 processRelocations + 0
000000005028 000300000007 R_X86_64_JUMP_SLO 0000000000000000 memcpy + 0
000000005030 000400000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
...

这些偏移量指向全局偏移量表(特别是 .got.plt),因此我可以使用 objdump -d -s -j .plt -j .got.plt 获取更多信息mylib.so:

Disassembly of section .got.plt:

0000000000005000 <_GLOBAL_OFFSET_TABLE_>:
5000: 80 4e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .N..............
...
5018: 10 10 00 00 00 00 00 00 20 10 00 00 00 00 00 00 ........ .......
5028: 30 10 00 00 00 00 00 00 40 10 00 00 00 00 00 00 0.......@.......
...

Disassembly of section .plt:

0000000000001000 <.plt>:
1000: ff 35 02 40 00 00 pushq 0x4002(%rip) # 5008 <_GLOBAL_OFFSET_TABLE_+0x8>
1006: f2 ff 25 03 40 00 00 bnd jmpq *0x4003(%rip) # 5010 <_GLOBAL_OFFSET_TABLE_+0x10>
100d: 0f 1f 00 nopl (%rax)
1010: f3 0f 1e fa endbr64
1014: 68 00 00 00 00 pushq $0x0
1019: f2 e9 e1 ff ff ff bnd jmpq 1000 <.plt>
101f: 90 nop
1020: f3 0f 1e fa endbr64

请注意,此二进制文件是小尾数法。所以 .got.plt 中的偏移量,即 0x1010, 0x1020, 0x1030... 似乎总是指向相应的 endbr64 指令PLT条目。这类似于 this answer 中的信息其中引用“在启动时,动态链接器用指向适当 PLT 条目的第二条指令的地址填充 GOT 槽。”但是,在我的例子中,它似乎指向 PLT 条目中的第四条指令。该答案进一步表明,此重定位是通过将模块的基地址添加到原始 GOT 值来完成的。

但是,当我运行我的测试程序并查看动态链接后内存中的实际值时,这并不是我所期望的。例如,现在运行它,processRelocations0x5020 的 GOT 条目以值 0x7FF06A0F5AC5 结束。该次运行时我的模块在内存中的基地址是 0x7ff06a0f4000。减去它会得到 0x1AC5,它实际上看起来是该函数的符号表条目的值:

Symbol table '.dynsym' contains 34 entries:
Num: Value Size Type Bind Vis Ndx Name
...
32: 0000000000001ac5 491 FUNC GLOBAL DEFAULT 10 processRelocations

然而,符号表条目并不是我想要的;我需要返回到 0x1020 的原始值,而且我在符号表中的任何地方都看不到该值。

如何在运行时反转这些重定位以找到它们的原始值?

最佳答案

您可以通过使用 -fno-plt 进行编译来回避这个问题,这样您根本就没有任何 PLT 条目,并且相关的惰性绑定(bind)机制也不会发挥作用。

GCC and clang will use 调用 *printf@GOTPCREL(%rip) 强制早期绑定(bind):在进程启动时解析 GOT 条目。这使得每次调用 more efficient , 并且一些发行版(例如 Arch GNU/Linux)已经以这种方式编译它们的包。

TL:DR:这通常是一个不错的选择,只是在当前的 GCC 和 clang 发行版配置中默认情况下(尚未)启用。

关于c - 如何反转 R_X86_64_JUMP_SLOT 重定位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66810305/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com