插件窝 干货文章 怎么深入理解GOT表和PLT表

怎么深入理解GOT表和PLT表

函数 GOT PLT 链接 738    来源:    2025-04-25

深入理解GOT表和PLT表

GOT(Global Offset Table)和PLT(Procedure Linkage Table)是动态链接过程中非常重要的两个数据结构,理解它们对于掌握程序动态链接机制至关重要。

基本概念

GOT (全局偏移表)

  • 全局偏移表(Global Offset Table)是一个存储外部符号地址的数据结构
  • 每个动态链接的程序和共享库都有自己的GOT
  • 位于数据段(.data),因此可以在运行时被修改

PLT (过程链接表)

  • 过程链接表(Procedure Linkage Table)是一个包含跳转指令的代码段
  • 位于代码段(.text),在程序加载时就已经确定
  • 用于延迟绑定(lazy binding)的实现

工作原理

动态链接过程

  1. 首次调用外部函数时

    • 程序通过PLT表跳转
    • PLT表项包含跳转到GOT表项的指令
    • 初始时GOT表项指向PLT表中的解析例程
    • 解析例程查找函数真实地址并更新GOT表
  2. 后续调用同一函数时

    • 直接通过GOT表跳转到真实函数地址
    • 无需再次解析

延迟绑定(Lazy Binding)

  • 动态链接器不会在程序启动时解析所有外部函数
  • 只有在函数第一次被调用时才进行解析
  • 提高了程序启动速度

技术细节

GOT表结构

  • .got:存储全局变量引用
  • .got.plt:存储函数引用
  • 典型GOT表项: GOT[n]: 0xXXXXXXXX (函数实际地址)

PLT表结构

  • 典型PLT表项: assembly PLT[n]: jmp *GOT[n] ; 第一次跳转到解析例程,之后跳转到真实函数 push n ; 压入函数索引 jmp PLT[0] ; 跳转到解析例程

实际观察方法

使用readelf查看

readelf -S executable | grep -E 'plt|got'
readelf -r executable  # 查看重定位表

使用objdump查看

objdump -d -j .plt executable
objdump -R executable  # 查看动态重定位项

使用gdb调试观察

gdb executable
(gdb) disas function@plt  # 查看函数的PLT条目
(gdb) x/x &function@got.plt  # 查看GOT表中的地址

安全考虑

GOT/PLT劫持攻击

  • 攻击者可能通过修改GOT表项来改变程序控制流
  • 防护措施:
    • RELRO(Relocation Read-Only)保护:
    • Partial RELRO:重定位段在初始化后设为只读
    • Full RELRO:所有重定位在程序启动时完成,整个GOT设为只读

编译选项

gcc -Wl,-z,now -Wl,-z,relro  # 启用Full RELRO

实际应用场景

  1. 动态链接分析:理解程序如何与共享库交互
  2. 二进制分析:逆向工程中的重要知识点
  3. 漏洞利用:某些漏洞利用技术依赖于GOT/PLT操作
  4. 性能优化:理解动态链接开销来源

通过深入理解GOT和PLT表,你可以更好地掌握程序在动态链接环境下的行为,这对于系统编程、安全研究和性能优化都非常重要。