defextract_number(self): if self.mti == 0: self.twist() y = self.mt[self.mti] y = y ^ y >> 11 y = y ^ y << 7 & 2636928640 y = y ^ y << 15 & 4022730752 y = y ^ y >> 18 self.mti = (self.mti + 1) % 624 return _int32(y)
deftwist(self): for i inrange(0, 624): y = _int32((self.mt[i] & 0x80000000) + (self.mt[(i + 1) % 624] & 0x7fffffff)) self.mt[i] = (y >> 1) ^ self.mt[(i + 397) % 624]
if y % 2 != 0: self.mt[i] = self.mt[i] ^ 0x9908b0df
逆extract_number
extract_number是最后进行随机数返回的,所以要先逆
而位运算都是可以逆的,就算魔改了数据也一样
1 2 3 4 5 6 7 8 9
defrecover_state(out): state = [] for i in out: i = inverse_right(i, 18) i = inverse_left_values(i, 15, 4022730752) i = inverse_left_values(i, 7, 2636928640) i = inverse_right(i, 11) state.append(i) return state
逆extract_number plus
魔改了位运算的形式,比如
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defrand(self): if self.index == 0: self.generate() y = self.MT[self.index] y = y ^ self.cs2l(y, 11) ^ self.cs2l(y,15) y = y ^ self.cs2r(y,7) ^ self.cs2r(y,19) self.index = (self.index + 1) % 624 return y
defrecover_state(out): ret = [] for _ in out: y = _ for j inrange(7): y = y ^ cs2r(y, 7) ^ cs2r(y, 19) for j inrange(7): y = y ^ cs2l(y, 11) ^ cs2l(y, 15) ret.append(y) return ret
defbacktrace(cur): high = 0x80000000 low = 0x7fffffff mask = 0x9908b0df state = cur for i inrange(623, -1, -1): tmp = state[i] ^ state[(i + 397) % 624] # recover Y,tmp = Y if tmp & high == high: tmp ^= mask tmp <<= 1 tmp |= 1 else: tmp <<= 1 # recover highest bit res = tmp & high # recover other 31 bits,when i =0,it just use the method again it so beautiful!!!! tmp = state[i - 1] ^ state[(i + 396) % 624] # recover Y,tmp = Y if tmp & high == high: tmp ^= mask tmp <<= 1 tmp |= 1 else: tmp <<= 1 res |= (tmp) & low state[i] = res return state
逆init
初始化624位状态,其中初始值,即种子可以自己定
其实就是一个模运算,可以求个逆元逆回来
1 2 3 4 5 6 7 8 9 10 11 12 13 14
definvert_right(res, shift): tmp = res for i inrange(32 // shift): res = tmp ^ res >> shift return _int32(res)
defrecover(last): n = 1 << 32 inv = invert(2037740385, n) for i inrange(623, 0, -1): last = ((last - 1) * inv) % n last = invert_right(last, 30) return last
for i inrange(1,624): t = 1314433253 * (self.MT[i-1] ^ (self.MT[i-1] >> 30)) + 1 self.MT[i] = t & 0xffffffff print(self.MT)
defgenerate(self): for i inrange(624): y = (self.MT[i] & 0x80000000) + (self.MT[(i+1)%624] & 0x7fffffff) self.MT[i] = self.MT[(i+397)%624] ^ (y >> 1) if y & 1: self.MT[i] ^= 2567483520
defrand(self): if self.index == 0: self.generate() y = self.MT[self.index] y = y ^ self.cs2l(y, 11) ^ self.cs2l(y,15) y = y ^ self.cs2r(y,7) ^ self.cs2r(y,19) self.index = (self.index + 1) % 624 return y
import os secret = int(os.urandom(4).hex(),16) print(secret) r = Myrand(secret) out = [] for i inrange(624): out.append(r.rand()) print(out) try: for i inrange(2): a = int(input("Your "+['first','second'][i]+ " see: ")) print(out[a % len(out)]) guess = int(input("You konw my secret? ")) if guess == secret: print("For you ~") print(os.getenv("DASFLAG")) exit() else: print(["Try again~ ","Bye~"][i]) except Exception as e: exit()
Yusa的密码学课堂——三行情书
题目代码
1 2 3
import random output=[random.getrandbits(32) & 2037740385for i inrange(2000)] flag = 'DASCTF{'+hex(random.getrandbits(32*4))[2:] + '}'# DASCTF{3797****************************}
defmt19937truncated(): a = 2037740385 a = bin(a)[2:].rjust(32, '0') x = [] for i inrange(len(a)): if a[i] == '0': x.append(i) r1 = Random() ut = Untwister() r = for i in r: ut.submit(fun(i, x)) r1.getrandbits(32)