抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

加密代码:

1
2
3
4
5
6
7
8
# FROM python:3
import random
with open("flag.txt","rb") as f:
flag=f.read()
for i in range(2**64):
print(random.getrandbits(32)+flag[random.getrandbits(32)%len(flag)])
input()

明显是随机数预测类型的题了,每次循环都进行了两次getrandbitsgetrandbits,因为后面这部分flag[random.getrandbits(32)%len(flag)最多也就255,反正很小,如果考虑是可见字符,就更小了,所以最多只能影响到低8比特

简单测试一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import random
flag = b'XTCF{22333111}'
res, data = [], []
for i in range(2**64):
a = random.getrandbits(32)
b = random.getrandbits(32)
res.append(a + flag[b % len(flag)])
t1 = a >> 24
t2 = res[i] >> 24
if t1 != t2:
print(i)
print(t1)
print(t2)
break


'''
203649
34
35
'''

出现误差都是到很后面才出现的,我们还原随机数生成器的状态也不需要这么多,所以放心搞就行

其实这题和https://tangcuxiaojikuai.xyz/post/69eaef2e.html算是非常像了,这题主要理解一下MT19937的内部大概原理

可以直接理解为如下的矩阵运算(注意TTbb的列并不一定是19968,可以更多,看你进行了多少次getrandbitsgetrandbits,这边按照19968来看)

s1,19968T19968,19968=b1,19968s_{1,19968}T_{19968, 19968}=b_{1,19968}

这边的s1,19968s_{1,19968}​是statestate的初始状态,只要我们还原出这个,就可以预测随机数了

T19968,19968T_{19968, 19968}可以理解为内部的运算状态,最终得到的b1,19968b_{1,19968}就是对应的getrandbitsgetrandbits的结果

那么这边我们要得到s1,19968s_{1,19968},显然是要得到T19968,19968T_{19968, 19968}b1,19968b_{1,19968},这边的b1,19968b_{1,19968}是题目已经给我们的,通常也就是随机数的结果,都是知道的,现在难点就是如何得到T19968,19968T_{19968, 19968}

这边的话,我们可以利用到如下的操作

image-20250310010415741

然后直接解solveleftsolve_left​就行了

最后对于可以预测getrandbitsgetrandbits的输出之后,返回拿flagflag,我们只要做个列表映射,全部映射完之后输出就行

这边直接拿鸡块的exp改改就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from Crypto.Util.number import *
from random import *
from tqdm import *
from pwn import *

io = remote('1.95.57.127', 3001)
gift = []
for i in trange(4992):
gift.append(eval(io.recvline()))
io.sendline(b'1')
RNG = Random()

def construct_a_row(RNG):
row = []
for i in range(4992): #测试了一下高8位需要4992组
row += list(map(int, bin(RNG.getrandbits(32) >> 24)[2::].zfill(8)))
RNG.getrandbits(32)
return row

L = []
for i in trange(19968):
state = [0]*624
temp = "0"*i + "1"*1 + "0"*(19968-1-i)
for j in range(624):
state[j] = int(temp[32*j:32*j+32],2)
RNG.setstate((3,tuple(state+[624]),None))
L.append(construct_a_row(RNG))

L = Matrix(GF(2),L)
# print(L.nrows(), L.ncols())
# print(L.rank())
R = []
for i in trange(4992):
R += list(map(int, (bin(gift[i] >> 24)[2:].zfill(8))))

R = vector(GF(2),R)
s = L.solve_left(R)
# print(s)


init = "".join(list(map(str,s)))
state = []
for i in range(624):
state.append(int(init[32*i:32*i+32],2))

RNG1 = Random()


for length in trange(5, 100):
RNG1.setstate((3,tuple(state+[624]),None))
flag = [0] * length
for i in gift:
tmp = i - RNG1.getrandbits(32)
flag[RNG1.getrandbits(32) % length] = tmp
if 0 not in flag:
print(bytes(flag))
break

评论

评论区