binary-exploitation-methodology

$npx mdskill add wgpsec/AboutSecurity/binary-exploitation-methodology

Analyze binary vulnerabilities and select exploitation strategies.

  • Identify stack, heap, format string, and use-after-free flaws.
  • Evaluate ASLR, NX, canary, PIE, and RELRO protections.
  • Choose between ret2win, ret2shellcode, ROP, and ret2libc approaches.
  • Generate exploit code using GDB and pwntools for testing.
SKILL.md
.github/skills/binary-exploitation-methodologyView on GitHub ↗
---
name: binary-exploitation-methodology
description: "二进制漏洞利用基础方法论。涵盖漏洞识别(栈溢出/堆溢出/格式化字符串/UAF)、保护机制分析(ASLR/NX/Stack Canary/PIE/RELRO)、利用策略选择(ret2win/ret2shellcode/ROP/ret2libc)、调试与利用开发流程。当 Agent 需要分析二进制程序漏洞、选择利用策略、或理解保护机制绕过方法时触发。区别于 CTF pwn 技巧,侧重实战方法论。"
metadata:
  tags: "二进制利用,栈溢出,rop,保护机制,gdb,pwntools,实战"
  category: "exploit/binary"
---

# 二进制漏洞利用基础方法论

> **核心流程**:分析目标二进制 → 识别保护机制 → 判断漏洞类型 → 选择利用策略 → 开发利用代码 → 测试验证

## 深入参考

- 利用策略完整决策树与保护机制绕过详解 → [references/exploitation-strategy-reference.md](references/exploitation-strategy-reference.md)
- Heap 利用实战方法论(tcache/fastbin/unsorted bin/House of X) → [references/heap-exploitation.md](references/heap-exploitation.md)
- Format string 完整攻击流程 → [references/format-string-exploitation.md](references/format-string-exploitation.md)
- libc 版本识别与偏移计算 → [references/libc-identification.md](references/libc-identification.md)
- seccomp 沙箱评估与绕过 → [references/seccomp-sandbox-assessment.md](references/seccomp-sandbox-assessment.md)

---

## Phase 1: 目标分析

```
目标二进制初步分析:
├─ 文件类型与架构
│  ├─ file <binary>
│  ├─ ELF 32/64-bit, LSB/MSB
│  └─ 架构: x86, x86_64, ARM, MIPS
├─ 链接方式
│  ├─ 动态链接 → 有 libc, GOT/PLT 可利用
│  └─ 静态链接 → 无外部库,gadget 丰富但无 libc 函数地址泄露
├─ 符号信息
│  ├─ stripped → 需要逆向分析函数
│  └─ not stripped → 函数名可见,分析更容易
└─ 基本字符串搜索
   └─ strings <binary> | grep -i "flag\|shell\|bin/sh\|password"
```

### 初步分析命令

```bash
# 文件类型与架构
file ./target_binary

# 检查动态链接库
ldd ./target_binary

# 符号表
nm ./target_binary 2>/dev/null | head -30

# 有价值的字符串
strings ./target_binary | grep -i "flag\|shell\|/bin/sh\|system\|exec"

# 反汇编关键函数
objdump -d -Mintel ./target_binary | less
```

## Phase 2: 保护机制识别

```
保护机制检查决策树:
├─ checksec --file=<binary>
├─ CANARY(Stack Canary / 栈金丝雀)
│  ├─ 启用 → 需要泄露 canary 值才能覆盖返回地址
│  │  ├─ 格式化字符串泄露
│  │  ├─ 信息泄露漏洞
│  │  └─ brute force(仅 fork 模式有效)
│  └─ 未启用 → 可直接覆盖返回地址
├─ NX(No-Execute / 不可执行)
│  ├─ 启用 → 栈上 shellcode 不可执行,需用 ROP/ret2libc
│  └─ 未启用 → 可在栈上放置 shellcode 并跳转执行
├─ PIE(Position Independent Executable)
│  ├─ 启用 → 代码段地址随机化,需要泄露基地址
│  │  ├─ partial overwrite(只改低位字节)
│  │  └─ 信息泄露获取代码段地址
│  └─ 未启用 → 代码段地址固定,可直接使用 gadget 地址
├─ ASLR(地址空间布局随机化)
│  ├─ 启用 → 栈/堆/libc 地址随机
│  │  ├─ 信息泄露获取 libc 基地址
│  │  ├─ ret2plt 间接调用
│  │  ├─ ret2dlresolve 动态解析
│  │  └─ brute force(32-bit 熵较低)
│  └─ 未启用 → 地址可预测
├─ RELRO(Relocation Read-Only)
│  ├─ Full RELRO → GOT 只读,不可覆写 GOT 条目
│  ├─ Partial RELRO → GOT 可写,可覆写 GOT 实现任意调用
│  └─ No RELRO → .dynamic 也可写
└─ Fortify Source
   └─ 编译时替换不安全函数为安全版本
```

