1. 漏洞机理 (The Mechanism)
C 语言不进行数组边界检查。如果向栈上的局部数组(Buffer)写入超过其容量的数据:
- 覆盖局部变量: 破坏程序逻辑。
- 覆盖保存的 %rbp: 破坏上层栈帧。
- 覆盖返回地址 (Return Address): 致命一击。
- 当函数执行
ret时,CPU 会跳转到攻击者写入的地址(如 Shellcode 或 ROP gadget)。
- 当函数执行
2. 攻击形式
- Code Injection: 这里的“数据”包含可执行机器码(Shellcode)。跳转到栈上执行。
- ROP (Return-Oriented Programming): 利用现有的代码片段(Gadgets)串联执行流。对抗 NX/DEP 的主要手段。
攻击原理:
地址 (高) | 栈内存内容 (4字节/格) | 说明 / 寄存器指向
-----------+-------------------------------+-----------------------
0xbffffc98 | [ ...... ] | 调用者(Caller)的栈内容
0xbffffc94 | [ Old EBP (0xbffffcxx) ] | <- 调用 getline 前的 %ebp
0xbffffc90 | [ 0x08048643 ] | 返回地址 (Return Address)
-----------+-------------------------------+-----------------------
0xbffffc8c | [ 0xbffffc94 ] | 保存的旧 %ebp (Saved %ebp) <--- %ebp
0xbffffc88 | [ [?] ] | 局部变量空间 (1)
0xbffffc84 | [ [?] ] | 局部变量空间 (2) - 缓冲区起点
0xbffffc80 | [ [?] ] | 局部变量空间 (3)
0xbffffc7c | [ [?] ] | 局部变量空间 (4)
0xbffffc78 | [ 0x00000001 ] | 保存的 %esi (Saved %esi)
0xbffffc74 | [ 0x00000002 ] | 保存的 %ebx (Saved %ebx) <--- %esp
-----------+-------------------------------+-----------------------
地址 (低) | (向下增长) |地址 (高) | 栈内存内容 (十六进制) | 溢出后的状态
-----------+-------------------------------+-----------------------
0xbffffc94 | [ 0xbffffcxx ] | (尚未被淹没)
0xbffffc90 | [ 0x080486 00 ] | 返回地址被覆盖!最后 43 变 00 (\0)
-----------+-------------------------------+-----------------------
0xbffffc8c | [ 0x31 30 39 38 ] | Old EBP 被淹没!("8901")
0xbffffc88 | [ 0x37 36 35 34 ] | 缓冲区后半段 ("4567")
0xbffffc84 | [ 0x33 32 31 30 ] | 缓冲区前半段 ("0123") <--- 缓冲区起点
-----------+-------------------------------+-----------------------
0xbffffc80 | [ [?] ] |
0xbffffc7c | [ [?] ] |
0xbffffc78 | [ 0x00000001 ] |
0xbffffc74 | [ 0xbffffc84 ] | gets 参数 (指向 0xbffffc84)
-----------+-------------------------------+-----------------------
地址 (低) | (崩溃点) |3. 对抗防御 (Defenses)
这也是一场“道高一尺魔高一丈”的军备竞赛:
| 防御技术 | 机制 (Mechanism) | 绕过思路 (Bypass) |
|---|---|---|
| Stack Canary (金丝雀) | 在 Return Address 之前插入一个随机值。函数返回前检查该值是否被修改。 | 泄漏 Canary 值;爆破(Fork Server);覆盖异常处理链。 |
| NX / DEP (不可执行) | 标记栈和堆为不可执行 (No-Execute)。 | ROP (利用代码段已有的指令)。 |
| ASLR (地址随机化) | 每次运行程序时,栈、堆、库的位置随机变化。 | 信息泄漏 (Info Leak);堆喷射 (Heap Spray)。 |