当前位置: 首页 > news >正文

【学习记录】Week2(一):深入 ELF 结构视图与 .got/.plt 节区作用详解

写在前面:进入 Week2,我们需要把目光从宏观的保护机制下沉到微观的文件结构中。在平时用readelfobjdump分析二进制时,我们经常会看到“节区”和“段”这两个词。它们到底有啥区别?我们天天喊的“打 GOT 表”,GOT 表到底在文件结构的哪个位置?本文将为你彻底讲透。

📑 目录

  1. ELF 双视图:节区 与 段 的本质区别
  2. 核心节区速览
  3. 动态链接的枢纽:.plt 与 .got 详解
  4. PWN 视角:为什么要区分 .got 和 .got.plt?

1. ELF 双视图:节区 与 段 的本质区别

ELF (Executable and Linkable Format) 文件可以从两个不同的维度来看待:链接视图执行视图。这也是节区和段的最根本区别。

1.1 链接视图(节区 Section)

  • 服务对象:链接器。
  • 作用:链接器需要知道代码放在哪、数据放在哪、符号表在哪。因此 ELF 被划分成了无数个细分的“节区”。
  • 特点:粒度极细。比如.text(代码)、.data(已初始化全局变量)、.bss(未初始化全局变量)都是独立的节区。

1.2 执行视图(段 Segment)

  • 服务对象:操作系统的程序加载器。
  • 作用:加载器在把程序载入内存时,不需要知道.text.rodata的区别,它只关心“这块内存需要可读可执行,那块内存需要可读可写”。为了节约内存页的开销,加载器会将多个属性相同的节区合并成一个“段”来加载。
  • 特点:粒度较粗。

💡 假设性说明(模拟readelf输出):
假设我们在终端输入readelf -l vuln(查看段信息),你会在输出中看到类似这样的对照关系:

Section to Segment mapping: Segment Sections... 00 .interp 01 .interp .note.gnu.property .note.ABI-tag ... 02 .init .plt .plt.got .text .fini <-- 合并成了可执行段 03 .rodata .eh_frame_hdr .eh_frame <-- 合并成了只读段 04 .init_array .fini_array .dynamic .got .data .bss <-- 合并成了可读写段

从上面的模拟输出可以直观看到:.plt.text被打包在一起执行;而.got.data被打包在一起读写。节区是逻辑划分,段是物理装载。

2. 核心节区速览

在 PWN 中,我们最常打交道的几个节区如下:

节区名称说明PWN 关注度
.text存放程序编译后的机器指令。通常只读可执行。⭐⭐⭐ (找 ROP Gadget、后门函数)
.bss存放未初始化的全局/静态变量。运行时在内存中分配并清零。⭐⭐ (ret2shellcode 或 堆利用占位)
.data存放已初始化的全局/静态变量。⭐⭐ (查数据)
.rodata只读数据,比如字符串常量"/bin/sh"⭐⭐⭐ (找/bin/sh地址)
.got/.plt动态链接跳板与地址表。⭐⭐⭐⭐⭐ (核心攻击目标)

3. 动态链接的枢纽:.plt 与 .got 详解

在 Week1 我们讲过“懒绑定”机制,程序在第一次调用外部函数时才去寻找真实地址。这个过程就是靠.plt.got配合完成的。

3.1 .plt (过程链接表)

  • 属性:属于代码段,可读可执行(通常不可写)。
  • 作用:它是一段段极其精简的跳板代码。程序中call printf,实际上汇编是call printf@plt
  • 内部结构:每个外部函数在.plt中都有一个小项(比如 16 字节)。它的核心逻辑是:“去.got表里查地址并跳转过去”

3.2 .got (全局偏移表)

  • 属性:属于数据段,可读可写(除非开启了 Full RELRO)。
  • 作用:它本质上是一个指针数组。每个表项占 4 字节(32位)或 8 字节(64位),用来存放外部函数在 libc 中的真实绝对地址。

4. PWN 视角:为什么要区分 .got 和 .got.plt?

readelf -S查看节区时,你可能会发现有两个长得像 GOT 的东西:.got.got.plt。它们有什么区别?

4.1.got

这个表主要用于存放全局变量的地址(比如引用其他动态库中的全局变量)。在 PWN 中较少直接作为主要攻击目标。

4.2.got.plt(重点中的重点)

这个表专门用于存放外部函数的真实地址(如puts,system,gets)。这就是我们常说的“打 GOT 表”的那个表。