### 检查命令

```bash
# 一键检查所有保护
checksec --file=./target_binary

# 手动检查 NX
readelf -l ./target_binary | grep GNU_STACK
# RW 表示 NX 启用(栈不可执行),RWE 表示栈可执行

# 检查 PIE
readelf -h ./target_binary | grep Type
# DYN 表示 PIE,EXEC 表示非 PIE

# 检查 ASLR(系统级)
cat /proc/sys/kernel/randomize_va_space
# 0=关闭, 1=部分, 2=完全

# 检查 RELRO
readelf -l ./target_binary | grep GNU_RELRO
readelf -d ./target_binary | grep BIND_NOW
```

## Phase 3: 漏洞类型判断

```
漏洞类型识别决策树:
├─ 栈溢出(Stack Buffer Overflow)
│  ├─ 特征: gets/strcpy/sprintf/scanf 等不安全函数
│  ├─ 可覆盖: 返回地址、保存的寄存器、局部变量
│  └─ 子类型
│     ├─ 标准溢出 → 覆盖返回地址
│     ├─ Off-by-one → 只能覆盖 1 字节(通常是 EBP 低字节)
│     └─ 整数溢出导致的栈溢出
├─ 格式化字符串(Format String)
│  ├─ 特征: printf(user_input) 而非 printf("%s", user_input)
│  ├─ 能力: 任意读 + 任意写
│  └─ 利用: %p 泄露栈内容, %n 写入任意地址
├─ 堆溢出(Heap Overflow)
│  ├─ 特征: malloc 后写入超出分配大小
│  ├─ 利用: 覆盖堆元数据或相邻 chunk 的数据
│  └─ 进阶: fastbin attack, tcache poisoning, unsafe unlink
├─ Use-After-Free (UAF)
│  ├─ 特征: free 后指针未置空且继续使用
│  ├─ 利用: 重新分配同大小 chunk 控制已释放内存
│  └─ 通常需要理解对象布局
├─ 数组越界(Array Out-of-Bounds)
│  ├─ 特征: 可控的数组索引缺少边界检查
│  └─ 利用: 任意读/写
└─ 整数溢出
   ├─ 特征: 大小计算中的整数截断/回绕
   └─ 通常作为触发其他漏洞的前置条件
```

### 漏洞定位方法

```bash
# 搜索不安全函数
objdump -d ./target_binary | grep -E "gets|strcpy|sprintf|scanf|strcat"

# Ghidra 中搜索(使用反编译视图)
# Search → For Strings → "system" / "/bin/sh"
# 查找 cross-reference 到危险函数的路径

# 动态 fuzzing
# 简单输入测试
python3 -c "print('A'*200)" | ./target_binary
python3 -c "print('A'*500)" | ./target_binary
# 段错误 → 可能存在溢出
```

## Phase 4: 利用策略选择

```
利用策略总决策树:

目标: 调用已有函数(ret2win)
├─ 无 PIE + 无 Canary → 直接覆盖返回地址为 win 函数地址
├─ 有 PIE → 先泄露基地址或 partial overwrite
├─ 有 Canary → 先泄露 canary
├─ 需要设置参数
│  ├─ ROP gadgets 充足 → ROP chain 设置寄存器
│  ├─ SROP → sigreturn 控制所有寄存器
│  └─ ret2csu / ret2vdso → 控制多个寄存器
└─ WWW (Write-What-Where) → 通过任意写调用 win 函数

目标: 获取 Shell (RCE)
├─ NX 未启用
│  ├─ 无 ASLR → ret2shellcode(跳转到栈上 shellcode)
│  ├─ 有 ASLR → ret2esp / ret2reg(通过 gadget 跳转到 shellcode)
│  └─ 有 NX → ROP 调用 mprotect 使栈可执行,再跳转 shellcode
├─ 通过 syscall
│  ├─ ret2syscall → ROP chain 调用 execve("/bin/sh", 0, 0)
│  └─ SROP → sigreturn 设置寄存器后 syscall
├─ 通过 libc
│  ├─ 静态链接 + 无 PIE → system 和 "/bin/sh" 地址固定
│  ├─ 无 ASLR → libc 地址固定,直接 ret2libc
│  ├─ 有 ASLR + 无 PIE + binary 有 system → ret2plt(system)
│  ├─ 有 ASLR + 无 PIE + binary 无 system
│  │  ├─ ret2dlresolve → 动态解析 system 地址
│  │  └─ 泄露 libc 地址 → 计算 system 偏移
│  └─ 有 ASLR + 有 PIE + 未知 libc
│     ├─ 先绕过 PIE(泄露代码段地址)
│     ├─ 泄露 libc 函数地址 → 确定 libc 版本
│     └─ 计算 system 和 "/bin/sh" 地址
└─ Stack Pivoting
   ├─ Off-by-one → 控制 EBP → 控制 ESP → 控制 RET
   └─ 构造 payload 到可控内存,通过 EBP 跳转
```

