ciscn-2025

Posted by Ma3t1n on 2025-01-15
Estimated Reading Time 19 Minutes
Words 3.8k In Total
Viewed Times

fffffhash

观察题目是让我们输入一个hash后的值等于题目给的giao值。

观察hash函数,每次都是乘一个相同的数字后再与字节值异或,由于异或的值是一个小值,我们可以当作是加减一个值,这个值的大小不大于256,所以对于一个长度为n的字节串,他的hash值应该就满足下面这个式子:
$$
base*(x^n+v_{n-1}*x^{n-1}+v_{n-2}*x^{n-2}+…+v_{1}*x+v_0)(modMOD)
$$
对于这个式子我们就可以使用格规约的方法进行攻击,测试第一个规约出来的值长度为16

这个题也可以使用中间相遇攻击的方法进行攻击,可以尝试一下,这里就不给出了。

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
from sage.all import *
MOD = 2**128
t=16
PR = PolynomialRing(Zmod(MOD), t, names='x')
xx = [PR.gen(i) for i in range(t)]
base_num = 0x6C62272E07BB014262B821756295C58D
x = 0x0000000001000000000000000000013B
giao=201431453607244229943761366749810895688
for i in range(t):
base_num = base_num * x
base_num =base_num+xx[i]
f=base_num-giao
coe=f.coefficients()
M=matrix(ZZ,t+2,t+2)
for i in range(t):
M[i,i]=1
M[t,t]=256
for i in range(t+1):
M[i,-1]=coe[i]
M[-1,-1]=MOD
H=M.LLL()
for i in H:
if(256 in i):
res=i
break

base_num = 0x6c62272e07bb014262b821756295c58d
x = 0x0000000001000000000000000000013b
MOD = 2**128
flag=[]
for i in range(len(res)):
base_num = (base_num * x) & (MOD - 1)
for k in range(256):
if((base_num^k)-base_num==res[i]):
base_num ^=k
flag.append(k)
break
ss=''
for i in flag:
ss+=hex(i)[2:].zfill(2)
print(ss)

rasnd

对于第一个部分的flag

我们观察题目给的两个式子

$$
hint1=x1\times p+y1\times q-0x114 \\ hint2=x2\times p+y2\times q-0x514
$$

x是11bit,y是114和514bit,由于x比较小,其实我们是可以通过遍历的方式求得x,可以把$x_1,x_2$当作一个已知量,题目就已经很清晰了,把p约掉后剩下q再与n做gcd即可分解n了。

