[GKCTF 2021]Random
[GKCTF 2021]Random题目import randomfrom hashlib import md5def 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
[GKCTF 2021]Random
题目
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)
解题
通过读代码,知道是求生成104组随机数之后的一个随机数
通过算法出的随机数是伪随机数,这里用到的随机数生成函数是random.getrandbits(k)
random.getrandbits(k)
返回具有 k 个随机比特位的非负 Python 整数。 此方法随 MersenneTwister 生成器一起提供,其他一些生成器也可能将其作为 API 的可选部分提供。 在可能的情况下,getrandbits() 会启用 randrange() 来处理任意大的区间。
在 3.9 版更改: 此方法现在接受零作为 k 的值。
所以这又是梅森算法了, MersenneTwister是为了解决过去伪随机数生成器PRNG产生的伪随机数质量不高而生成的。(指路详细解析梅森旋转算法:传送门)。我们了解到 MT19937能做生成在 1≤k≤623 个32位均匀分布的随机数。而正巧我们已经有624( 104 + 104 ∗ ( 64 / 32 ) + 104 ∗ ( 96 / 32 ) = 624 104+104*(64/32)+104*(96/32)=624 104+104∗(64/32)+104∗(96/32)=624)个生成的随机数了,也就是说,根据已经有的随机数我们完全可以推出下面会生成的随机数。
需要用到的是randcrack的库
先了解一下randcrack
randcrack
工作原理
该生成器基于 M e r s e n n e T w i s t e r MersenneTwister MersenneTwister(梅森算法),能够生成具有优异统计特性的数字(与真正的随机数无法区分)。但是,此生成器的设计目的不是加密安全的。您不应在关键应用程序中用作加密方案的PRNG。
您可以[在维基百科上]了解有关此生成器的更多信息(https://en.wikipedia.org/wiki/Mersenne_Twister).
这个饼干的工作原理如下。
它从生成器获得前624个32位数字,并获得Mersenne Twister矩阵的最可能状态,即内部状态。从这一点来看,发电机应该与裂解器同步。
如何使用
将生成器生成的32位整数准确地输入cracker非常重要,因为它们无论如何都会生成,但如果您不请求它们,则会删除它们。 同样,您必须在出现新种子之后,或者在生成 624 ∗ 32 624*32 624∗32位之后,准确地为破解程序馈电,因为每个 624 ∗ 32 624*32 624∗32位数字生成器都会改变其状态,并且破解程序设计为从某个状态开始馈电。
(忘了这一段是从哪里复制下来仍百度翻译的结果了)
大致意思就是:
RandCrack中有一个方法是predict_getrandbits(),在给出的随机数数量多时,可以预测下一个随机数。
from hashlib import md5
from randcrack import RandCrack
def foo(l,i):
a=[]
a.append(l[i])
b1=l[i+1]>>32
b2=l[i+1]&(2**32-1)
a.append(b2)
a.append(b1)
b1=l[i+2]>>64
b2=(l[i+2]&(2**64-1))>>32
b3=l[i+2]&(2**32-1)
a.append(b3)
a.append(b2)
a.append(b1)
return a
with open(r'random.txt','r') as f:
l=f.readlines()
l=[int(i.strip()) for i in l]
ll=[]
for i in range(0,len(l),3):
ll+=foo(l,i)
rc=RandCrack()
for i in ll:
rc.submit(i)
aa=rc.predict_getrandbits(32)
print(md5(str(aa).encode()).hexdigest())
代码就很容易读懂了,先将我们有的随机数排列到一个列表ll中,然后挨个用RandCrack.submit()提交,最后用RandCrack.predict_getrandbits()预测下一个32位随机数,然后md5一下输出就好了
运行得到:14c71fec812b754b2061a35a4f6d8421
答案
GKCTF{14c71fec812b754b2061a35a4f6d8421}
(坑人,检查好几遍不知道哪错了,最后发现错到格式上了)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)