【问题标题】:.plt .plt.got what is different?.plt .plt.got 有什么不同?
【发布时间】:2020-01-24 08:32:37
【问题描述】:

.plt :在 RE 能段中,蹦床在 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

got.plt 不见了,02 段中的.plt.got 是什么?

我转储了两个部分(plt,plt.got)并得到了这个程序集

.plt 是 plt 我了解到的:

.plt.got ,这是干什么用的?

抱歉倾销不好,这是由

objcopy -O binary --only-section=.plt.got /bin/bash ./pltgot
objcopy -O binary --only-section=.plt /bin/bash ./plt

问题

  1. .plt 和 .plt.got 有什么区别
  2. 为什么会出现这种差异?

【问题讨论】:

  • 不要发布文字图片。将您的 readelf 输出复制/粘贴到代码块中,最好只是相关部分。除此之外的好问题,但这是一个大问题。
  • 感谢编辑,我担心只是感谢评论也违反规则,可能会杀死帖子。但是仍然没有答案,我认为帖子会淹没在stackoverflow中的深暗存储中。我的意思是……嗯……谢谢你的建议!我会尽量对stackoverflow编辑风格更友好。
  • 现在用edit 解决您的问题还为时不晚。如果不是文字图片,我会赞成它。顺便说一句,您可以使用 objdump -d --section=.plt.got 而不是先将其转储到平面二进制文件中。请参阅手册页中的 -j 选项。您还可以在一次调用中使用 -j / --section 两次来反汇编这两个部分。
  • 顺便说一句,一些现代 Linux 系统(例如 Arch)使用 gcc -fno-plt 编译软件包,因此在 /bin/bash 或其他二进制文件中没有 .plt.plt.got 部分。

标签: matplotlib assembly x86-64 elf dynamic-linking


【解决方案1】:

查看您的问题的答案。希望对您有所帮助。

  1. 不同之处在于 .got.plt 是运行时可写的,而 .got 不是如果您启用了针对称为 RELRO 的 GOT 覆盖攻击的防御(重定位只读)。要启用 RELRO,请使用 ld 选项 -z relro。 RELRO 将 GOT 条目放置在 .got.plt 中,对于惰性绑定必须是运行时可写的,而所有其他条目则放在只读的 .got 部分中

  2. 这种差异或这种设计已经作为 ELF 通用标准文件格式的一部分存在:

    ELF 二进制文件通常包含一个名为 .got.plt 的单独 GOT 部分,用于在惰性绑定过程中与 .plt 结合使用

第一季度参考第 45 页: Andriesse,Dennis。实用二进制分析:构建您自己的 Linux 工具,用于二进制检测、分析和反汇编。旧金山,No Starch Press , 2019

Q2 Ref Page 45:同一本书,参见“惰性绑定和 PLT”部分

【讨论】:

  • 非常感谢您的帮助,很抱歉我完全脱离了这个话题......并且检查得太晚了。
【解决方案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条目,如果GOT条目尚未绑定,第二个jmpq执行惰性绑定。

.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

【讨论】:

  • 您的反汇编代码来自objdump -d,但R_X86_64_JUMP_SLOTR_X86_64_GLOB_DAT 的行来自什么? readelf,或objdump 的不同选项?
  • 他们来自readelfobjdump -R 也可以,但它不显示哪些部分包含重定位。
  • 好的,很酷。通常,最好提及生成您在答案中显示的输出的命令,以便未来的读者可以自己尝试。 (edit 甚至比仅仅一个评论更好。)顺便说一句,还值得指出的是 .plt.got 非惰性条目是 gcc -fno-plt code-gen 使用的,这是某些发行版(如 Arch)的默认值Linux。
  • -fno-plt 不使用.plt.got,所以我也编辑了答案以涵盖它。
  • 错了,只是直接 GOT 条目,使用 R_X86_64_GLOB_DAT 就像 .plt.got 一样,谢谢。
猜你喜欢
  • 1970-01-01
  • 2012-11-23
  • 2011-07-25
  • 2014-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多