CTF PWN 利用开发
把二进制内存破坏转化为代码执行。
环境约定
$PY= 64 位解题 Python(含 pwntools/z3/capstone/unicorn/ropgadget 等)。 环境不确定时先运行 ctf-router 技能的scripts/env-check.py自检。- checksec:pwntools 自带,
$PY -m pwn checksec <elf>或checksec --file=<elf>。 - ROPgadget:Kali 内
ROPgadget --binary <elf>;或 pwntools 的ROP()自动找 gadget。 - gdb 调试:仅 Linux 可执行文件能跑,Windows 用户走 WSL:
wsl -d <distro> -- bash -lc "gdb <elf>"。 - 反汇编:优先 Ghidra 无头分析(
analyzeHeadless,需 Java 17+); 或 pwntoolsdisasm()/asm()。
约定:利用脚本写在题目目录下,用 $PY exploit.py 运行。
工作流
- 识别:
$PY -c "import magic; print(magic.from_file('bin'))"看架构(x86/x64/ARM)。 - 保护机制:
$PY -m pwn checksec bin(Windows 上查 ELF 保护可用,运行仍需 Linux)。 - 按保护选路线(决策树):
- No PIE + Partial RELRO → GOT 覆写(最简单,地址全固定)
- NX 开 → 不能直接执行 shellcode,用 ROP / ret2win / ret2libc
- Canary → 先泄露 canary(格式化字符串)或改走堆
- Full RELRO → 改打
__free_hook/返回地址/FSOP
- 找偏移:
$PY -c "from pwn import *; print(cyclic(200).decode())"送进去, 崩溃后用cyclic_find(0x...)算偏移。 - 写利用:pwntools 模板见下。
- 远程:
remote(host, port);题目给了 libc 就本地对齐偏移。
常用命令速查
# 保护机制
$PY -m pwn checksec bin
# 找 gadget(Kali/WSL 内)
wsl -d kali-linux -- bash -lc "ROPgadget --binary /mnt/c/path/bin | grep 'pop rdi'"
# 生成/解析 cyclic 偏移
$PY -c "from pwn import *; print(cyclic(200))"
$PY -c "from pwn import *; print(cyclic_find(0x61616168))"
# Ghidra 无头反汇编(路径按实际安装位置调整)
analyzeHeadless <proj_dir> pwn_tmp -import bin -postScript ExportStrings.py
pwntools 骨架(远程/本地通用)
from pwn import *
context.binary = './bin' # 自动架构/位宽
context.log_level = 'debug'
io = remote('host', 1234) # 本地: process('./bin')
# ... recvuntil / sendline / flat(...)
io.interactive()
ret2libc 两阶段:第一阶段 puts@PLT(puts@GOT) 泄露 libc → 返回 main 再进第二阶段
system("/bin/sh")。远程不知道 libc 版本时用 pwn.DynELF 直接解析符号。
技术要点(按题型)
- 栈溢出/ret2win:overflow → 可选
ret对齐(movapsSIGSEGV 就是缺对齐)→pop rdi;ret→ 参数 → win()。偏移 = 缓冲到 rbp 距离 + 8。 - 格式化字符串:
%p链泄露;GOT 覆写打printf@GOT→system;无回显时打__free_hook或.fini_array循环。输入被变换(ROT13 等)先做逆变换。 - 堆:tcache poisoning / double free / unsorted bin attack 泄露 libc;
House of Apple 2(
_IO_FILE+ setcontext);先确认 glibc 版本再选手法 (2.34+ 无__malloc_hook)。 - SROP/seccomp:
sigreturn构造全寄存器;seccomp 白名单时用 ORW(open/read/write)链,pop rdx缺失可用 canary 检查尾声的xor rdx, fs:28h归零。 - shellcode:NX 关 + 无坏字符直接放;有过滤用 XOR 编码或
read()二段式 (小缓冲区先读入完整 shellcode)。
何时换技能
- 看不懂二进制在干什么 → 先用逆向技能分析,再回来利用。
- 本质是 pyjail/编码谜题 → 用 Misc 技能。
- 突破点其实在 Web 接口 → 用 Web 技能。
深度知识库(按需读取,勿全量加载)
本技能目录 references/ctf-pwn/ 下为完整参考文件(含大量真题解法与完整代码):
| 文件 | 内容 |
|---|---|
| overflow-basics.md | ret2win、canary 绕过、解析器溢出、结构体指针覆写、有符号整数绕过 |
| rop-and-shellcode.md | ret2libc 两阶段、ret2csu、DynELF、坏字符 XOR、栈迁移、rdx 控制 |
| rop-advanced.md | 双重栈迁移、SROP、seccomp 绕过、RETF 架构切换、.fini_array 劫持 |
| format-string.md | 泄露、GOT 覆写、盲打、过滤绕过、ROT13 编码格式化串 |
| heap-techniques.md / heap-techniques-2.md | House of Apple/Einharjar/Orange、tcache、musl 堆 |
| heap-fsop.md | _IO_FILE vtable 劫持、stdin 劫持、vtable 校验绕过 |
| advanced.md / advanced-exploits*.md | UAF、ret2dlresolve、类型混淆、字节码沙箱逃逸等进阶手法 |
| kernel*.md | 内核题(QEMU 环境、KASLR/KPTI/SMEP 绕过、modprobe_path) |
| sandbox-escape.md | 自定义 VM、受限 shell、进程隔离绕过 |
| field-notes.md | 堆与进阶手法速查笔记 |
Scan to join WeChat group