### 保持循环利用(Eternal Loop)

```
单次漏洞触发不够时,需要多次利用:
├─ ROP chain 中跳回 main 或漏洞函数地址
├─ 覆写 GOT 中 exit 条目 → 跳回漏洞点
└─ .fini_array 写入两个函数:
   ├─ 函数 1: 调用漏洞函数
   └─ 函数 2: 调用 __libc_csu_fini(再次触发 .fini_array)
```

## Phase 5: 利用开发

### 确定溢出偏移量

```bash
# 使用 pwntools 生成 cyclic pattern
python3 -c "from pwn import *; print(cyclic(300))" | ./target_binary

# GDB 中确定偏移
# (gdb) run < <(python3 -c "from pwn import *; print(cyclic(300))")
# (gdb) x/wx $rsp  → 查看覆盖到返回地址的值
# python3 -c "from pwn import *; print(cyclic_find(0x61616168))"

# 或使用 Metasploit
msf-pattern_create -l 300
msf-pattern_offset -l 300 -q <value>
```

### pwntools 利用模板

```python
from pwn import *

# 设置上下文
context.binary = elf = ELF('./target_binary')
context.log_level = 'debug'

# 本地 / 远程
# p = process('./target_binary')
# p = remote('host', port)

# 构造 payload
offset = 72  # 根据实际偏移调整
payload = b'A' * offset

# ret2win 示例
payload += p64(elf.symbols['win_function'])

# ret2libc 示例(需要先泄露 libc 基地址)
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# libc_base = leaked_addr - libc.symbols['puts']
# system = libc_base + libc.symbols['system']
# bin_sh = libc_base + next(libc.search(b'/bin/sh'))
# ret = elf address of a "ret" gadget  (stack alignment)
# payload += p64(ret) + p64(pop_rdi) + p64(bin_sh) + p64(system)

p = process('./target_binary')
p.sendline(payload)
p.interactive()
```

### ROP Chain 构造

```bash
# 搜索 gadgets
ROPgadget --binary ./target_binary | grep "pop rdi"
ROPgadget --binary ./target_binary | grep "pop rsi"
ropper --file ./target_binary --search "pop rdi"

# one_gadget(libc 中的一键 shell gadget)
one_gadget /lib/x86_64-linux-gnu/libc.so.6
```

## Phase 6: 测试验证

```
验证流程:
├─ 本地测试
│  ├─ 关闭 ASLR 测试: echo 0 > /proc/sys/kernel/randomize_va_space
│  ├─ 确认 exploit 可靠触发
│  └─ 开启 ASLR 测试稳定性
├─ 调试失败排查
│  ├─ 栈对齐问题(x86_64 要求 16 字节对齐)
│  │  └─ 在 payload 中加一个 ret gadget 对齐栈
│  ├─ 坏字符(\x00, \x0a, \x0d)
│  │  └─ 检查输入函数是否截断特定字符
│  ├─ 地址计算错误
│  │  └─ GDB 中 verify: x/gx $rsp, info registers
│  └─ 远程环境差异
│     ├─ libc 版本不同
│     ├─ 栈偏移不同
│     └─ 使用 pwntools 的 DynELF 动态泄露
├─ 远程验证
│  ├─ 调整 payload 适配远程环境
│  └─ 处理网络延迟与 IO 缓冲
└─ 可靠性测试
   └─ 多次运行确认成功率
```

### GDB 调试技巧

```bash
# 确保 GDB 与实际运行地址一致
# (gdb) unset env LINES
# (gdb) unset env COLUMNS
# (gdb) set env _=/full/path/to/binary

# 查看崩溃时寄存器状态
# (gdb) info registers
# (gdb) x/20gx $rsp
# (gdb) bt

# 静态链接二进制的 backtrace 定位输入点
# 运行程序 → 等待输入 → Ctrl+C → bt
```

## 工具速查

| 工具 | 用途 |
|------|------|
| checksec | 检查二进制保护机制 |
| pwntools | 利用开发框架 |
| GDB + GEF/pwndbg | 调试分析 |
| ROPgadget | ROP gadget 搜索 |
| one_gadget | libc 中一键 shell gadget |
| Ghidra | 反编译与逆向 |
| ropper | gadget 搜索与 ROP chain 生成 |
| msf-pattern_create | 偏移量计算 |
| readelf / objdump | 二进制信息查看 |
More from wgpsec/AboutSecurity