题目
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)
附件
这道题的漏洞在于这个函数:
random.getrandbits(32)
MT19973算法能生成1-623个32位随机数,而我们有 (32/32+64/32+96/32)*104=624个已知随机数,那么我们就完全可以求出下一个随机数。
这里生成的一组数据里分别是32位、64位、96位,这里我们只需要32位,所以需要把64位和96位的数分成两个或者三个32位数,可以用它们与32位全为1的二进制数来分离。
这里可以直接引用RandCrack库,将已经生成的624个数按顺序传入RandCrack函数里,利用predict_getrandbits来计算出下一个32位随机数,再使用md5加密一下就可以得到flag。
exp:
from randcrack import RandCrack
from hashlib import md5
with open(r'random.txt','r') as f:
l = f.readlines()
l = [int(i.strip()) for i in l] #strip函数用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列,这里就默认为空格
arr = []
#print(l)
for i in range(len(l)):
if i %3 == 0:
arr.append(l[i]) #第三位数或三的倍数位就是32位数,直接加入
elif i %3 == 1:
arr.append(l[i] & (2**32-1)) #64位数,包含两个32位数,取第一个32位数,64位与32个1按位与,结果剩下低位32位
arr.append(l[i] >> 32) #右移32位,保留高位32位
else:
arr.append(l[i] & (2**32-1)) #保留低32位
arr.append(l[i] & (2**64-1)>>32) #保留中间32位
arr.append(l[i]>>64) #保留高32位
rc = RandCrack() #解题关键函数
for i in arr:
rc.submit(i) #按顺序传入RandCrack函数
flag = rc.predict_getrandbits(32) #预测下一个32位数
print(md5(str(flag).encode()).hexdigest()) #md5加密
flag{14c71fec812b754b2061a35a4f6d8421}
成功拿到flag!!!