[ pwn 学习 ] CTFshow-pwn21 Partial RELRO
1. 基础信息

和 pwn20 唯一区别:RELRO 从 No RELRO 变成 Partial RELRO。
2. 回顾:RELRO 三等级
| 等级 | .got 能写? |
.got.plt 能写? |
|---|---|---|
| No RELRO | ✅ | ✅ |
| Partial RELRO | ❌ | ✅ |
| Full RELRO | ❌ | ❌ |
Partial RELRO 的取舍:
.got里的数据初始化后不会再变 → 锁掉.got.plt因为延迟绑定还要填函数地址 → 留着能写
3. 找两张表地址
段表 -S 说的都能写,别信。程序头 -l 里 GNU_RELRO 圈起来那块,运行时会被锁成只读。
3.1 readelf -S 先看段表
段表里两张表都标 WA(可写),但段表是静态声明,运行时由程序头决定。

| 段名 | 地址 | 说明 |
|---|---|---|
.got |
0x600ff0 | 杂项数据 |
.got.plt |
0x601000 | 外部函数地址表 |
3.2 readelf -l 再看程序头(真正权限)
readelf -l pwn21:

| 字段 | 值 | 含义 |
|---|---|---|
| VirtAddr | 0x600e10 | 保护区起始 |
| MemSiz | 0x1f0 | 保护区大小 = 496 字节 |
| Flags | R | 只读 |
保护区范围 = [0x600e10, 0x601000)
对照段地址:
1 | 保护区范围:[0x600e10 —————————— 0x601000) |
Section to Segment 映射也验证了 .got.plt 不在 GNU_RELRO 内:

4. 解题
Partial RELRO→.got不可写(0)、.got.plt可写(1).got地址 →0x600ff0.got.plt地址 →0x601000
1 | ctfshow{0_1_0x600ff0_0x601000} |