diff options
Diffstat (limited to 'meta')
| -rw-r--r-- | meta/solve.py | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/meta/solve.py b/meta/solve.py new file mode 100644 index 0000000..ef5842a --- /dev/null +++ b/meta/solve.py @@ -0,0 +1,93 @@ +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:]) |
