PWN Static Analysis
npx machina-cli add skill allsmog/pwn-claude-plugin/static-analysis --openclawPWN Static Analysis
Overview
Static analysis examines the binary without execution to identify vulnerabilities, understand program flow, and map out exploitation targets. This phase focuses on disassembly, dangerous function identification, and vulnerability pattern recognition.
Analysis Targets
- Main function and program flow
- Vulnerable functions (user input handlers)
- Buffer sizes and stack layouts
- Dangerous function calls
- Potential write primitives
- Leak opportunities
Step 1: Disassemble Key Functions
Using objdump
# Disassemble specific function
objdump -d ./binary | grep -A 50 '<main>:'
# Disassemble all with Intel syntax
objdump -d -M intel ./binary > disasm.txt
Using radare2
# Quick analysis
r2 -A ./binary -c 'pdf @ main' -q
# Full function list
r2 -A ./binary -c 'afl' -q
Using pwntools
from pwn import *
elf = ELF('./binary')
print(disasm(elf.read(elf.symbols['main'], 100)))
Step 2: Identify Dangerous Functions
Buffer Overflow Sources
| Function | Risk | Pattern |
|---|---|---|
gets() | Critical | No bounds checking |
scanf("%s") | Critical | No width specifier |
strcpy() | High | No length check |
strcat() | High | Can overflow dest |
sprintf() | High | No bounds on output |
read() | Medium | Check size vs buffer |
Search for dangerous calls:
objdump -d ./binary | grep -E 'call.*<(gets|strcpy|sprintf|strcat|scanf)@plt>'
Format String Vulnerabilities
Check for user-controlled format strings:
# Look for printf-family calls
objdump -d ./binary | grep -E 'call.*<(printf|fprintf|sprintf|snprintf)@plt>'
Red flags in disassembly:
printfcalled directly after user input- No format string argument (just buffer)
- User buffer passed as first argument to printf
Step 3: Calculate Buffer Sizes
From Disassembly
Look for stack allocation patterns:
; x86_64
sub rsp, 0x40 ; 64 bytes allocated
lea rax, [rbp-0x30] ; Buffer at rbp-0x30 (48 bytes from rbp)
; x86
sub esp, 0x28 ; 40 bytes allocated
lea eax, [ebp-0x20] ; Buffer at ebp-0x20 (32 bytes from ebp)
Calculate Offset to Return Address
For x86_64:
- Buffer starts at [rbp - offset]
- Return address at [rbp + 8]
- Offset = offset + 8
For x86:
- Buffer starts at [ebp - offset]
- Return address at [ebp + 4]
- Offset = offset + 4
Step 4: Map Function Call Graph
For small binaries, understand the call flow:
# Using radare2
r2 -A ./binary -c 'agC' -q
# Or manual grep
objdump -d ./binary | grep 'call' | sort | uniq -c | sort -rn
Step 5: Identify Write Primitives
GOT Overwrite Targets
If Partial RELRO:
from pwn import *
elf = ELF('./binary')
# Overwrite exit@got with win function
print(f"exit@got: {hex(elf.got['exit'])}")
print(f"win: {hex(elf.symbols['win'])}")
Stack-based Targets
- Return addresses
- Function pointers on stack
- Saved base pointers (for stack pivoting)
Step 6: Find Leak Opportunities
Format String Leaks
If format string vulnerability exists:
%pleaks stack values%sleaks strings at stack addresses- Calculate offset to leak canary, libc, PIE base
puts/printf on Stack Data
Look for functions that print stack buffers - may leak canary or addresses.
Vulnerability Patterns
Pattern 1: Simple Buffer Overflow
void vuln() {
char buf[64];
gets(buf); // Overflow here
}
Disassembly shows:
sub rsp, 0x50(stack allocation)call gets@pltwith buffer on stack
Pattern 2: Off-by-One
void vuln() {
char buf[64];
for(int i = 0; i <= 64; i++) // <= instead of <
buf[i] = getchar();
}
Can overwrite least significant byte of saved RBP.
Pattern 3: Format String
void vuln() {
char buf[64];
read(0, buf, 64);
printf(buf); // No format specifier
}
Allows arbitrary read/write via format string.
Output Format
## Static Analysis
### Findings
- Vulnerability: Buffer overflow in vuln() via gets()
- Buffer size: 64 bytes at [rbp-0x40]
- Offset to RIP: 72 bytes (64 + 8 for saved RBP)
- Win function: 0x401234 (win)
- Dangerous calls: gets@plt at 0x401186
### Disassembly Highlights
```asm
vuln:
push rbp
mov rbp, rsp
sub rsp, 0x40 ; 64 byte buffer
lea rax, [rbp-0x40] ; Buffer address
mov rdi, rax
call gets@plt ; VULNERABLE
Implications
- Direct ret2win possible (no PIE, no canary)
- Payload: 72 bytes padding + address of win()
Next Steps
- Confirm offset with cyclic pattern
- Craft payload: b'A'*72 + p64(0x401234)
- Test locally before remote
## Quick Reference
```bash
# Full static analysis one-liner
objdump -d -M intel ./binary | grep -E '(main>:|vuln|gets|strcpy|printf|system|call|ret|leave)'
Additional Resources
References
references/vulnerability-patterns.md- Common vulnerability patterns in CTF binariesreferences/stack-layout.md- Detailed stack frame layouts for x86/x64references/gadgets.md- Common ROP gadget patterns
Source
git clone https://github.com/allsmog/pwn-claude-plugin/blob/main/pwn-htb/skills/static-analysis/SKILL.mdView on GitHub Overview
Static analysis inspects a binary without executing it to identify vulnerabilities, understand program flow, and map exploitation targets. It emphasizes disassembly, dangerous function identification, and vulnerability pattern recognition to guide reverse engineering.
How This Skill Works
Use tools like objdump, radare2, or pwntools to disassemble key functions and inspect control flow. The process then flags risky calls (e.g., gets, strcpy, sprintf), checks for format string patterns, and evaluates buffer sizes and stack layouts. Finally, it builds a call graph and identifies potential write primitives and leak opportunities to guide exploitation planning.
When to Use It
- Disassemble a binary to understand main flow and identify vulnerable functions.
- Identify dangerous input handlers and unsafe library calls in the binary.
- Calculate buffer sizes and stack layout to plan exploitation offsets.
- Map the function call graph and locate write primitives or GOT/PLT targets.
- Search for leak opportunities and format string vulnerabilities.
Quick Start
- Step 1: Disassemble the binary with objdump or radare2, focusing on main and user-input paths.
- Step 2: Identify dangerous functions and format string patterns in the disassembly.
- Step 3: Calculate buffer sizes and offset to return address, then map a simple call graph to locate exploit targets.
Best Practices
- Cross-verify disassembly with objdump, radare2, and pwntools.
- Search for dangerous function calls like gets, strcpy, strcat, and sprintf.
- Check for format string usage and missing format specifiers after user input.
- Analyze stack allocations (sub rsp/esp) to estimate buffer size and return address offset.
- Construct a minimal call graph to pinpoint where writes or leaks can occur and validate canary status.
Example Use Cases
- A CTF-style binary where a gets-based overflow is uncovered through disassembly and stack analysis.
- A binary contains a printf-family call with a user-controlled format string vulnerability discovered via disassembly.
- Reverse engineering a binary to locate dangerous input handlers and potential overflow paths.
- Determining the offset to the return address on x86_64 by analyzing sub rsp and lea patterns.
- A GOT overwrite scenario where exit@got is redirected toward a winner function to demonstrate exploitation potential.