BUUCTF wdb2018_guess题解:Canary绕过与栈溢出利用
1. 题目背景与初步分析
BUUCTF是一个知名的CTF(Capture The Flag)竞赛平台,而"wdb2018_guess"是其中一道经典的pwn题目。这道题目主要考察选手对Canary保护机制的绕过能力,属于二进制安全领域的栈溢出类题目。
Canary(栈保护金丝雀)是一种常见的栈溢出防护机制,它通过在函数栈帧中插入一个随机值(canary值),在函数返回前检查该值是否被修改,从而防止栈溢出攻击。要成功利用这类漏洞,通常需要先泄露canary值,再构造精确的ROP链或shellcode。
2. 环境搭建与题目获取
首先需要准备调试环境,推荐使用以下工具组合:
- Ubuntu 18.04/20.04 LTS(与题目环境匹配)
- pwntools(Python漏洞利用框架)
- gdb-peda(增强版GDB调试工具)
- checksec(检查程序保护机制)
获取题目文件后,先用checksec检查保护情况:
checksec --file=wdb2018_guess预期输出会显示开启Canary和NX(不可执行栈),但未开启PIE(地址随机化),这为我们利用提供了重要线索。
3. 逆向分析与漏洞定位
使用IDA Pro或Ghidra对程序进行逆向分析,重点关注以下函数:
- main函数:程序主逻辑
- 存在漏洞的函数(通常包含不安全的输入操作)
- 可能的信息泄露点
关键发现:
- 程序中存在格式化字符串漏洞,可以用于泄露内存信息
- 存在栈溢出漏洞,但受Canary保护
- 程序加载了某些关键库函数(如system)
4. Canary绕过技术详解
4.1 Canary工作原理
Canary通常位于栈帧的返回地址之前,结构如下:
[局部变量][Canary][EBP][返回地址][参数]在函数返回前,会检查Canary值是否被修改,若被修改则立即终止程序。
4.2 利用格式化字符串泄露Canary
通过构造特定的格式化字符串(如"%n$p"),可以读取栈上指定位置的值。通过反复尝试,可以定位到:
- Canary在栈上的位置(通常距格式化字符串参数6-8个偏移)
- libc基地址(用于计算system等函数地址)
- 程序基地址(如果开启PIE)
关键payload示例:
payload = b"%7$p" # 尝试泄露canary p.sendline(payload) canary = int(p.recvline(), 16)4.3 构造精确溢出payload
获取canary后,需要构造包含以下部分的payload:
- 填充到canary位置的垃圾数据
- 正确的canary值(保持不被修改)
- 覆盖返回地址的ROP链或shellcode地址
典型结构:
[垃圾数据填充][正确canary][EBP覆盖][目标地址][参数]5. 完整利用流程
5.1 信息泄露阶段
- 通过格式化字符串泄露canary值
- 泄露libc基地址(计算system地址)
- 确定其他关键地址(如"/bin/sh"字符串)
5.2 构造ROP链
根据泄露的信息构建ROP链:
- 调用system("/bin/sh")
- 或使用one_gadget(如果有合适条件)
5.3 发送最终payload
精心构造的payload需要:
- 保持canary值不变
- 精确覆盖返回地址
- 设置好参数传递
示例代码片段:
from pwn import * context(arch='amd64', os='linux') p = process('./wdb2018_guess') # 第一阶段:泄露canary p.sendlineafter('>', '%7$p') canary = int(p.recvline(), 16) # 第二阶段:构造ROP rop = ROP('./wdb2018_guess') rop.system(next(elf.search(b'/bin/sh'))) payload = flat( b'A'*offset, canary, b'B'*8, # 覆盖EBP rop.chain() ) p.sendline(payload) p.interactive()6. 调试技巧与注意事项
6.1 常见问题排查
- Canary泄露位置不准确:逐步尝试不同偏移(%6$p到%15$p)
- 栈对齐问题:在ROP链中添加ret指令调整栈对齐
- 地址计算错误:确保使用正确的libc版本
6.2 GDB调试命令
b *0x400123 # 在关键地址下断点 x/20xg $rsp # 查看栈内存 p canary # 查看canary值7. 防御措施与变种
理解攻击方法后,开发者可以采取以下防护:
- 完全禁用格式化字符串(使用安全函数)
- 启用FORTIFY_SOURCE
- 结合ASLR和PIE增加利用难度
- 使用SSP(Stack Smashing Protector)强化版
这道题目的变种可能包括:
- 增加Canary随机化频率
- 移除格式化字符串漏洞但保留其他信息泄露渠道
- 改变内存布局增加定位难度