binary-protection-bypass
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSKILL: Binary Protection Bypass — Expert Attack Playbook
技能:二进制防护绕过——专家级攻击手册
AI LOAD INSTRUCTION: Expert binary protection identification and bypass techniques. Covers ASLR, PIE, NX, RELRO, canary, FORTIFY_SOURCE, stack clash, CET shadow stack, and ARM MTE. Each protection is paired with its bypass methods and required primitives. Distilled from ctf-wiki mitigation sections and real-world exploitation. Base models often confuse which protections block which attacks and miss the combinatorial effect of multiple protections.
AI加载说明:专家级二进制防护识别与绕过技术,覆盖ASLR、PIE、NX、RELRO、金丝雀、FORTIFY_SOURCE、栈冲突、CET影子栈以及ARM MTE。每种防护都对应了绕过方法和所需原语,内容提炼自ctf-wiki的防护绕过章节和真实场景漏洞利用。基础大模型通常会混淆不同防护对应的拦截攻击类型,也会忽略多种防护组合生效的叠加效果。
0. RELATED ROUTING
0. 相关路由
- stack-overflow-and-rop — ROP chains to bypass NX, ret2libc for ASLR bypass
- format-string-exploitation — primary method for leaking canary, PIE, libc addresses
- heap-exploitation — heap attacks for RELRO bypass (when GOT is read-only)
- arbitrary-write-to-rce — what to overwrite when GOT is protected by RELRO
- stack-overflow-and-rop — 用于绕过NX的ROP链,用于绕过ASLR的ret2libc
- format-string-exploitation — 泄露金丝雀、PIE、libc地址的主要方法
- heap-exploitation — 用于绕过RELRO的堆攻击(当GOT为只读时)
- arbitrary-write-to-rce — 当GOT受RELRO保护时的覆写目标参考
Advanced Reference
高级参考
Load PROTECTION_BYPASS_MATRIX.md for comprehensive protection × bypass × primitive matrix.
加载 PROTECTION_BYPASS_MATRIX.md 可查看完整的防护×绕过×原语矩阵。
1. PROTECTION IDENTIFICATION
1. 防护识别
bash
$ checksec ./binary
[*] '/path/to/binary'
Arch: amd64-64-little
RELRO: Full RELRO ← GOT read-only
Stack: Canary found ← stack canary enabled
NX: NX enabled ← stack not executable
PIE: PIE enabled ← position-independent code
FORTIFY: Enabled ← fortified libc functionsbash
$ checksec ./binary
[*] '/path/to/binary'
Arch: amd64-64-little
RELRO: Full RELRO ← GOT只读
Stack: Canary found ← 已启用栈金丝雀
NX: NX enabled ← 栈不可执行
PIE: PIE enabled ← 位置无关代码
FORTIFY: Enabled ← 已启用libc函数加固Quick Identification Table
快速识别表
| Protection | Check Command | Binary Indicator |
|---|---|---|
| ASLR | | OS-level (0=off, 1=partial, 2=full) |
| PIE | | Binary compiled with |
| NX | | |
| Canary | | |
| Partial RELRO | | |
| Full RELRO | | |
| FORTIFY | Presence of | |
| 防护机制 | 检查命令 | 二进制标识 |
|---|---|---|
| ASLR | | 操作系统级别(0=关闭,1=部分开启,2=完全开启) |
| PIE | | 二进制编译时添加 |
| NX | | |
| 金丝雀 | | |
| 部分RELRO | | |
| 完全RELRO | | |
| FORTIFY | 存在 | |
2. ASLR BYPASS
2. ASLR绕过
ASLR randomizes base addresses of stack, heap, libc, and mmap regions at each execution.
| Bypass Method | Required Primitive | Notes |
|---|---|---|
| Information leak | Any read primitive (format string, OOB read, UAF) | Leak libc/stack/heap address → calculate base |
| Partial overwrite | Write primitive (limited length) | Overwrite last 1-2 bytes (page offset fixed) |
| Brute force (32-bit) | Ability to reconnect/retry | ~256–4096 attempts (8-12 bits entropy) |
| Return-to-PLT | Stack overflow | PLT addresses are at fixed offset from binary base (if no PIE) |
| ret2dlresolve | Stack overflow + write primitive | Resolve arbitrary function without knowing libc base |
| Format string leak | Format string vulnerability | |
| Stack reading | Byte-by-byte (fork server) | Read stack byte-by-byte via crash oracle |
ASLR会在每次程序执行时随机化栈、堆、libc和mmap区域的基地址。
| 绕过方法 | 所需原语 | 说明 |
|---|---|---|
| 信息泄露 | 任意读原语(格式化字符串、越界读、UAF) | 泄露libc/栈/堆地址 → 计算基地址 |
| 部分覆写 | 有限长度的写原语 | 覆写最后1-2字节(页偏移固定) |
| 暴力破解(32位) | 支持重连/重试 | 约256–4096次尝试(8-12位熵) |
| 返回PLT | 栈溢出 | PLT地址相对于二进制基地址偏移固定(无PIE时) |
| ret2dlresolve | 栈溢出 + 写原语 | 无需知道libc基地址即可解析任意函数 |
| 格式化字符串泄露 | 格式化字符串漏洞 | 用 |
| 栈读取 | 逐字节读取(fork服务场景) | 通过崩溃预言机逐字节读取栈内容 |
ASLR Entropy (x86-64 Linux)
ASLR熵值(x86-64 Linux)
| Region | Entropy (bits) | Positions |
|---|---|---|
| Stack | 22 | ~4M |
| mmap / libc | 28 | ~256M |
| Heap (brk) | 13 | ~8K |
| PIE binary | 28 | ~256M |
| 内存区域 | 熵值(位) | 可能位置数 |
|---|---|---|
| 栈 | 22 | ~4M |
| mmap / libc | 28 | ~256M |
| 堆(brk) | 13 | ~8K |
| PIE二进制 | 28 | ~256M |
3. PIE BYPASS
3. PIE绕过
PIE (Position Independent Executable) randomizes the binary's own code/data base address.
| Bypass Method | Required Primitive | Notes |
|---|---|---|
| Information leak | Read return address from stack | PIE base = leaked_addr - known_offset |
| Partial overwrite | One-byte or two-byte write | Last 12 bits of page offset are fixed |
| Format string leak | Format string vulnerability | |
| Relative addressing | Knowledge of binary layout | If you know relative offsets, only need one leak |
PIE(位置无关可执行文件)会随机化二进制自身的代码/数据基地址。
| 绕过方法 | 所需原语 | 说明 |
|---|---|---|
| 信息泄露 | 从栈读取返回地址 | PIE基地址 = 泄露地址 - 已知偏移 |
| 部分覆写 | 1字节或2字节写权限 | 页偏移的最后12位固定 |
| 格式化字符串泄露 | 格式化字符串漏洞 | 用指向.text段返回地址的 |
| 相对寻址 | 已知二进制布局 | 如果知道相对偏移,仅需一次泄露即可 |
Partial Overwrite Details
部分覆写细节
PIE binary loaded at: 0x555555554000 (example)
Function at offset 0x1234: 0x555555555234
Overwrite return address last 2 bytes: 0x?234 → 0x?XXX
Unknown: bits 12-15 (one nibble = 4 bits = 16 possibilities)
Success rate: 1/16 per attemptPIE二进制加载地址示例:0x555555554000
偏移0x1234处的函数地址:0x555555555234
覆写返回地址最后2字节:0x?234 → 0x?XXX
未知部分:12-15位(1个半字节=4位=16种可能)
单次尝试成功率:1/164. NX / DEP BYPASS
4. NX / DEP绕过
NX (No-eXecute) / DEP (Data Execution Prevention) prevents execution of code on the stack/heap.
| Bypass Method | Detail |
|---|---|
| ROP (Return-Oriented Programming) | Chain existing code gadgets ending in |
| ret2libc | Call libc functions (system, execve) directly |
| ret2csu | Use |
| ret2dlresolve | Forge dynamic linker structures to resolve arbitrary functions |
| SROP | Use sigreturn to set all registers from fake signal frame |
| mprotect ROP | Chain mprotect(addr, size, PROT_RWX) → make page executable → jump to shellcode |
| JIT spray | In JIT environments (V8, etc.), create executable code via JIT compiler |
NX(不可执行)/ DEP(数据执行防护)会阻止栈/堆上的代码执行。
| 绕过方法 | 详情 |
|---|---|
| ROP(面向返回编程) | 串联以 |
| ret2libc | 直接调用libc函数(system、execve) |
| ret2csu | 用 |
| ret2dlresolve | 伪造动态链接器结构解析任意函数 |
| SROP | 用sigreturn从伪造信号帧设置所有寄存器 |
| mprotect ROP | 串联调用mprotect(addr, size, PROT_RWX) → 使页可执行 → 跳转到shellcode |
| JIT喷射 | 在JIT环境(V8等)中,通过JIT编译器生成可执行代码 |
mprotect Chain
mprotect链示例
python
undefinedpython
undefinedMake stack executable, then jump to shellcode
使栈可执行,然后跳转到shellcode
rop = b'A' * offset
rop += p64(pop_rdi) + p64(stack_page) # page-aligned address
rop += p64(pop_rsi) + p64(0x1000) # size
rop += p64(pop_rdx) + p64(7) # PROT_READ|PROT_WRITE|PROT_EXEC
rop += p64(mprotect_addr)
rop += p64(shellcode_addr) # jump to shellcode on now-executable stack
---rop = b'A' * offset
rop += p64(pop_rdi) + p64(stack_page) # 页对齐地址
rop += p64(pop_rsi) + p64(0x1000) # 大小
rop += p64(pop_rdx) + p64(7) # PROT_READ|PROT_WRITE|PROT_EXEC
rop += p64(mprotect_addr)
rop += p64(shellcode_addr) # 跳转到现在可执行栈上的shellcode
---5. RELRO BYPASS
5. RELRO绕过
| RELRO Level | GOT Status | Bypass |
|---|---|---|
| No RELRO | GOT fully writable | Direct GOT overwrite |
| Partial RELRO | | GOT overwrite still works |
| Full RELRO | All GOT entries resolved at load, GOT read-only | Cannot write GOT → target other structures |
| RELRO级别 | GOT状态 | 绕过方法 |
|---|---|---|
| 无RELRO | GOT完全可写 | 直接覆写GOT |
| 部分RELRO | | 仍可使用GOT覆写 |
| 完全RELRO | 所有GOT条目加载时就完成解析,GOT只读 | 无法写GOT → targeting其他结构 |
Full RELRO Alternative Targets
完全RELRO替代目标
| Target | When | How |
|---|---|---|
| glibc < 2.34 | Overwrite with one_gadget |
| glibc < 2.34 | Overwrite with |
| Any glibc | FSOP / vtable hijack |
| Any glibc | Overwrite exit handler list |
| glibc ≥ 2.34 | Thread-local destructor list (needs pointer guard) |
| If writable | Overwrite destructor function pointers |
| Stack return address | Direct stack write | Overwrite return address for ROP |
See arbitrary-write-to-rce for comprehensive target list.
| 目标 | 适用场景 | 方法 |
|---|---|---|
| glibc < 2.34 | 覆写为one_gadget |
| glibc < 2.34 | 覆写为 |
| 所有glibc版本 | FSOP / vtable劫持 |
| 所有glibc版本 | 覆写退出处理程序列表 |
| glibc ≥ 2.34 | 线程局部析构函数列表(需要指针防护) |
| 可写时 | 覆写析构函数指针 |
| 栈返回地址 | 可直接写栈时 | 覆写返回地址实现ROP |
查看 arbitrary-write-to-rce 获取完整目标列表。
6. CANARY BYPASS
6. 金丝雀绕过
| Method | Condition | Detail |
|---|---|---|
| Format string leak | printf(user_input) | |
| Brute-force | fork() server (canary persists in child) | Byte-by-byte: 256 × (canary_size-1) attempts |
| Stack reading | Partial overwrite / info leak | Overwrite canary's null byte, leak via output |
| Thread canary overwrite | Overflow reaches TLS | Canary at |
| Canary-relative overwrite | Overflow after canary but before return addr | Skip canary, only overwrite return address (rare layout) |
| Heap-based | Vulnerability is on heap, not stack | Canary only protects stack |
| __stack_chk_fail GOT overwrite | Partial RELRO | Overwrite |
| 方法 | 条件 | 详情 |
|---|---|---|
| 格式化字符串泄露 | 存在printf(user_input) | 用 |
| 暴力破解 | fork()服务(金丝雀在子进程中保持不变) | 逐字节破解:256 × (金丝雀大小-1)次尝试 |
| 栈读取 | 部分覆写 / 信息泄露 | 覆写金丝雀的空字节,通过输出泄露 |
| 线程金丝雀覆写 | 溢出可以到达TLS | 金丝雀位于 |
| 金丝雀相对覆写 | 溢出发生在金丝雀之后、返回地址之前 | 跳过金丝雀,仅覆写返回地址(罕见布局) |
| 堆-based漏洞 | 漏洞在堆上而非栈上 | 金丝雀仅保护栈 |
| __stack_chk_fail GOT覆写 | 部分RELRO | 覆写 |
Canary Format
金丝雀格式
x86: 0x00XXXXXX (4 bytes, leading null byte)
x86-64: 0x00XXXXXXXXXXXXXX (8 bytes, leading null byte)The leading prevents string operations from accidentally reading the canary.
\x00x86: 0x00XXXXXX (4字节,前导空字节)
x86-64: 0x00XXXXXXXXXXXXXX (8字节,前导空字节)前导的可以防止字符串操作意外读取金丝雀值。
\x007. FORTIFY_SOURCE BYPASS
7. FORTIFY_SOURCE绕过
_FORTIFY_SOURCE=2| Fortified Function | Restriction | Bypass |
|---|---|---|
| | Use non-positional |
| Destination buffer size checked | Use heap overflow instead of stack |
| Same | |
| Read size checked against buffer |
_FORTIFY_SOURCE=2| 加固函数 | 限制 | 绕过方法 |
|---|---|---|
| 禁止使用带位置参数的 | 用非位置型 |
| 检查目标缓冲区大小 | 用堆溢出替代栈溢出 |
| 同上 | |
| 对照缓冲区检查读取大小 |
Format String with FORTIFY_SOURCE
FORTIFY_SOURCE下的格式化字符串利用
python
undefinedpython
undefined%1$n is blocked by __printf_chk
%1$n会被__printf_chk拦截
But sequential (non-positional) %n may still work:
但顺序(非位置型)%n可能仍然有效:
Print exact byte count, then %hn — must be very precise
打印精确字节数,然后用%hn — 必须非常精确
Or: find unfortified printf in binary/libc via ROP
或者:通过ROP找到二进制/libc中未加固的printf
---
---8. CET (Control-flow Enforcement Technology)
8. CET(控制流强制技术)
Intel CET adds two mechanisms:
Intel CET添加了两种机制:
Shadow Stack
影子栈
- Hardware-maintained copy of return addresses
- On , CPU checks shadow stack matches actual stack
ret - Mismatch → fault (control protection exception)
#CP
| Impact | Detail |
|---|---|
| ROP blocked | Return address overwrite detected on |
| JOP possible | |
| COP possible | |
- 硬件维护的返回地址副本
- 执行时,CPU检查影子栈与实际栈是否匹配
ret - 不匹配 → 触发故障(控制保护异常)
#CP
| 影响 | 详情 |
|---|---|
| ROP被阻断 | |
| JOP仍可行 | 影子栈不检查 |
| COP仍可行 | |
Indirect Branch Tracking (IBT)
间接分支跟踪(IBT)
- Indirect /
jmpmust land oncallinstructionENDBR64 - Non-ENDBR landing → fault
#CP
Bypass:
- Data-only attacks (don't change control flow)
- Find valid ENDBR gadgets that chain into useful operations
- JOP with ENDBR-prefixed gadgets
- Target structures outside CFI scope (modprobe_path, function pointer arrays)
- 间接/
jmp必须落在call指令上ENDBR64 - 非ENDBR着陆 → 触发故障
#CP
绕过方法:
- 纯数据攻击(不改变控制流)
- 找到可以串联成有效操作的合法ENDBR gadget
- 使用带ENDBR前缀的gadget实现JOP
- targetingCFI范围外的结构(modprobe_path、函数指针数组)
9. MTE (Memory Tagging Extension, ARM)
9. MTE(内存标记扩展,ARM架构)
ARM MTE assigns 4-bit tags to memory pointers and allocations. Tag mismatch = fault.
| Aspect | Detail |
|---|---|
| Tag bits | 4 bits in pointer (bits 56-59) = 16 possible tags |
| Granule | 16 bytes (each 16-byte granule has one tag) |
| Check | Load/store: pointer tag must match memory tag |
| Probabilistic | Random tag → 1/16 chance attacker guesses correctly |
ARM MTE为内存指针和内存分配分配4位标签,标签不匹配就会触发故障。
| 维度 | 详情 |
|---|---|
| 标签位 | 指针中的4位(56-59位)= 16种可能的标签 |
| 颗粒度 | 16字节(每个16字节内存颗粒对应一个标签) |
| 检查 | 加载/存储时:指针标签必须与内存标签匹配 |
| 概率性 | 随机标签 → 攻击者猜对的概率为1/16 |
Bypass Approaches
绕过方法
| Method | Success Rate |
|---|---|
| Brute-force | 1/16 per attempt (6.25%) |
| Tag oracle | Side-channel to determine tag (timing, error messages) |
| In-bounds exploit | Stay within same tagged region (use relative offsets) |
| Tag bypass gadget | Use |
| Speculative execution | Spectre-style bypass of tag check |
| 方法 | 成功率 |
|---|---|
| 暴力破解 | 每次尝试1/16(6.25%) |
| 标签预言机 | 侧信道获取标签(时序、错误信息) |
| 界内利用 | 保持在同一标签区域内(使用相对偏移) |
| 标签绕过gadget | 如果可以访问 |
| 推测执行 | Spectre风格的标签检查绕过 |
10. DECISION TREE
10. 决策树
Binary analysis: checksec output
├── NX disabled?
│ └── Shellcode on stack/heap (simplest path)
│
├── NX enabled (standard modern binary)?
│ ├── Need code execution → ROP/ret2libc
│ │
│ ├── Canary enabled?
│ │ ├── fork server? → byte-by-byte brute-force
│ │ ├── Format string? → leak canary via %p
│ │ ├── Heap vuln? → canary doesn't protect heap
│ │ └── Partial RELRO? → overwrite __stack_chk_fail@GOT
│ │
│ ├── PIE enabled?
│ │ ├── Format string? → leak .text address → PIE base
│ │ ├── Partial overwrite → last 12 bits fixed (1/16 brute-force)
│ │ └── OOB read? → leak code pointer
│ │
│ ├── ASLR enabled?
│ │ ├── Info leak available → leak libc base
│ │ ├── No leak → ret2dlresolve or SROP
│ │ ├── 32-bit? → brute-force feasible (~4096 attempts)
│ │ └── Return-to-PLT (no libc base needed for PLT calls)
│ │
│ ├── RELRO level?
│ │ ├── None/Partial → GOT overwrite
│ │ └── Full → alternative targets:
│ │ ├── glibc < 2.34 → __malloc_hook / __free_hook
│ │ ├── glibc ≥ 2.34 → _IO_FILE / exit_funcs / TLS_dtor_list
│ │ ├── .fini_array (if writable)
│ │ └── Stack return address
│ │
│ └── FORTIFY_SOURCE?
│ ├── Blocks positional %n → use sequential %n or heap exploit
│ └── Blocks buffer overflows in fortified functions → use unfortified paths
│
├── CET (shadow stack)?
│ ├── ROP blocked → data-only attack or JOP
│ └── ENDBR-gadget chaining
│
└── MTE (ARM)?
├── 1/16 brute-force
└── Stay in-bounds for relative corruption二进制分析:checksec输出
├── NX未开启?
│ └── 栈/堆上直接放shellcode(最简单路径)
│
├── NX已开启(现代标准二进制)?
│ ├── 需要代码执行 → ROP/ret2libc
│ │
│ ├── 已启用金丝雀?
│ │ ├── 是fork服务器? → 逐字节暴力破解
│ │ ├── 有格式化字符串漏洞? → 通过%p泄露金丝雀
│ │ ├── 是堆漏洞? → 金丝雀不保护堆
│ │ └── 是部分RELRO? → 覆写__stack_chk_fail@GOT
│ │
│ ├── 已启用PIE?
│ │ ├── 有格式化字符串漏洞? → 泄露.text地址 → 计算PIE基地址
│ │ ├── 可部分覆写 → 最后12位固定(1/16概率暴力破解)
│ │ └── 有越界读? → 泄露代码指针
│ │
│ ├── 已启用ASLR?
│ │ ├── 有信息泄露 → 泄露libc基地址
│ │ ├── 无泄露 → ret2dlresolve或SROP
│ │ ├── 是32位? → 暴力破解可行(约4096次尝试)
│ │ └── 返回PLT(调用PLT函数不需要libc基地址)
│ │
│ ├── RELRO级别?
│ │ ├── 无/部分 → GOT覆写
│ │ └── 完全 → 替代目标:
│ │ ├── glibc < 2.34 → __malloc_hook / __free_hook
│ │ ├── glibc ≥ 2.34 → _IO_FILE / exit_funcs / TLS_dtor_list
│ │ ├── .fini_array(可写时)
│ │ └── 栈返回地址
│ │
│ └── 已启用FORTIFY_SOURCE?
│ ├── 拦截位置型%n → 用顺序型%n或堆漏洞
│ └── 拦截加固函数中的缓冲区溢出 → 用未加固路径
│
├── 已启用CET(影子栈)?
│ ├── ROP被阻断 → 纯数据攻击或JOP
│ └── ENDBR-gadget串联
│
└── 已启用MTE(ARM)?
├── 1/16概率暴力破解
└── 保持界内实现相对篡改