BUUCTF wdb2018_guess题解:Canary绕过与栈溢出利用

发布时间:2026/11/2 3:23:13
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函数:程序主逻辑
  • 存在漏洞的函数(通常包含不安全的输入操作)
  • 可能的信息泄露点

关键发现:

  1. 程序中存在格式化字符串漏洞,可以用于泄露内存信息
  2. 存在栈溢出漏洞,但受Canary保护
  3. 程序加载了某些关键库函数(如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:

  1. 填充到canary位置的垃圾数据
  2. 正确的canary值(保持不被修改)
  3. 覆盖返回地址的ROP链或shellcode地址

典型结构:

[垃圾数据填充][正确canary][EBP覆盖][目标地址][参数]

5. 完整利用流程

5.1 信息泄露阶段

  1. 通过格式化字符串泄露canary值
  2. 泄露libc基地址(计算system地址)
  3. 确定其他关键地址(如"/bin/sh"字符串)

5.2 构造ROP链

根据泄露的信息构建ROP链:

  1. 调用system("/bin/sh")
  2. 或使用one_gadget(如果有合适条件)

5.3 发送最终payload

精心构造的payload需要:

  1. 保持canary值不变
  2. 精确覆盖返回地址
  3. 设置好参数传递

示例代码片段:

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 常见问题排查

  1. Canary泄露位置不准确:逐步尝试不同偏移(%6$p到%15$p)
  2. 栈对齐问题:在ROP链中添加ret指令调整栈对齐
  3. 地址计算错误:确保使用正确的libc版本

6.2 GDB调试命令

b *0x400123 # 在关键地址下断点 x/20xg $rsp # 查看栈内存 p canary # 查看canary值

7. 防御措施与变种

理解攻击方法后,开发者可以采取以下防护:

  1. 完全禁用格式化字符串(使用安全函数)
  2. 启用FORTIFY_SOURCE
  3. 结合ASLR和PIE增加利用难度
  4. 使用SSP(Stack Smashing Protector)强化版

这道题目的变种可能包括:

  • 增加Canary随机化频率
  • 移除格式化字符串漏洞但保留其他信息泄露渠道
  • 改变内存布局增加定位难度