pwn20
1.提交格式
提交ctfshow{【.got表与.got.plt是否可写(可写为1,不可写为0)】,【.got的地址】,【.got.plt的地址】}
4 个问题 2 个”能不能写” 2 个”地址是多少”
2. IDA
F5 反编译 main 函数,核心逻辑非常短:
1 | int main(int argc, const char **argv) { |
总结:
1 | 你给它一个地址 → 它往里写 "RELR" → 读出来显示给你 |
| 地址可写 | 地址不可写 |
|---|---|
打印 RELRO: 52454c52 |
程序直接段错误崩溃 |
程序本质上就是一个 GOT 表可写性测试器。
3.前置基础:程序怎么找到函数
先理解程序怎么调用函数
代码里有一行printf("hello")
但是printf的真实代码在哪?它不在程序里,在一个叫libc的公共库里
问题是:编译的时候,编译器根本不知道运行的时候libc会被加载到内存的哪个位置
3.1 两张表
程序内部准备了两张表 一张是PLT表 一张是GOT表
PLT表是中转站,负责任务分发GOT表是电话簿,记录每个函数真正的内存地址
3.2 GOT表两部分:.got和.got.plt
.got |
.got.plt |
|
|---|---|---|
| 存放内容 | 杂项(全局变量的地址、动态链接器的内部数据等) | 函数指针(每个外部函数对应一个 GOT 条目) |
| 条目数量 | 很少(2-4 条) | 较多(每个导入函数一条) |
| 是攻击目标吗 | 不太是 | 是的 |
3.3 为什么GOT表需要能写
Linux为了启动快。默认不会在程序启动时把所有函数地址都查好,而是用到谁再查谁(也就是延迟绑定 Lazy Blinding)
| 时机 | GOT 表里 printf 那一栏写的是 |
|---|---|
程序刚启动,还没调用过 printf |
“我还没查呢,去找 ld.so 帮忙查” |
第一次调用 printf |
ld.so 查到地址,填进 GOT 表 |
之后再调用 printf |
地址已经在表里了,直接跳转 |
也就是说GOT表在程序运行过程中是需要被写入的(至少第一次调用时)
4.漏洞点:GOT劫持
漏洞在于如果GOT表是可随意更改的 黑客就可以
1 | 原来 GOT 表里: printf → 0x7f1234567890 (libc 里 printf 的地址) |
之后程序只要调用printf("/bin/sh"),实际执行的就是system("/bin/sh")—— 拿到 shell。
也就是GOT劫持(GOT Hijacking****)
5.RELRO:给GOT上锁
为了防GOT劫持,系统出了一个保护叫RELRO(RELocation Read-Only,把重定位相关的表设为可读)
5.1 三种等级
| 等级 | 保护程度 | .got 能写? | .got.plt 能写? | 备注 |
|---|---|---|---|---|
| No RELRO | 🔓 完全没上锁 | ✅ 能写 | ✅ 能写 | 想怎么改就怎么改 |
| Partial RELRO | 🔐 上了一半锁 | ❌ 不能写 | ✅ 能写 | 杂项页.got锁了,但是函数地址页.got.plt还能写(因为要支持延迟绑定) |
| Full RELRO | 🔒 锁死了 | ❌ 不能写 | ❌ 不能写 | 启动时一次性把所有地址函数查好填完,然后整本电话簿焊死。没法修改了。 |
5.2 怎么判断等级
| 方法 | No RELRO | Partial RELRO | Full RELRO |
|---|---|---|---|
checksec |
No RELRO |
Partial RELRO |
Full RELRO |
程序头里是否有 GNU_RELRO段? |
❌ | ✅ | ✅ |
动态段里是否有 BIND_NOW? |
❌ | ❌ | ✅ |
6.解题
6.1 可写性
第一步用checksec看一眼

RELRO:NO RELRO没有保护
NO RELRO就是两张表都能写 所以前两个空填 1 和 1
6.2 找两张表地址
第二步用readelf找地址
readelf -S pwn20 | grep -A "\.got"

就知道了.got和.got.plt的地址 并且标志是WA(可写)
6.3 可选验证:运行程序试一下
程序本身就可以验证。给它地址,它能写进去就说明可写
写.got表

52454c52="RELR"写入成功
写.got.plt表

ctfshow{1_1_0x600f18_0x600f28}
相关笔记
RELRO 三部曲:
前置基础:
- pwn1 —
checksec查看安全保护 - pwn25 ret2libc 栈溢出利用 (NX 绕过) — GOT 泄露 + ret2libc 实战