对于第二个部分的flag
$(514\times p - 114\times q )^{n - p - q}=(514\times p - 114\times q ) (modn)$
所以直接联立方程组即可求出p,q还原明文,整体代码如下:

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
from tqdm import *
import math
from Crypto.Util.number import *
from sage.all import *
n=15428378682808047369729539612849773977351266907005249848551927745179589793201094228559121175032737955878647870160177160397245988513653262495752422128908799243256506605455757248368872726223873708635139946850304152435502570141379286853985364541354685264122339662762441747372478895242822893933897462705436998125064994343778026334193014741078794234731029543321503363519697567486316749015392604019903565484166338202778119436114878787666820006192734321442574905682701228037779919642807430553465725881974172731400277846697398837064840194185750356843931240280984419631010218867389259679817956941531563720176489959565536188397
c=12311541499004604200236916499349205846427096674314588086510631788926072078719351448646169918289109610507742992745781039518728731071967436965061884458130326005168245432412279626906101863478338683877895019784422395240860608685913496357594241053186169697293064446273562113197595287624822079722824077054648562740537822534033140390319787295623650383968704875832547313466734377262050704021334193507275258922262660647824318306838104067714316000286869379693942751129882040996725977381520370180207186392901674104709320401895811780418145615330784795101228750698014242817456836562876899931370268409067660675018643871717227313658
hint1=1642169733436771135664520656142188761411845959348096784398376090505380052495290097851697457504611854584152629529425307316772033432534375461053077627455193773130301015652592603250376477669193772833357092836311168720444956930063724726061060140962165091692267031606422347042905067658647729884255199407653433190610665322919179561630336761190467365
hint2=5551747138618727171773321575791733273076756615723885567436415904604966959458490277318362541649129337808802118926493262634763937750210378053453527713899901774935433023207535935321843155751766422374491886434532618700040108440935479135753975555403376309454682833100109181877266998543543846909295860103484771406415217260109315235129296658055184813958169218495709245196271855267640622190375062939285960112201873430002149251649679935167927817626331832294069313328206778
hint1=hint1+0x114
hint2=hint2+0x514
def getp(hint1,hint2,n):
for x1 in trange(1,2**11):
for x2 in range(1,2**11):
p=math.gcd(hint2*x1-hint1*x2,n)
if(p!=1):
return p
p=getp(hint1,hint2,n)
q=n//p
e = 0x10001
d=inverse(e,(p-1)*(q-1))
flag=b''
flag+=long_to_bytes(int(pow(c,d,n)))
n=27304780849694423339383484977186266330389425646528065625497565745795638648828062639473996623588698762753146235151108126420977796844428501160763319666798715218447902834612303735177872027008920401294357482031854938125709140433065827081300839613511804160316491491031632730824994184914234660446289671804022045677787702098863099539651943453926045087901898426244698413091456344802150260007283612823928043655412081343588031466645814347820061064753335412269236089640592319528756769313451596405487571315468336477244984077644293384871690534279543863484767904901210496058795440596942630968255014984731155489864246840234667001417
c=15345714434074055292694048806935544270153104021609550824876952306034067479894701698573290606861629285414856546362924472951947263518612748639904603022632760447886103691397382763388218549691497957562969398205996016066835482973092125604584119551351190484227333681302207328483167508461378264653318581823728471816676463601178380020697690176558636427767120185430857580427504967241695510761471224004993094661089353253222240299229409715246243046129930003638405080254505248363707962924419789835146265839618520569141805792060381649038337877178822148975540522056612034461760014474075882340504541481513970630835462554235470346475
hint1=17602174385973044814178733507403094284745791129903364104533711640443330458579716563753178246981073542692332433844902742118325919571150280367606023196267358245762199293741825875527085813095646769963953826540824744879337001014346793390335985309617368648336161014893966160872805800912168191899742324853272847938704487420436610804168779631219370534647095461154552565485779033131497101303042725461524799298270217450073396092439394777919860949842498974276505857076208386972099387042756791993606329357195903926533712694571189872758863613002801173053427969910237331140104634532523474080106045440196525334795994605760965286097
var('p,q')
c1=inverse(hint1,n)
f=514*p - 114*q-c1
g=p * q-n
print(solve([f,g],[p,q]))
p=160247203535926288327472656601878781443989033826771766955734470318827419391305327872790796496428041845814802384723559871289959299088000887848984637610216098983438408353121194529852283540070441367798473737141676032568377447595601130840102873781251017230839516821654257824215338216643049472594309958707439106441
q=170391621489812050399712037637431632018509218121185391060891105777675416473171049932716729939354748557973484195449133496291238596503578305511179199378536936739711381230517911177551655316019732468100928430291180811640657984776088247830397489245305174528823256517954781339979951279712313196947494726049133459137
d=inverse(e,(p-1)*(q-1))
print(flag+long_to_bytes(int(pow(c,d,n))))
#flag{edd3d199-1b37-47ff-94dc-05628985f54d}

LWEWL

对于flag的第一部分

已知
$const\times K_1,const\times K_2+m+e\times 257 $

​ 我们需要还原m,对于第二个式子,如果我们能求出$const\times K_2$后,然后由于m是小于257的,所以对于整体模257后,我们就可以消除噪声的干扰,然后还原m。所以问题就转换为求$const$,$K_1$是一个$612\times 512$的矩阵,$const$是一个$1*612$的向量,直接对$K_1$进行求解是解不出来的,因为未知数大于方程的数量,所以考虑格的方法。

​ 本题直接构造格是算不出来的,是一个1125维的格,需要使用flatter进行加速,但是格出来后也无法得到我们想要的向量,需要使用其他的方法。

​ 因为前面我们使用solve_left可以求解出一个512长度的向量,然后后面是100个零,对于$K_1$最后的100行我们可以用前面的512行线性表示

