"""
Launch Remcos with SSL_CERT_FILE + apply IAT patches.
Run WHILE server_only.py is running in another terminal.
"""
import ctypes, ctypes.wintypes as wt, struct, subprocess, os, sys, time

PROCESS_ALL_ACCESS = 0x1F0FFF
PAGE_EXECUTE_READWRITE = 0x40
MEM_COMMIT, MEM_RESERVE = 0x1000, 0x2000
UNPACK_ADDR, UNPACK_SIG = 0x8EEED8, b'\x55\x8b\xec\x6a'

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
OpenProcess = kernel32.OpenProcess; OpenProcess.restype = wt.HANDLE
ReadProcessMemory = kernel32.ReadProcessMemory; ReadProcessMemory.restype = wt.BOOL
WriteProcessMemory = kernel32.WriteProcessMemory; WriteProcessMemory.restype = wt.BOOL
VirtualAllocEx = kernel32.VirtualAllocEx; VirtualAllocEx.restype = wt.LPVOID
VirtualProtectEx = kernel32.VirtualProtectEx; VirtualProtectEx.restype = wt.BOOL
CloseHandle = kernel32.CloseHandle

def read_mem(h, addr, sz):
    buf = ctypes.create_string_buffer(sz); n = ctypes.c_size_t(0)
    return buf.raw[:n.value] if ReadProcessMemory(h, addr, buf, sz, ctypes.byref(n)) else None

def write_mem(h, addr, data):
    old = wt.DWORD(0)
    VirtualProtectEx(h, addr, len(data), PAGE_EXECUTE_READWRITE, ctypes.byref(old))
    n = ctypes.c_size_t(0); buf = ctypes.create_string_buffer(data)
    ok = WriteProcessMemory(h, addr, buf, len(data), ctypes.byref(n))
    VirtualProtectEx(h, addr, len(data), old.value, ctypes.byref(old))
    return ok and n.value == len(data)

def main():
    d = os.path.dirname(os.path.abspath(__file__))
    exe = os.path.join(d, "Remcos v7.2.2 Pro.exe")

    # Set SSL env
    ca = os.path.join(d, "certs", "ca_bundle.pem")
    if os.path.exists(ca):
        os.environ["SSL_CERT_FILE"] = ca
        os.environ["SSL_CERT_DIR"] = os.path.join(d, "certs")
        print(f"[+] SSL_CERT_FILE={ca}")

    # Kill old
    subprocess.run(['taskkill', '/F', '/IM', 'Remcos v7.2.2 Pro.exe'], capture_output=True)
    time.sleep(1)

    # Launch
    proc = subprocess.Popen([exe], cwd=d)
    pid = proc.pid; print(f"[+] PID {pid}")

    h = None
    for _ in range(30):
        h = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
        if h: break
        time.sleep(0.1)
    if not h: print("[-] Can't open"); return

    # Wait unpack
    print("[*] Waiting for unpack...")
    t0 = time.time()
    while time.time() - t0 < 45:
        if proc.poll() is not None: print("[-] Exited early"); CloseHandle(h); return
        if read_mem(h, UNPACK_ADDR, 4) == UNPACK_SIG: break
        time.sleep(0.05)
    else: print("[-] Timeout"); CloseHandle(h); return
    print(f"[+] Unpacked {time.time()-t0:.1f}s"); time.sleep(0.2)

    # Stubs
    page = VirtualAllocEx(h, None, 4096, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
    stub = bytearray(32)
    stub[0x00] = 0xC3  # ret
    stub[0x04:0x07] = b'\xC2\x04\x00'  # ret 4
    stub[0x08:0x10] = b'\xB8\x01\x00\x00\x00\xC2\x18\x00'  # CryptVerify -> TRUE
    write_mem(h, page, bytes(stub))

    # Exit hooks
    for addr, off, name in [(0x9DF18C,0,"Halt"),(0x4C36428,4,"PostQuitMessage"),
        (0xA1007C,4,"ExitProcess1"),(0x4C36590,4,"ExitProcess2"),(0x4C36AE8,4,"ExitProcess3")]:
        write_mem(h, addr, struct.pack('<I', page+off)); print(f"  [+] {name}")

    # Crypto IAT
    for addr in [0x9DF0F8, 0x4C364FC]:
        write_mem(h, addr, struct.pack('<I', page+0x08)); print("  [+] CryptVerify IAT")

    # Builder gate
    write_mem(h, 0x983F9C, b'\x01'); print("  [+] Builder gate=1")
    # TLS init
    write_mem(h, 0x97126C, struct.pack('<I', 1)); print("  [+] TLS flag=1")

    print(f"\n[+] Done. Remcos PID {pid}")
    print("[*] Enter email in auth dialog. Server handles the rest.")
    CloseHandle(h)
    proc.wait()

if __name__ == "__main__": main()