.got.plt表的特殊结构(前 3 项是特殊数据):

  1. 第一项:存放.dynamic节的地址(动态链接器使用)。
  2. 第二项:存放link_map结构的地址(动态链接器使用)。
  3. 第三项:存放动态链接解析函数_dl_runtime_resolve的地址。
  4. 第四项及以后:才是我们熟悉的puts@gotgets@got等。

4.3 攻击逻辑复盘

在 Partial RELRO(部分保护)下,.got.plt是可写的。

  1. 程序调用puts,第一次执行时,动态链接器找到puts在 libc 的地址,比如0x7ffff7a649c0,然后把这个地址写入.got.plt表中puts对应的表项里。
  2. 下次再调用puts,程序直接从.got.plt读出0x7ffff7a649c0并跳转。
  3. 攻击发生:如果我们通过栈溢出或格式化字符串漏洞(任意地址写),把.got.plt表中puts的表项内容,篡改成system函数的地址0x7ffff7a4c440
  4. 程序再次执行puts("hello")时,去.got.plt读地址,读出的是system的地址,于是实际执行了system("hello")

这就是经典的GOT Table Overwrite(GOT 表覆写)攻击。而开启 Full RELRO 的原理,就是在程序启动时一口气解析完所有函数地址填入.got.plt,然后直接把这块内存设为只读,从根源上掐断覆写可能。

5. 结语

理解了 ELF 的双视图以及.got.plt表的精确结构,我们就能在后续实战中精准地算出目标函数 GOT 表的绝对地址。下一步,我们将学习如何利用泄露出来的地址,反查libc版本并计算system函数的偏移量。

如果本篇文章对您有帮助,请点赞收藏支持一下,感谢阅读!我们下一部分见!🙏

http://www.jsqmd.com/news/1091028/

相关文章:

  • 如何快速掌握NDS游戏文件编辑器:Tinke的完整使用指南
  • 还在愁论文框架搭不好?9款AI论文写作软件一键生成逻辑连贯初稿!
  • 程序员真正的天花板,不是技术,是表达
  • 如何彻底解决Cursor试用限制:从设备指纹识别到一键重置的完整指南
  • 音频混音原理(MIXer)
  • 毕业生必备:9款免费AI写作辅助平台,一键生成开题报告与论文大纲
  • Ubuntu 磁盘排查必备:sudo du -sh * 与 du -shx /var/lib/docker 用法详解与实战
  • 基于STM32+FPGA的驱控一体伺服控制器:从硬件架构到FreeRTOS任务调度的设计实践
  • 2026好用的命理软件推荐给进阶用户:工具箱、学习路径和资料安全怎么选
  • 从零构建企业级iSCSI存储:Openfiler安装与基础服务配置实战
  • FreeRTOS源码详解(八)——Event
  • SGLang vs vLLM:优先级调度、限流、淘汰策略对比
  • 从Swin到Video Swin:时空Transformer如何重塑视频理解
  • 基于 Self-RAG 与列表级重排序的进阶 RAG 系统设计与实现
  • 从图形化到代码:基于ESP8266与米思齐的温室大棚控制逻辑深度解析
  • AI赋能Burp Suite:智能Web漏洞扫描与WAF绕过实战解析
  • “AI编程工具2026盘点:这5个工具让程序员效率翻倍“
  • TPA3128D2评估板设计解析:从D类功放原理到硬件实战配置
  • ESP8266 NodeMCU物联网实战速成(基于Arduino IDE)——从环境搭建到MQTT全链路开发
  • 统信UOS 1060右键菜单精修:从系统级到用户级的打开方式管理全攻略
  • 使用AWS Workload Credentials Provider在EKS中管理应用密钥的实践
  • 阿里云盘Refresh Token获取终极指南:3分钟扫码搞定自动化管理
  • TS泛型坑,编译懵!
  • 每日一题————2026-6-28 最长上升子序列加强版(线性DP版)
  • 世界模型、元宇宙、数字孪生、物理AI:它们是一回事吗?
  • AR 镀膜技术原理:为什么能减少反光?——悟赫德护景贴观复盾的抗反射实现
  • 第11天:进程基础内核认知:PCB与task_struct结构体解析
  • 企业官网的信息架构设计:从内容建模、导航到 URL 与内链
  • FreeRTOS源码详解(一)——申请和释放内存
  • MTEX工具箱:如何用5个关键功能解决材料科学家的晶体学分析难题