Get the FREE Ultimate OpenClaw Setup Guide →

PWN Static Analysis

npx machina-cli add skill allsmog/pwn-claude-plugin/static-analysis --openclaw
Files (1)
SKILL.md
5.4 KB

PWN 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

  1. Main function and program flow
  2. Vulnerable functions (user input handlers)
  3. Buffer sizes and stack layouts
  4. Dangerous function calls
  5. Potential write primitives
  6. 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

FunctionRiskPattern
gets()CriticalNo bounds checking
scanf("%s")CriticalNo width specifier
strcpy()HighNo length check
strcat()HighCan overflow dest
sprintf()HighNo bounds on output
read()MediumCheck 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:

  • printf called 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:

  • %p leaks stack values
  • %s leaks 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@plt with 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

  1. Confirm offset with cyclic pattern
  2. Craft payload: b'A'*72 + p64(0x401234)
  3. 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 binaries
  • references/stack-layout.md - Detailed stack frame layouts for x86/x64
  • references/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

  1. Step 1: Disassemble the binary with objdump or radare2, focusing on main and user-input paths.
  2. Step 2: Identify dangerous functions and format string patterns in the disassembly.
  3. 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.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers