from pwn import * import random import subprocess import sys import time # MT19937 constants W, N, M, R = 32, 624, 397, 31 A = 0x9908B0DF w_upper = (1 << W) - (1 << R) w_lower = (1 << R) - (1 << 0) w_full = (1 << W) - (1 << 0) def _mask_lower(n): return (1 << n) - (1 << 0) def mask_lower(bits, n, shl): mask = _mask_lower(n) return (bits & mask) << shl def _mask_upper(n): return (1 << W) - (1 << (W - n)) def mask_upper(bits, n, shr): mask = _mask_upper(n) return (bits & mask) >> shr def undo_selfxor(bits, mask, shr, shl): dirty = (mask << shl) >> shr clean = w_full ^ dirty assert(dirty == (dirty & w_full)) rec = bits & clean while dirty != 0: pre = clean & ((dirty << shr) >> shl) post = ((pre << shl) >> shr) & w_full assert(pre != 0) # we can recover new bits rec |= (((rec & pre) << shl) >> shr) ^ (bits & post) clean |= post dirty &= w_full ^ clean return rec def harden(bits): bits ^= mask_upper(bits, W - 11, 11) bits ^= mask_lower(bits, W - 7, 7) & 0x9d2c5680 bits ^= mask_lower(bits, W - 15, 15) & 0xefc60000 bits ^= mask_upper(bits, W - 18, 18) return bits def unharden(bits): bits = undo_selfxor(bits, _mask_upper(W - 18), 18, 0) bits = undo_selfxor(bits, _mask_lower(W - 15) & (0xefc60000 >> 15), 0, 15) bits = undo_selfxor(bits, _mask_lower(W - 7) & (0x9d2c5680 >> 7), 0, 7) bits = undo_selfxor(bits, _mask_upper(W - 11), 11, 0) return bits val = random.getrandbits(32) assert(unharden(harden(val)) == val) # for initial state population from seed def mul_a(x): return (x >> 1) ^ (A * (x & 1)) def gen_next(states): si = len(states) x = (states[si - N] & w_upper) | (states[si - N + 1] & w_lower) return states[si - N + M] ^ mul_a(x) def main(host="localhost", port="9051"): io = remote(host, int(port)) retries = 100 good = 9 values = [] for n in range(retries): assert(io.readline() == b"Hints:\n") for i in range(good): values.append(unharden(int(io.readline()))) assert(io.readline() == b"Guess:\n") if n == retries - 1: break values.append(None) io.sendline(b"0") predict = gen_next(values) io.sendline(str(harden(int(predict))).encode()) print(io.readline().decode()) if __name__ == "__main__": main(*sys.argv[1:])