.plt
:在可再生能源段中,蹦床在plt[n]
上起作用,除0外,在plt[0]
上具有.got.plt解析器链接
.got
.got.plt
:在可读写的网段中,仅提供地址
我从这篇文章中学到了什么: https://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/
实际的Linux shell命令给了我一个不同的答案
$readelf -l /bin/bash
我转储了两个部分(plt,plt.got)并得到了这个程序集
.plt是我所学的:
.plt.got,这是做什么用的?
对不起,这是因为
objcopy -O binary --only-section=.plt.got /bin/bash ./pltgot
objcopy -O binary --only-section=.plt /bin/bash ./plt
答案 0 :(得分:2)
查看问题的答案。希望它能对您有所帮助。
区别在于.got.plt是运行时可写的,而.got如果启用了针对称为RELRO(重定位为只读)的GOT覆盖攻击的防御,则不是.got。要启用RELRO,请使用ld选项-z relro。 RELRO将必须为运行时可写的GOT条目进行延迟绑定,并将其放置在.got.plt中,并将所有其他条目放置在只读.got节中
差异或这种设计是作为ELF通用标准文件格式的一部分出现的:
ELF二进制文件通常包含一个单独的名为.got.plt的GOT节,用于在延迟绑定过程中与.plt一起使用
Q1参考资料第45页: 丹尼斯·安德里斯(Andriesse),实用的二进制分析:构建自己的Linux工具进行二进制检测,分析和反汇编。 ,2019年
第二季度参考资料第45页 :同一本书,请参见“延迟绑定和PLT”一节
答案 1 :(得分:2)
.plt
和.plt.got
之间的区别在于.plt
使用延迟绑定,而.plt.got
使用非延迟绑定。
当对函数的所有使用都是简单的函数调用时,可以进行延迟绑定。但是,如果任何东西都需要函数的地址,则必须使用非延迟绑定,因为绑定只能在调用函数时发生,而且我们可能需要在第一次调用之前知道地址。请注意,获取地址时,将直接访问GOT条目。只有函数调用通过.plt
和.plt.got
传递。
如果使用-fno-plt
编译器选项,则不会同时发出.plt
和.plt.got
,并且函数调用也将直接访问GOT条目。
在以下示例中,objdump -d
用于反汇编,readelf -r
用于列出重定位。
.plt
以x64-64为例,.plt
将包含以下条目:
0000000000014050 <_Unwind_Resume@plt>:
14050: ff 25 3a e6 0e 00 jmpq *0xee63a(%rip) # 102690 <_Unwind_Resume@GCC_3.0>
14056: 68 02 00 00 00 pushq $0x2
1405b: e9 c0 ff ff ff jmpq 14020 <.plt>
第一个jmpq
到GOT条目,而第二个jmpq
如果尚未绑定GOT条目,则执行延迟绑定。
.plt
的相关GOT条目的重定位在.rela.plt
部分中,并使用R_X86_64_JUMP_SLOT
,这使动态链接程序知道它们是惰性的。
0000000000102690 0000004600000007 R_X86_64_JUMP_SLOT 0000000000000000 _Unwind_Resume@GCC_3.0 + 0
.plt.got
.plt.got
包含仅需一个jmpq
的条目,因为它们并不懒惰:
0000000000014060 <memset@plt>:
14060: ff 25 5a ea 0e 00 jmpq *0xeea5a(%rip) # 102ac0 <memset@GLIBC_2.2.5>
14066: 66 90 xchg %ax,%ax
.plt.got
的相关GOT条目的重定位在.rela.dyn
部分(以及其余的GOT重定位)中,动态链接程序立即将其绑定:
0000000000102ac0 0000004b00000006 R_X86_64_GLOB_DAT 0000000000000000 memset@GLIBC_2.2.5 + 0