$K_{1,i}=K_1,i,i\in[0,511],K_{1,i}=\sum_{i=0}^{511}x_{i,j}\times K_{1,j},i\in[512,611]$

所以说我们前面使用solve_left求出来的解

$ cfake_i=k_i+\sum_{j=512}^{611}k_j\times x_{i,j}(modq)=>-k_i=-cfake_i+\sum_{j=512}^{611}k_j\times x_{i,j}(modq)$

对于上面的$k_i$使用格的方式进行求解

$$
\begin{bmatrix}1 && \cdots & &&x_{0,0} & x_{1,0} & \cdots & x_{99,0} \\ &1& \cdots & &&x_{0,1} & x_{1,1} & \cdots & x_{99,1} \\ \vdots&\vdots &&& & \vdots & \vdots & & \vdots \\ &&\cdots& 1& & x_{0,99} & x_{1,99} & \cdots & x_{99,99} \\ & &\cdots&&1 & cfake_{0} & cfake_{1} & \cdots & cfake_{99} \\ &&&&&q&&& \\ &&&&&&q&& \\ &&&&&&&\ddots \\ &&&&&&&&q\end{bmatrix}
$$

格出来的最短向量就是后面的$K_1$前面512位代入方程即可,然后判断一下正负号即可还原const,从而解出flag的第一部分

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from Crypto.Util.number import *
from sage.all import *
from re import findall
from subprocess import check_output
from tqdm import *
def flatter(M):
# compile https://github.com/keeganryan/flatter and put it in $PATH
z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]"
ret = check_output(["flatter"], input=z.encode())
return matrix(M.nrows(), M.ncols(), map(int, findall(b"-?\\d+", ret)))
def decrypt(const, lwe_pubkey2, enc):
return (int(enc)-int(const * vector(GF(lwe_ciphertext_modulus), lwe_pubkey2)))%lwe_plaintext_modulus

n = 512
m = n + 100
p = 257
q = next_prime(1048576)
c1,c2=load('/home/martin/code/task3/lwe_ciphertext.sobj')
k1,k2=load('/home/martin/code/task3/lwe_public_key.sobj')
pk_A=Matrix(GF(q),k1)
pk_b=Matrix(GF(q),k2)
encrypt_A=c1
encrypt_b=c2

def pk_Aexpress(pk_A):
pkA_1 = pk_A[:512,:]
pkA_2 = pk_A[512:,:]
ks = []
for row in pkA_2:
ks.append(pkA_1.solve_left(row))
return Matrix(ZZ,ks)

def fuck(A,pk_A):
c_tmp = pk_A.solve_left(A)[:-100]
tmpks = pk_Aexpress(pk_A)
ks = tmpks[:,:100]
ks = ks.stack(Matrix(ZZ,[c_tmp[:100]]))
M = Matrix(ZZ,100 + 100 + 1,100 + 100 + 1)
M[:101,:101] = identity_matrix(101)
M[:101,101:] = ks[:,:100]
M[101:,101:] = q * identity_matrix(100)
ML = flatter(M)
rows = ML[0]
c_new = [0 for i in range(612)]
c_list = Matrix(ZZ,Matrix(GF(q),rows[:100]*tmpks) + Integer(rows[100]) * Matrix(GF(q),c_tmp))[0]
for _ in range(512):
if c_list[_] == q-1:
c_new[_] = -1
else:
c_new[_] = int(c_list[_])
for _ in range(100):
if rows[_] == q-1:
c_new[_+512] = -1
else:
c_new[_+512] = int(rows[_])

return c_new

flag=''
for _ in trange(len(encrypt_A)):
A = vector(GF(q),encrypt_A[_])
b = encrypt_b[_]
c_new = fuck(A,pk_A)

c_first = c_new[:512]
c_secon = c_new[512:]

c = vector(ZZ, c_first+c_secon)
if c*pk_A != A:
c_first = [-i for i in c_first]
c = vector(ZZ, c_first+c_secon)

if c*pk_A != A:
c_first = [-i for i in c_first]
c_secon = [-i for i in c_secon]
c = vector(ZZ, c_first+c_secon)

