pwntools 是 CTF Pwn 题最常用的 Python 库,提供了与二进制程序交互、调试、ROP 链构造等功能。
模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from pwn import * import sys
context.terminal = ['tmux', 'sp', '-h'] context.update(log_level='debug', os='linux', arch='amd64')
if len(sys.argv) > 1 and sys.argv[1] == "r": io = remote('') else: io = process('')
elf = ELF('')
io.interactive()
|
常用函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| io = process('./binary') io = remote('host', port) io = gdb.debug('./binary', gdbscript)
p64(0x41414141) p32(0x41414141) u64(data) u32(data)
io.send(data) io.sendline(data) io.sendafter(delim, data) io.recv(n) io.recvline() io.recvuntil(delim) io.interactive()
elf = ELF('./binary') elf.symbols['main'] elf.got['puts'] elf.plt['puts'] elf.bss() elf.search(b'/bin/sh')
context.arch = 'amd64' shellcode = asm(shellcraft.sh()) shellcode = asm(shellcraft.execve('/bin/sh'))
rop = ROP(elf) rop.call('puts', [elf.got['puts']]) rop.chain() rop.find_gadget(['pop rdi', 'ret'])
libc = ELF('./libc.so.6') libc.symbols['system'] next(libc.search(b'/bin/sh'))
|
pwndbg
pwndbg 是 gdb 的一个增强插件,提供了更友好的界面和强大的堆分析功能。
打印
1 2 3 4 5 6 7
| print *0xAAAA x /20xg 0xAAAA # 以 16 进制格式打印 20 个 8 字节 x /20xw 0xAAAA # 以 16 进制格式打印 20 个 4 字节 x /20xb 0xAAAA # 以 16 进制格式打印 20 个字节 x /20s 0xAAAA # 以字符串格式打印 print *0xAAAA # 打印地址处的值 print $rsp # 打印寄存器值
|
堆
1 2 3 4 5 6 7 8 9 10
| vmmap # 查看内存映射 heap # 显示堆信息 parseheap # 解析堆结构 vis # 可视化堆块 bins # 显示所有 bin fastbins # 显示 fastbin unsortedbin # 显示 unsorted bin smallbins # 显示 smallbin largebins # 显示 largebin tcache # 显示 tcache(glibc 2.26+)
|
其他常用命令
1 2 3 4 5 6 7 8 9
| context # 显示当前上下文(寄存器、栈、代码) break *0x400000 # 在地址处下断点 continue # 继续执行 nexti # 执行下一条汇编指令 stepi # 单步进入(会进入函数) finish # 执行到当前函数返回 backtrace # 显示调用栈 info registers # 显示所有寄存器 disassemble # 反汇编当前函数
|
patchelf
patchelf 用于修改 ELF 文件的动态链接器和库依赖,常用于本地调试时使用指定版本的 libc。
1 2 3 4 5 6 7 8 9 10 11 12
| # 设置动态链接器 sudo patchelf --set-interpreter ./ld-2.23.so ./binary
# 替换库依赖 sudo patchelf --replace-needed libc.so.6 ./libc-2.23.so ./binary
# 添加库依赖 sudo patchelf --add-needed ./libc-2.23.so ./binary
# 查看当前设置 patchelf --print-interpreter ./binary patchelf --print-needed ./binary
|
ROPgadget
ROPgadget 用于在二进制文件中搜索 ROP gadget,是构造 ROP 链的重要工具。
基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # 搜索所有 gadget ROPgadget --binary ./binary
# 搜索特定指令 ROPgadget --binary ./binary --only "pop|ret" ROPgadget --binary ./binary --only "pop rdi"
# 搜索字符串 ROPgadget --binary ./binary --string "/bin/sh"
# 搜索特定字节序列 ROPgadget --binary ./binary --opcode "5fc3" # pop rdi; ret
# 只显示 gadget 地址(不显示指令) ROPgadget --binary ./binary --only "pop|ret" --ropchain
# 生成完整的 ROP 链(如果支持) ROPgadget --binary ./binary --ropchain
|
常用选项
1 2 3 4 5 6
| --binary <file> # 指定二进制文件 --only <instructions> # 只显示包含特定指令的 gadget --string <string> # 搜索字符串 --opcode <bytes> # 搜索字节序列 --depth <n> # 设置搜索深度 --badbytes <bytes> # 排除包含特定字节的 gadget
|
ropper
ropper 是另一个强大的 ROP gadget 搜索工具,功能比 ROPgadget 更强大,支持交互式使用。
基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| # 启动交互模式 ropper
# 在交互模式中搜索 search pop rdi # 搜索包含 "pop rdi" 的 gadget search /1/ pop # 搜索包含 1 个 pop 的 gadget search "pop rdi; ret" # 搜索精确的 gadget
# 命令行模式 ropper --file ./binary --search "pop rdi" ropper --file ./binary --search "pop rdi; ret"
# 生成 ROP 链 ropper --file ./binary --chain "execve" ropper --file ./binary --chain "mprotect"
# 显示所有 gadget ropper --file ./binary
# 搜索特定指令 ropper --file ./binary --opcode "5fc3" # pop rdi; ret
|
高级功能
1 2 3 4 5 6 7 8 9 10 11 12
| # 过滤坏字符 ropper --file ./binary --badbytes "000a0d"
# 设置搜索深度 ropper --file ./binary --depth 5
# 导出 gadget 到文件 ropper --file ./binary --output gadgets.txt
# 搜索 syscall gadget ropper --file ./binary --search "syscall" ropper --file ./binary --search "int 0x80" # 32位
|
seccomp-tools 用于分析和转储 seccomp(Secure Computing)沙箱规则,帮助理解程序的系统调用限制。
基本用法
1 2 3 4 5 6 7 8 9 10 11
| # 转储 seccomp 规则 seccomp-tools dump ./binary
# 反汇编 seccomp bpf seccomp-tools disasm <bpf_file>
# 跟踪系统调用 seccomp-tools trace ./binary
# 从 strace 输出中提取规则 strace ./binary 2>&1 | seccomp-tools dump
|
使用场景
当程序使用 seccomp 限制系统调用时,需要了解哪些系统调用被允许:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| # 运行程序并查看允许的系统调用 seccomp-tools dump ./binary
# 输出示例: # line CODE JT JF K # ================================= # 0000: 0x20 0x00 0x00 0x00000004 A = arch # 0001: 0x15 0x00 0x05 0xc000003e if (A != ARCH_X86_64) goto 0007 # 0002: 0x20 0x00 0x00 0x00000000 A = sys_number # 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 # 0004: 0x15 0x00 0x02 0xffffffff if (A != 0xffffffff) goto 0007 # 0005: 0x15 0x01 0x00 0x00000000 if (A == read) goto 0007 # 0006: 0x06 0x00 0x00 0x00000000 return KILL # 0007: 0x06 0x00 0x00 0x7fff0000 return ALLOW
|
1 2 3 4 5 6
| from pwn import *
io = process('./binary')
|