skills/exploit/binary/binary-exploitation-methodology/SKILL.md
二进制漏洞利用基础方法论。涵盖漏洞识别(栈溢出/堆溢出/格式化字符串/UAF)、保护机制分析(ASLR/NX/Stack Canary/PIE/RELRO)、利用策略选择(ret2win/ret2shellcode/ROP/ret2libc)、调试与利用开发流程。当 Agent 需要分析二进制程序漏洞、选择利用策略、或理解保护机制绕过方法时触发。区别于 CTF pwn 技巧,侧重实战方法论。
npx skillsauth add wgpsec/AboutSecurity binary-exploitation-methodologyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
核心流程:分析目标二进制 → 识别保护机制 → 判断漏洞类型 → 选择利用策略 → 开发利用代码 → 测试验证
目标二进制初步分析:
├─ 文件类型与架构
│ ├─ 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"
# 文件类型与架构
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
保护机制检查决策树:
├─ 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
└─ 编译时替换不安全函数为安全版本
# 一键检查所有保护
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
漏洞类型识别决策树:
├─ 栈溢出(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)
│ ├─ 特征: 可控的数组索引缺少边界检查
│ └─ 利用: 任意读/写
└─ 整数溢出
├─ 特征: 大小计算中的整数截断/回绕
└─ 通常作为触发其他漏洞的前置条件
# 搜索不安全函数
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
# 段错误 → 可能存在溢出
利用策略总决策树:
目标: 调用已有函数(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 跳转
单次漏洞触发不够时,需要多次利用:
├─ ROP chain 中跳回 main 或漏洞函数地址
├─ 覆写 GOT 中 exit 条目 → 跳回漏洞点
└─ .fini_array 写入两个函数:
├─ 函数 1: 调用漏洞函数
└─ 函数 2: 调用 __libc_csu_fini(再次触发 .fini_array)
# 使用 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>
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()
# 搜索 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
验证流程:
├─ 本地测试
│ ├─ 关闭 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 与实际运行地址一致
# (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 | 二进制信息查看 |
testing
Azure 云环境渗透测试总体方法论。当目标使用 Azure/Microsoft 365/Entra ID、发现 Azure 相关资产(Blob Storage/App Service/Azure VM/Azure Functions)、获取 Azure 凭据(Service Principal/Managed Identity/Access Token)、或需要对 Azure 环境进行安全评估时使用。提供从未授权枚举到 Entra ID 攻击、服务提权、Cloud-to-OnPrem 横向移动的全流程决策树。覆盖 35+ Azure 服务攻击面
tools
Mythic C2 操作方法论。当需要部署 Mythic、选择 Mythic Agent、安装 C2 Profile、配置 HTTP/DNS/WebSocket/SMB/TCP 通信、生成 payload、管理回连任务,或把 Mythic 作为跨平台 C2 框架用于授权红队演练时使用。覆盖 mythic-cli 安装、Agent/Profile 选择、SSL 证书配置、payload 构建和基础 OPSEC 判断
development
Docker 安全测试与容器渗透方法论。当需要评估 Docker 容器、Docker Daemon、Docker Registry、镜像层、构建产物或容器逃逸风险时使用。覆盖容器环境识别、特权容器逃逸、docker.sock/Remote API 利用、procfs/cgroup/capabilities 滥用、Docker 用户组提权、运行时/内核 CVE、Registry 枚举、镜像层 Secret 分析和构建上下文泄露。发现 Docker 容器环境、Registry 暴露、镜像凭据或容器配置错误时应使用此技能
development
使用 PadBuster 进行 Padding Oracle 攻击。当发现 Web 应用使用 CBC 模式加密且存在 Padding Oracle 漏洞时使用。PadBuster 可自动解密密文和伪造任意明文对应的合法密文,适用于加密 Cookie/Token/URL 参数。任何涉及 Padding Oracle 攻击、CBC 密文解密、Cookie 伪造的场景都应使用此技能