if c*pk_A != A:
c_first = [-i for i in c_first]
c = vector(ZZ, c_first+c_secon)
# print(c*pk_A == A)
s=vector(GF(q),c)
flag+=chr(decrypt(s,k2,encrypt_b[_]))
print(flag)
#a3bc5491-fa53-4f47

另一种解法:

​ 我们其实不需要求出const,我们需要求的是$const\times K_2$,已知$const\times K_1$,所以我们其实可以只需要求出一个矩阵S使得$K_1*S=K_2$即可,攻击代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
K1 = matrix(ZZ, k1)
K2 = vector(ZZ, k2)
K1r = K1.change_ring(RDF)
K2r = K2.change_ring(RDF)
sk = K1r.solve_right(K2r)
sk = vector(GF(lwe_ciphertext_modulus), [round(x) for x in sk])
flag = []

for tmp1, tmp2 in zip(*lwe_ciphertext):
T1 = vector(GF(lwe_ciphertext_modulus), tmp1)
m = ZZ(tmp2 - T1 * sk)
if m >= lwe_ciphertext_modulus // 2:
m -= lwe_ciphertext_modulus
m = m % lwe_plaintext_modulus
flag1.append(m)
print(bytes(flag1))

​ 对于flag的第二部分

​ 这个是在一个RLWE问题,在商环f下我们有$b = a * s + e$,e就是一个噪声,所以对于这个题思路很简单就是构造一个关于a,b的格直接格规约即可,但是由于是在商环上进行的,我们需要处理多项式的乘法和模就可以成功构造格,还原flag了。

​ 首先是多项式的乘法

$(a_0,a_1,…,a_{n-1})*\begin{bmatrix}b_0&b_1&b_2&\cdots&b_{n-1}&&&& \\ &b_0&b_1&\cdots&b_{n-2}&b_{n-1} \\ &&b_0&\cdots&b_{n-3}&b_{n-2}&b_{n-1} \\ &&&\ddots&\vdots&\vdots&\vdots&\ddots \\ &&&&b_0&b_1&b_2&\cdots&b_{n-1}\end{bmatrix}=(d_0,d_1,…,d_{2n-2})$

然后我们就需要对向量d进行模f然后得到我们最后的多项式c

然后是多项式的模运算,首先对于小于n次的直接写即可,所以我们只需要计算d中大于n次的每一个系数,对于
$x^n=-(v_{n-1}x^{n-1}+v_{n-2}x^{n-2}+…+v_1x+v_0)(modf)$
然后对于$x^{n+1}$其实就是上面的式子整体乘一个$x$,然后式子就变成了
$x^{n+1}=-(v_{n-1}x^{n}+v_{n-2}x^{n-1}+…+v_1x^2+v_0x)(modf)$
而这个式子中的$x^n$我们可以使用第一个式子$x^n$来进行替换,也就可以得到$x^{n+1}$在$modf$下的系数,同理也可以递推出剩下的。

然后我们就可以得到求模运算的矩阵

$(d_0,d_1,…,d_{2n-2})\begin{bmatrix}1 \\ &1 \\ &&1 \\ &&&\ddots \\ &&&&1 \\ v_{0,0}&r_{0,1}&r_{0,2}&\cdots&r_{0,n-1} \\ v_{1,0}&r_{1,1}&r_{1,2}&\cdots&r_{1,n-1} \\ \vdots&\vdots&\vdots&\vdots&\vdots& \\ v_{n-1,0}&r_{n-1,1}&r_{n-1,2}&\cdots&r_{n-1,n-1}\end{bmatrix}=(c_0,c_1,…,c_{n-1})$

所以对矩阵

$L=\begin{bmatrix}b_0&b_1&b_2&\cdots&b_{n-1}&&&& \\ &b_0&b_1&\cdots&b_{n-2}&b_{n-1} \\ &&b_0&\cdots&b_{n-3}&b_{n-2}&b_{n-1} \\ &&&\ddots&\vdots&\vdots&\vdots&\ddots \\ &&&&b_0&b_1&b_2&\cdots&b_{n-1}\end{bmatrix}*\begin{bmatrix}1 \\ &1 \\ &&1 \\ &&&\ddots \\ &&&&1 \\ v_{0,0}&r_{0,1}&r_{0,2}&\cdots&r_{0,n-1} \\ v_{1,0}&r_{1,1}&r_{1,2}&\cdots&r_{1,n-1} \\ \vdots&\vdots&\vdots&\vdots&\vdots& \\ v_{n-1,0}&r_{n-1,1}&r_{n-1,2}&\cdots&r_{n-1,n-1}\end{bmatrix}$

