Wiki Mersenne

Numpy uses plain old implementation of Mersenne Twister as the default pseudo random number generation.
Now Mersenne Twister by itself is not so bad, what’s bad is actually the seed initialization ( i.e. deriving the initial state of the random number generator from the seed ) same as explained in the Wikipedia Implementation which has been replaced in Improved Initialization with a more non-linear initialization with an array of seeds.
So, given a few (very few actually) outputs from the numpy random RNG, can you recover the flag?

Note that the seed is a 32-bit value and can be bruteforced easily, thats not the goal of this challenge, the goal of the challenge is to figure out a way which works equivalently well for MT-19937-64 bit as 64-bit is out of the bounds of bruteforce for a reasonably practical CTFer :P

import os
from numpy import random
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from secret import flag

def rand_32():
    return int.from_bytes(os.urandom(4),'big')

flag = pad(flag,16)
iv,key = random.bytes(16), random.bytes(16)
cipher =,iv=iv,mode=AES.MODE_CBC)
flag = iv+cipher.encrypt(flag)


# output 
# ba84b595a6c47ab8b5229df78b313fd983368f94c86e063ad9e60b53debf4cf062e0e7ee\ 
# 975a58ede95877add16603d089a7c01b5581278440b2fc8a25e698ae869a2c67de7b8a5e\ 
# bbe47fcb6cb210237d6cb60d06dabbf7756a2364ba2fbb5b0f0c04fb4383f66ff755c725\ 
# 2b699c33
Enter the flag: Check Flag