BUUCTF [GKCTF 2021]Random

关于MT19937的攻击

32位的MT19937python代码:

def _int32(x):
    return int(0xFFFFFFFF & x)

class MT19937:
    # 根据seed初始化624的state
    def __init__(self, seed):
        self.mt = [0] * 624
        self.mt[0] = seed
        self.mti = 0
        for i in range(1, 624):
            self.mt[i] = _int32(1812433253 * (self.mt[i - 1] ^ self.mt[i - 1] >> 30) + i)

    # 提取伪随机数
    def extract_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)

    # 对状态进行旋转
    def twist(self):
        for i in range(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

可以看出它一个大循环是以624为周期的
而观察题目给我们的源码

import random
from hashlib import md5

def get_mask():
    file = open("random.txt","w")
    for i in range(104):
        file.write(str(random.getrandbits(32))+"\n")
        file.write(str(random.getrandbits(64))+"\n")
        file.write(str(random.getrandbits(96))+"\n")
    file.close()
get_mask()
flag = md5(str(random.getrandbits(32)).encode()).hexdigest()
print(flag)

104x(1+2+3)正好=624
所以题目相当于给了我们一个完整的随机数生成块 我们可以利用RandCrack库进行预测
注意!64位 96位 这些都是由 2 3个32位拼接的 是从低位往高位拼接 注意顺序(否则会影响预测)

from hashlib import *
from randcrack import *

with open(r'\random.txt','r+') as f:
    lines = f.readlines()

num = []
for line in lines:
    line = int(line.strip())
    num.append(line)

_random = []
for i in range(len(num)):
    if i%3 == 0:
        _random.append(num[i])
    elif i%3 == 1:
        n = num[i]
        n1 = n & ((1<<32)-1)
        n2 = n >> 32
        _random.append(n1)
        _random.append(n2)
    else:
        n = num[i]
        n1 = n & ((1 << 32)-1)
        n2 = (n >> 32) & ((1 << 32)-1)
        n3 = n >> 64
        _random.append(n1)
        _random.append(n2)
        _random.append(n3)

Rc = RandCrack()
for n in _random:
    Rc.submit(n)

flag = Rc.predict_getrandbits(32)
print(md5(str(flag).encode()).hexdigest())

最后得到flag:14c71fec812b754b2061a35a4f6d8421
补 用mt19937predictor

from mt19937predictor import *

pre = MT19937Predictor()
data = open(r'.\random.txt','r+').readlines()
cnt = 0
for i in range(104):
    pre.setrandbits(int(data[i*3+0]),32)
    pre.setrandbits(int(data[i*3+1]),64)
    pre.setrandbits(int(data[i*3+2]),96)

print(cnt)
from hashlib import md5

flag = md5(str(pre.getrandbits(32)).encode()).hexdigest()
print(flag)
posted @ 2023-10-01 21:20  N0zoM1z0  阅读(77)  评论(0编辑  收藏  举报