进行格规约即可得到向量a,也就还原flag了

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
from Crypto.Util.number import *
from sage.all import *
from re import findall
from subprocess import check_output
def flatter(M):
# compile https://github.com/keeganryan/flatter and put it in $PATH
z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]"
ret = check_output(["flatter"], input=z.encode())
return matrix(M.nrows(), M.ncols(), map(int, findall(b"-?\\d+", ret)))
a, b, f, rlwe_modulus=load('/home/martin/code/task3/rlwe_ciphertext.sobj')
n = 64
A = a
B = b.list()
p = rlwe_modulus
def construct_poly_mul_mat(n,v,b):
assert v[-1] == 1
mat1 = Matrix(ZZ,n,2*n-1)
for i in range(n):
for j in range(n):
mat1[i,j+i] = b[j]
mat2 = Matrix(ZZ,2*n-1,n)
for i in range(n):
mat2[i,i] = 1
for i in range(n,2*n-1):
for j in range(i-n,n):
mat2[i,j] = -v[j-(i-n)]

init_row = vector(ZZ,n*[0])
for j in range(i-n):
temp = -v[n-1-j]*vector(ZZ,mat2[i-j-1])
init_row += temp
for j in range(n):
mat2[i,j] += init_row[j]
return(mat1*mat2)

v = f.list()
poly_mul_mat = construct_poly_mul_mat(n,v,A)

I = identity_matrix(n)
B_mat = Matrix(ZZ,B)
O = diagonal_matrix([0]*n)
O_vec = Matrix(ZZ,1,n)
O_vec_T = Matrix(ZZ,n,1)
L = block_matrix(ZZ,[[p*I,O,0],[poly_mul_mat,I,O_vec_T],[B_mat,O_vec,1]])

res = flatter[L](0)

s = res[n:2*n]
for i in s:
print(chr(abs(i)),end = "")
# -8819-856a8fe5ada0
# flag{a3bc5491-fa53-4f47-8819-856a8fe5ada0}

babypqc

​ 这个题有个很简单的非预期,就是其实整个题只需要考虑最后的answer==num,而我们的num题目原意是通过MT19937进行预测后,进行正确次数的验签成功后获得flag,因此还需要多次交互使得answer刚好为1时才可以成功,但是既然我们都可以多次交互使得answer为1了,实际上也就可以使得answer为0,$\frac{1}{16}$的概率,所以多次交互后就可以获得flag了。

​ 非预期:

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

cnt = 0

while True:
cnt += 1
print(f'Try #{cnt}')
r = remote('node1.anna.nssctf.cn', '28975')
r.sendline('0')
r.sendline('[]')
r.recvuntil('hex format!')
r.interactive()
r.close()

​ 我的解法:

​ 先求解MT19937,发现p+q+d的所有bit刚好满足MT19937的预测bit数量,所以我们需要通过N还原所有的p,q,d,将式子展开,我们会发现后面的N

$N_i=(p+d_i)\times (q+d_i)=p\times q+d_i(p+q)+d_i^2=N_0+d_i(p+q)+d_i^2,i\in[1,25] \\ d_i(p+q)+d_i^2=N_i-N_0$

最后这个式子其实就是一个AGCD问题,可以使用格规约的方法。

构造格

$\begin{bmatrix}2^\rho&x2&x3&\cdots&x25 \\ &-x1&&\cdots& \\ &&-x1&\cdots \\ &&&\ddots \\ &&&&-x1\end{bmatrix},\rho=d_i^2的比特数,x_i=N_i-N_0,i\in[1,25]$

