Exploit Development Guidance
Auto-loads: When developing exploits or analyzing exploitation feasibility
Token cost: ~600 tokens
Purpose: Verify constraints before attempting techniques, avoid wasted effort
Core Principle
Verify constraints BEFORE attempting any exploit technique.
Many hours can be wasted attempting techniques that are architecturally impossible. Check constraints first, then choose appropriate techniques.
Using RAPTOR's Mitigation Analysis
Run mitigation analysis FIRST. Check the output for:
TECHNIQUE VIABILITY
----------------------------------------
BLOCKED (don't waste time on these):
✗ strcpy multi-gadget ROP
✗ strcpy ret2libc chain (pop_rdi + bin_sh + system)
VIABLE (focus here):
✓ format string %n writes
✓ partial overwrite
✓ single gadget redirect (one_gadget)
Key fields in analysis result:
result['input_handlers'] - Detected input functions (strcpy, fgets, etc.)
result['constraints']['blocked_techniques'] - Don't waste time on these
result['constraints']['viable_techniques'] - Focus here
result['constraints']['input_handler'] - Which handler drove the constraints
Constraint Checklist
1. Bad Bytes
What bytes cannot appear in the payload?
| Input Handler |
Bad Bytes |
Notes |
| strcpy, strcat, sprintf |
0x00 |
Null terminates |
| fgets, gets |
0x00, 0x0a |
Null and newline |
| scanf %s |
0x00, 0x09-0x0d, 0x20 |
Null and whitespace |
| read, recv |
None (binary safe) |
Length-limited only |
2. Architecture
| Property |
x86 (32-bit) |
x86_64 (64-bit) |
ARM |
ARM64 |
| Pointer size |
4 bytes |
8 bytes |
4 bytes |
8 bytes |
| Endianness |
Little |
Little |
Usually little |
Usually little |
| Stack growth |
Down |
Down |
Down |
Down |
| Calling convention |
Stack args |
RDI, RSI, RDX, RCX, R8, R9 |
R0-R3 |
X0-X7 |
| Address null bytes |
Rare |
Always (bytes 6-7) |
Varies |
Common |
x86_64 null byte pitfall: Userland addresses are 0x00007fff... format. In little-endian memory: 78 56 34 12 ff 7f 00 00. The null bytes are at offsets 6-7. String functions copy low bytes first, then stop at null - so only 6 bytes of an address can be written via strcpy.
3. Protections
| Protection |
Impact |
Bypass |
| NX |
No shellcode on stack/heap |
ROP, ret2libc |
| ASLR |
Randomized addresses |
Info leak, partial overwrite, brute force |
| PIE |
Randomized binary base |
Info leak for binary addresses |
| Stack canary |
Detects stack overflow |
Leak canary, format string, or skip it |
| Full RELRO |
GOT read-only |
Target other writable areas |
| Partial RELRO |
GOT writable |
Overwrite GOT entries |
4. Primitives Needed
| Primitive |
Description |
Common Sources |
| Arbitrary write |
Write controlled value to controlled address |
Format string %n, heap overflow |
| Arbitrary read |
Read from controlled address |
Format string %s, OOB read |
| Info leak |
Disclose addresses/canary |
Format string %p, uninitialized memory |
| Control RIP |
Redirect execution |
Stack overflow, GOT overwrite, vtable |
Vulnerability Class Quick Reference
Format String
- Read:
%p leaks stack values, %s reads from pointer on stack
- Write:
%n writes byte count to address on stack
- Bypass null bytes: Write address using multiple
%hhn (one byte each)
- Key insight: Format string CAN write null bytes; strcpy overflow CANNOT
Stack Buffer Overflow
- With NX: ROP chain, ret2libc
- Without NX: Shellcode on stack, jump to it
- With canary: Leak canary first (format string, separate bug)
- x86_64 + strcpy: Can only write ONE gadget address (null byte issue)
Heap Exploitation
- tcache (glibc 2.26+): tcache poisoning, double-free
- fastbin: Fastbin dup, House of Spirit
- Unsorted bin: Unsorted bin attack, House of Orange
- Key: Know your glibc version - techniques vary significantly
Use-After-Free
- Object replacement: Allocate controlled data in freed slot
- Vtable hijack: Replace C++ vtable pointer
- Function pointer: Overwrite function pointer in struct
When Technique A is Blocked
| Blocked |
Try Instead |
| Multi-gadget ROP (null bytes) |
Format string %n writes, partial overwrite, one-gadget |
| GOT overwrite (Full RELRO) |
Stack return address, __exit_funcs (needs PTR_DEMANGLE bypass) |
| Stack shellcode (NX) |
ROP, ret2libc, mprotect to make region executable |
| Direct address (ASLR/PIE) |
Leak addresses first, partial overwrite, brute force |
| Large payload (length limit) |
Staged payload, reuse existing code |
IMPORTANT: Full RELRO typically blocks BOTH GOT AND .fini_array (standard linker
scripts place both in the RELRO segment). Do NOT suggest .fini_array when Full RELRO is enabled.
Testing Methodology
- Verify assumptions: Use GDB/pwndbg to check actual memory layout
- Test constraints empirically: Send payload with suspect bytes, observe behavior
- Check versions:
ldd --version for glibc, actual offsets vary by version
- Iterate: Exploit development is rarely first-try; debug and refine
Common Mistakes
- Assuming technique works without checking constraints
- Forgetting endianness when constructing addresses
- Not accounting for stack alignment requirements (x86_64: 16-byte before call)
- Using offsets from wrong libc/binary version
- Overlooking simpler alternatives when complex technique is blocked
1---2name: 862-exploit-guidance-ac8d69a73description: Exploit Development Guidance4---5# Exploit Development Guidance6# Auto-loads: When developing exploits or analyzing exploitation feasibility7# Token cost: ~600 tokens8# Purpose: Verify constraints before attempting techniques, avoid wasted effort910## Core Principle1112**Verify constraints BEFORE attempting any exploit technique.**1314Many hours can be wasted attempting techniques that are architecturally impossible. Check constraints first, then choose appropriate techniques.1516---1718## Using RAPTOR's Mitigation Analysis1920Run mitigation analysis FIRST. Check the output for:2122```23TECHNIQUE VIABILITY24----------------------------------------25 BLOCKED (don't waste time on these):26 ✗ strcpy multi-gadget ROP27 ✗ strcpy ret2libc chain (pop_rdi + bin_sh + system)2829 VIABLE (focus here):30 ✓ format string %n writes31 ✓ partial overwrite32 ✓ single gadget redirect (one_gadget)33```3435Key fields in analysis result:36- `result['input_handlers']` - Detected input functions (strcpy, fgets, etc.)37- `result['constraints']['blocked_techniques']` - Don't waste time on these38- `result['constraints']['viable_techniques']` - Focus here39- `result['constraints']['input_handler']` - Which handler drove the constraints4041---4243## Constraint Checklist4445### 1. Bad Bytes46What bytes cannot appear in the payload?4748| Input Handler | Bad Bytes | Notes |49|---------------|-----------|-------|50| strcpy, strcat, sprintf | `0x00` | Null terminates |51| fgets, gets | `0x00`, `0x0a` | Null and newline |52| scanf %s | `0x00`, `0x09-0x0d`, `0x20` | Null and whitespace |53| read, recv | None (binary safe) | Length-limited only |5455### 2. Architecture56| Property | x86 (32-bit) | x86_64 (64-bit) | ARM | ARM64 |57|----------|--------------|-----------------|-----|-------|58| Pointer size | 4 bytes | 8 bytes | 4 bytes | 8 bytes |59| Endianness | Little | Little | Usually little | Usually little |60| Stack growth | Down | Down | Down | Down |61| Calling convention | Stack args | RDI, RSI, RDX, RCX, R8, R9 | R0-R3 | X0-X7 |62| Address null bytes | Rare | Always (bytes 6-7) | Varies | Common |6364**x86_64 null byte pitfall:** Userland addresses are `0x00007fff...` format. In little-endian memory: `78 56 34 12 ff 7f 00 00`. The null bytes are at offsets 6-7. String functions copy low bytes first, then stop at null - so only 6 bytes of an address can be written via strcpy.6566### 3. Protections67| Protection | Impact | Bypass |68|------------|--------|--------|69| NX | No shellcode on stack/heap | ROP, ret2libc |70| ASLR | Randomized addresses | Info leak, partial overwrite, brute force |71| PIE | Randomized binary base | Info leak for binary addresses |72| Stack canary | Detects stack overflow | Leak canary, format string, or skip it |73| Full RELRO | GOT read-only | Target other writable areas |74| Partial RELRO | GOT writable | Overwrite GOT entries |7576### 4. Primitives Needed77| Primitive | Description | Common Sources |78|-----------|-------------|----------------|79| Arbitrary write | Write controlled value to controlled address | Format string %n, heap overflow |80| Arbitrary read | Read from controlled address | Format string %s, OOB read |81| Info leak | Disclose addresses/canary | Format string %p, uninitialized memory |82| Control RIP | Redirect execution | Stack overflow, GOT overwrite, vtable |8384---8586## Vulnerability Class Quick Reference8788### Format String89- **Read:** `%p` leaks stack values, `%s` reads from pointer on stack90- **Write:** `%n` writes byte count to address on stack91- **Bypass null bytes:** Write address using multiple `%hhn` (one byte each)92- **Key insight:** Format string CAN write null bytes; strcpy overflow CANNOT9394### Stack Buffer Overflow95- **With NX:** ROP chain, ret2libc96- **Without NX:** Shellcode on stack, jump to it97- **With canary:** Leak canary first (format string, separate bug)98- **x86_64 + strcpy:** Can only write ONE gadget address (null byte issue)99100### Heap Exploitation101- **tcache (glibc 2.26+):** tcache poisoning, double-free102- **fastbin:** Fastbin dup, House of Spirit103- **Unsorted bin:** Unsorted bin attack, House of Orange104- **Key:** Know your glibc version - techniques vary significantly105106### Use-After-Free107- **Object replacement:** Allocate controlled data in freed slot108- **Vtable hijack:** Replace C++ vtable pointer109- **Function pointer:** Overwrite function pointer in struct110111---112113## When Technique A is Blocked114115| Blocked | Try Instead |116|---------|-------------|117| Multi-gadget ROP (null bytes) | Format string %n writes, partial overwrite, one-gadget |118| GOT overwrite (Full RELRO) | Stack return address, __exit_funcs (needs PTR_DEMANGLE bypass) |119| Stack shellcode (NX) | ROP, ret2libc, mprotect to make region executable |120| Direct address (ASLR/PIE) | Leak addresses first, partial overwrite, brute force |121| Large payload (length limit) | Staged payload, reuse existing code |122123**IMPORTANT:** Full RELRO typically blocks BOTH GOT AND .fini_array (standard linker124scripts place both in the RELRO segment). Do NOT suggest .fini_array when Full RELRO is enabled.125126---127128## Testing Methodology1291301. **Verify assumptions:** Use GDB/pwndbg to check actual memory layout1312. **Test constraints empirically:** Send payload with suspect bytes, observe behavior1323. **Check versions:** `ldd --version` for glibc, actual offsets vary by version1334. **Iterate:** Exploit development is rarely first-try; debug and refine134135---136137## Common Mistakes1381391. Assuming technique works without checking constraints1402. Forgetting endianness when constructing addresses1413. Not accounting for stack alignment requirements (x86_64: 16-byte before call)1424. Using offsets from wrong libc/binary version1435. Overlooking simpler alternatives when complex technique is blocked