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)
random.txt
:
2584323193
1099154419438958164
35367876945070316311325317953
481304047
12782770146993102006
24789628292419559503661788402
2776391832
9046887565683900291
50006261016517120573540241998
4167723109
8540277546428614473
5932047064656933473553742683
2951765291
10958280862127627756
61364239380151547478360346674
727043053
10156271057154381198
32168336768992329620376069852
930821842
16276235036285538859
9299952556848430743503551046
2868231632
5239154873841417200
11073503953912227254738321705
3452646652
8203253126417399900
52795367131471301612397944513
1927997107
17486869700317373240
47859970254711877167132319582
1459348891
9270456490024856463
74988967035830352654888842228
3714813644
1001128959491001919
8338265486641240510773094199
1430706700
17510828220752339511
3163106687132931419335230580
663535320
9606088298064978425
42511409828594385595915384953
908684643
5421916296165007941
9630914642938890694059952508
2209941143
14999144064788271892
3764842169035734035997078921
2718456651
8541807093002241064
70305992075768658972224974121
930303353
887596273180600202
62528479418364179541352908078
3365397759
15219084820731944344
31433566654697222176709895388
1608992428
6417140575231408939
12879789575923814684090165215
2811970399
6123213785028348335
44681647388937033220521089118
1260870056
5601104844042776691
73199461252301674455633950458
883231057
17783480959798771462
53460694547508318015132953966
1332985617
6673661714524041073
54253348096650113440476985084
3911521675
3438383273755779719
50129032267969019444282164464
3311412816
8779405363908462634
77818642029003078860467063235
4204237422
17534771551489868719
47280916590275648057356977963
2090173606
12206397967662831376
9495602410639024810670107439
2896231201
7246124017447704664
64467120363081017096405905335
392254334
12789011750322942845
5247110397471141497763090834
814200188
14344105251896958923
38888779745538270252730950782
205529919
13939756220516981581
67139045733351688501202495914
3563698832
16840754399626540384
15354843719521267197455444900
1386481456
17766886653399976694
61203331542727632580855864074
2032518919
2355401958853696908
58793908005730868677649498244
3991002745
6506506581713943242
49187675946469291318483292566
2346942877
994297989736899070
45437626728896532873251413177
3841694984
14253899037419430689
8435766077661599453131339442
1679990328
5515793210854183190
32981467195097563488749918497
744869832
11965860903258650511
73456728458781563185478913274
1341354796
14941036303190219170
3601563989190071059996878006
3361509481
17629804697469609923
39935200308805986497519634478
213152541
18320881664493742431
35325602739583757661562537619
2583841550
13763800051589427155
24638499459902141689405229579
1930742512
2392210857598517491
10441235412645941387574306751
461860348
2960745717639761142
62671223148116753112168252981
342206006
6480900103080233462
68412521040142848818877222548
114798494
8473329380799862296
13698669860489083061204052132
2900249131
4183161143099214314
18705391538460150746163889528
3766817970
12378384893542868384
55065668763750424532726429526
937387269
6844068130337459179
3209183745118985928581969258
3341723085
5988612409695647387
74389503837936256104231536479
4240599755
15332231015110371140
62955965591068690743297262172
1555895753
6058791220464667520
38335642957673073804843192014
810331063
4826913432979346480
28611765156689124521247554769
2630955218
12776823600930336401
4939603509311727391894886152
3280912700
14886149455945180990
52545650130177883790984384989
2356751225
2213402912509116749
7670693824287789893690942739
1599077432
14059140725965938936
16912587144697957583184157226
1304928684
9448367331308980026
22467661289496622162065003733
2001054151
7669140498758745837
39387592809285963406216440474
1711960460
3944628516045148813
66275496498554499967007163069
1207238325
3474935157030029491
63309877710388250418928028870
759170859
5858654703302236387
47609248816278271537847269046
1571940308
8335124609741508060
63542562244865676783377908343
1103531693
673654248555391502
30211221866217572233934551180
1089271924
7205932443049001486
69303844715341292680611559319
78608136
3404862937733764913
4259499119552843766282799518
2856032696
18313272414884625578
13693483738598197670400133831
873953734
7709221139118742639
34347437826101106015248365081
1783225370
16395574393179667285
7105819215807952823387139051
4039492686
16956581102357069698
57880199206788615132959351746
4151578751
2089635663127651746
37224845035383461896791495968
3139901611
7354140220471025697
7677374435615054008235674795
2008633712
13970520912420834879
64431013803082441566118213963
1788996018
16490194110734000780
30074301251997624246501473245
2460472485
2420976394683211164
63223457068346692358441841920
83976303
11597367904222552300
541189103864720560882255271
1271705896
8355873362347678325
6344182152495584455275136810
516191728
14301559481738139949
56972815139785900061169383374
3206833632
10471460817277304217
48253348743985600958199235128
4093394606
18421023127368906484
3209763791222301851974194188
2294793393
5804188421524711527
71797815201668391465761200460
3776041666
4108093307245233290
36986873094794981638319354001
1123598142
18262625851690101956
75211342463083839154547686361
1000669502
18244976169672436911
72759872679663719847870853888
2863001571
18304840778989692776
22413497817784765711206417816
1497794697
11739492739170519132
67625171938756611423023578679
3351136254
11816001323328933293
68942708548438536419919996191
1327110822
1299589815565305619
62081225258542372826911047279
3410663545
13158537297009141542
21762078985419016317415112411
1245509971
8804545967037621189
12841311881373962346628325162
2090373367
5289193049949531539
58444176241871300895472370959
571136405
2357132884718584788
51271731657715979715595461713
1432929573
503683219995130744
42705435265543268884777575518
1452726104
2295689344585140511
56996373195070838495288737642
187502663
13760641334049999515
64971355271690455751992498230
2679386081
172294286357194222
78658263482976308261205349174
2643925505
9627451492376735719
44487428240561493246393172961
983662371
2375149476902080328
39784456552690724305541938380
3306946267
16316178008270132149
76712503805317876365091515524
3779008319
4892998918237451139
46329724632809073972496761660
3841865427
15115042473603448600
34888855489304037538590108588
585968278
15088560943809914475
46621092548977030580425482842
总共是312个随机数
分析
这一开始感觉什么思路也没有,给了个random.txt,flag的任何加密形式也没有给。
唯一的突破点就只有一个函数:random.getrandbits()
而且在该函数调用的时候,出现了三个数字32,64,96
,都是32的倍数,也不知道有什么用。
在python官方文档里有描述:
random.getrandbits(k)
返回具有 k 个随机比特位的非负 Python 整数。 此方法随 Mersenne Twister 生成器一起提供,其他一些生成器也可能将其作为 API 的可选部分提供。 在可能的情况下,getrandbits() 会启用 randrange() 来处理任意大的区间。
在 3.9 版更改: 此方法现在接受零作为 k 的值。
所以接下来我们看一看Mersenne Twister 梅森旋转算法
大概描述了一些关键的东西比如:
MT19937算法
:
可以产生32位整数序列,在$1\le k \le 623 $的维度之间都可以均等分布
这个32位序列和题目中的32刚好就对上了。但是题目中的64位和96位是怎么产生的呢?我们去了解一下MT19937算法。https://www.anquanke.com/post/id/205861#h3-4
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
python中内置的Random类就是采用了MT19937算法,getrandbits(32)方法可以获得一个32位随机数
整个获取伪随机数的过程的重点就是这个self.mt[]
也就是state块的状态。
在本题中,我们知道总共获取了312个随机数,104个32位的,104个64位的,104个96位的。他们都是由32位整数序列产生的,所以104个32位的需要产生104个随机数,104个64位的需要产生208个随机数,104个96位的需要产生312个随机数:加起来总共需要产生624个随机数。
这个数字刚刚好对应了624个state块的个数,所以按道理,我们可以将624个state块的状态推出来,然后就可以推出下面产生的随机数,也就是flag了。
Solve
from random import Random
def invert_right(m,l,val=''):
length = 32
mx = 0xffffffff
if val == '':
val = mx
i,res = 0,0
while i*l<length:
mask = (mx<<(length-l)&mx)>>i*l
tmp = m & mask
m = m^tmp>>l&val
res += tmp
i += 1
return res
def invert_left(m,l,val):
length = 32
mx = 0xffffffff
i,res = 0,0
while i*l < length:
mask = (mx>>(length-l)&mx)<<i*l
tmp = m & mask
m ^= tmp<<l&val
res |= tmp
i += 1
return res
def invert_temper(m):
m = invert_right(m,18)
m = invert_left(m,15,4022730752)
m = invert_left(m,7,2636928640)
m = invert_right(m,11)
return m
def clone_mt(record):
state = [invert_temper(i) for i in record]
gen = Random()
gen.setstate((3,tuple(state+[0]),None))
return gen
f = open("random.txt",'r').readlines()
prng = []
j=0
for i in f:
i = i.strip('\n')
print(int(i).bit_length())
if(j%3==0):
prng.append(int(i))
elif(j%3==1):#将生成两次随机数的两个随机数分离出来
prng.append(int(i)& (2 ** 32 - 1))
prng.append(int(i)>> 32)
else:#将生成三次随机数的三个随机数分离出来
prng.append(int(i)& (2 ** 32 - 1))
prng.append(int(i)& (2 ** 64 - 1) >> 32)
prng.append(int(i)>>64)
j+=1
g = clone_mt(prng[:624])
for i in range(624):
g.getrandbits(32)#产生前624个随机数,让state状态到生成flag前
key = g.getrandbits(32)
print(key)
from hashlib import md5
flag = md5(str(key).encode()).hexdigest()
print(flag)
#14c71fec812b754b2061a35a4f6d8421
参考wp:https://blog.youkuaiyun.com/m0_62506844/article/details/124278580
https://blog.youkuaiyun.com/m0_57291352/article/details/119655082
具体对MT19937的分析会在下一篇文章给出。