攻击代码如下:

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
res=[]
for i in range(1,26):
res.append(N[i]-N[0])
m=matrix(ZZ,25,25)
for i in range(1,25):
m[0,i]=res[i]
m[i,i]=-res[0]
m[0,0]=2**(704*2)
H=m.LLL()
for i in H:
if(i[0]%2**(704*2)==0):
d=i[0]//(2**(704*2))
if(res[0]%d==0):
d=abs(d)
pq=(res[0]//d-d)
print(pq)
break
var('p q')
f=p*q-N[0]
g=p+q-pq
solution=solve([f,g],[p,q])
# p,q
p=p>>282
q=q>>282
d=[]
for i in res:
d.append(iroot[i%pq,2](0))

还原p,q,d后我们可以成功拿到满足MT19937的攻击要求的比特数量,使用extend_mt19937_predictor库可以预测已知比特的前后的随机数https://github.com/NonupleBroken/ExtendMT19937Predictor

一开始我还在考虑我可以预测出tmp的所有值,是否可以通过

$s_1\times tmp_1=H_1 \\ s_2\times tmp_2=H_2$

就像task3中使用格的方法进行规约,但是我们只有625个方程,但是需要求出1024长度的向量,向量中的值在$[-2,2]$之间,比task3的条件苛刻了很多,实操后也并没有规约出正确的向量,所以考虑是否有什么信息没有考虑到。这个时候我看到后面有个让我输入m然后会返回一个关于m的签名值,我的第一反应是可能在m签名中会涉及到$s_1,s_2$的一些关系可以进行攻击,查看c语言的源码有点困难,遂放弃。随后突然想起题目最后是让我实现系统中一开始给出的m的签名值,而我们是可以在输入m时之前就可以获得系统的m签名了,所以我们并不需要还原$s_1,s_2$。

整体代码如下:

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
58
59
60
61
62
63
64
65
66
67
68
69
70
from random import getrandbits
from sage.all import *
from pwn import *
from gmpy2 import iroot
from extend_mt19937_predictor import ExtendMT19937Predictor
from re import findall
from subprocess import check_output
def flatter(M):
# compile https://github.com/keeganryan/flatter and put it in $PATH
z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]"
ret = check_output(["flatter"], input=z.encode())
return matrix(M.nrows(), M.ncols(), map(int, findall(b"-?\\d+", ret)))
while(1):
r = remote('', '')
s=r.recvuntil(b'N = ')
N=eval(r.recvuntil(b']').decode())
res=[]
for i in range(1,26):
res.append(N[i]-N[0])
m=matrix(ZZ,25,25)
for i in range(1,25):
m[0,i]=res[i]
m[i,i]=-res[0]
m[0,0]=2**(704*2)
H=flatter(m)
for i in H:
if(i[0]%2**(704*2)==0):
d=i[0]//(2**(704*2))
if(res[0]%d==0):
d=abs(d)
pq=(res[0]//d-d)
break
p,q=var('p,q')
f=p*q-N[0]
g=p+q-pq
solution=solve([f,g],[p,q])
s=str(solution[0]).split('==')
p=eval(s[1].split[','](0))
q=eval(s[2].split[']'](0))
p=p>>282
q=q>>282
d=[]
print('getpq!!')
for i in res:
d.append(iroot[i%pq,2](0))
rc = ExtendMT19937Predictor()
sub=''
sub+=bin[p](2:).zfill(1184)
sub+=bin[q](2:).zfill(1184)
for i in d:
sub+=bin[i](2:).zfill(704)
for i in range(78):
c=int(sub[i:i+256],2)
rc.setrandbits(c,256)
for _ in range(78):
s=rc.backtrack_getrandbits(256)
m=rc.backtrack_getrandbits(256)
s=r.recvuntil(b'm: ')
r.sendline(str(m).encode())
s=r.recvuntil(b'sinature = ')
sig=r.recvuntil[b'\n'](:-1)
s=r.recvuntil(b'signatures: ')
sig=b"['"+sig+b"']"
r.sendline(sig)
flag=r.recv()
if(b'}' in flag):
print(flag)
break
r.close()

经过测试,发现对于同样的密钥和同样的明文,签名后的签名值是一样的,所以对于最后那个点,对于任意的num如何构造出num种签名仍然未知,各位师傅可以尝试一下。


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !