羊城杯

z做了五道。话说最后一题sm4之后是个什么玩意?

Crypto

Bigrsa

签到题,模不互素,gcd求公共因子后就能分解了,之后就是最简单的RSA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import gmpy2
from Crypto.Util.number import *

n1=103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061
n2=115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073
e=65537
p=gmpy2.gcd(n1,n2)
q1=n1//p
q2=n2//p
phi1=(p-1)*(q1-1)
phi2=(p-1)*(q2-1)
c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264
d1=gmpy2.invert(e,phi1)
d2=gmpy2.invert(e,phi2)
c=pow(c,d2,n2)
m=pow(c,d1,n1)
print(long_to_bytes(m))

Easy_RSA

根据生成可以知道p-1和q-1smooth,并且存在公共因子也就是2g,看书之后了解到这玩意叫Common prime RSAimage-20210912095325832

因为这一题的n不大,所以a也不大,并且在模n有限域的情况下\[x^n-1\]最多就只有a个元素,那么可以考虑用Pollard rho算法分解n。其中f函数为\[f(x)=x^{n-1}+3\;mod\;n\],首先随机生成一个数x1,x2可以由f(x1)生成,然后每轮x1执行一次f,x2执行两次f(提高效率)p=gcd(|x1-x2|,n),当p不为1或n时可成功分解n。

image-20210912100142590

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
from Crypto.Util.number import *
import gmpy2

def f(x, n):
return (pow(x, n - 1, n) + 3) % n


def pollard_rho(n):
i = 1
while True:
x1 = getRandomRange(2, n)
x2 = f(x1, n)
j = 1
while True:
p = GCD(abs(x1 - x2), n)
if p == n:
break
elif p > 1:
return (p, n // p)
else:
x1 = f(x1, n)
x2 = f(f(x2, n), n)



n = 84236796025318186855187782611491334781897277899439717384242559751095347166978304126358295609924321812851255222430530001043539925782811895605398187299748256080526691975084042025794113521587064616352833904856626744098904922117855866813505228134381046907659080078950018430266048447119221001098505107823645953039
e = 58337
c = 13646200911032594651110040891135783560995665642049282201695300382255436792102048169200570930229947213493204600006876822744757042959653203573780257603577712302687497959686258542388622714078571068849217323703865310256200818493894194213812410547780002879351619924848073893321472704218227047519748394961963394668

p,q=pollard_rho(n)
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
print(long_to_bytes(pow(c,d,n)))

RingRingRing

nc后第一步是爆破md5,这里爆破了四位。

之后是要解一个方程: \[ a^4+b^4+c^4+d^4=e^2 \] 一开始以为是什么著名的曲线,查了一下没找到。突然想到这玩意没说abcd不能相等啊,相等时 \[ 4x^4=e^2\\ ∴e=2x^2 \] 嗯???这是什么意思,那传1—100不就可以了🐎?

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
from hashlib import md5
from pwn import *

def dehash(s,re):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz"
print(s,re)
for a in alphabet:
for b in alphabet:
for c in alphabet:
for d in alphabet:
ss=a+b+c+d+s
if md5(ss.encode()).hexdigest().startswith(re):
return a+b+c+d

def main():
context.log_level="debug"
p=remote('192.168.41.60',2378)
p.recvuntil(b"md5(str + ")
s= p.recvuntil(")[0:5] == ",drop=True)
hashre=p.recvline()[:-1]
print(s,hashre)
p.recvuntil(b" Give me xxxxx:")
p.sendline(dehash(s.decode(),hashre.decode()).encode())
for i in range(1,101):
p.recvuntil(b"a: ")
p.sendline(str(i).encode())
p.recvuntil(b"b: ")
p.sendline(str(i).encode())
p.recvuntil(b"c: ")
p.sendline(str(i).encode())
p.recvuntil(b"d: ")
p.sendline(str(i).encode())
p.recvuntil(b"e: ")
p.sendline(str(2*i**2).encode())
p.recvline()
p.recvline()
main()

Rsa?

根据代码前面的生成有: \[ M_y=flag,M_x=os.urandom(30)\\ Z=M_xM_y\;mod \;n\\ X=\frac{Z+\frac{1}{Z}}{2}\\ Y=M_y\\ a=\frac{\frac{1}{Z}-X}{Y},D=a^2 \]

这题定义了一个新的运算模式:

1
2
3
4
5
6
xy = lambda (x1,y1),(x2,y2) : ((x1*x2+D*y1*y2)%n, (x1*y2+x2*y1)%n)
def getloop((x,y), e):
ret = (x, y)
for i in range(e-1):
ret = xy(ret, (x,y))
return ret

之后对(X,Y)进行了e次这样的运算。

一开始想到ECC是不可逆的,所以默认了这个运算也是不可逆的,导致做了很多无用功。后来测试代码自定义数据进行计算的时候发现这个运算是可逆的,并且与a无关,也就是说a为任何值都是可逆的。所以接下来只需要拿到n的阶就能够还原X和Y(flag),现在考虑如何分解n。

由于没有其他信息可用了,那么只能硬着头皮开根号呗,没想到还真出了,那么之后就可以解了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import gmpy2
from Crypto.Util.number import *
n=13390709926509813526471364597371124446888078365567927211781799241724742352679484983709219580483800891886832613684875066109177882219522305348565532970795023
x=gmpy2.iroot(n,2)[0]
while x**2-n<=0:
x+=1

while not gmpy2.iroot(x**2-n,2)[1] :
x+=1
y=gmpy2.iroot(x**2-n,2)[0]
p=x+y
q=x-y
print(p*q==n)


还有一个点,因为对e求逆后的数据很大,用原始的loop跑的很慢很慢,所以需要改成快速幂。

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
import os
from Crypto.Util.number import *
import gmpy2
a=1762039418842677123086894939949574689744108610561557889235294034870342076452734215004689409493802437034960516295735815195656138656970901855976802991519141
e=65537
n=13390709926509813526471364597371124446888078365567927211781799241724742352679484983709219580483800891886832613684875066109177882219522305348565532970795023
x=gmpy2.iroot(n,2)[0]
while x**2-n<=0:
x+=1

while not gmpy2.iroot(x**2-n,2)[1] :
x+=1
y=gmpy2.iroot(x**2-n,2)[0]
p=x+y
q=x-y
print(p)
print(q)
assert p*q==n
phi=(p-1)*(q-1)
D=a**2%n

xy = lambda x,y : ((x[0]*y[0]+D*x[1]*y[1])%n, (x[0]*y[1]+y[0]*x[1])%n)
def getloop(x, e):
res = (1, 0)
while e!=0:
if e & 1:
res = xy(res, x)
x = xy(x, x)
e = e >> 1
return ret
d=gmpy2.invert(e,phi)
(xx,yy)=getloop((5404548088049249951619519701935576492239293254135836357417714329205323074367876875480850741613547220698045360461761929952847796420174204143917852624050110, 2110372753170830610718226848526649992911771424441223687775304654852191999130502986109306355582366065947895295520226816523397652918227241733632791793362785),d)

Mx=(2*yy*xx-1)*(gmpy2.invert(yy,n)**2)%n
print(long_to_bytes(yy))

话说这题flag解出来是pell方程很有趣,可是除了在loop里x运算用到了pell方程外似乎没有用到了呀,难道非预期?

MISS

这一题出题人自己写了个AES,查看代码后发现key一点用也没有,也就是说主要的流程都集中在这里:image-20210912102743034

那么理论上只需要简单的逆一下AES就行了。

res是16字的,subBytes操作是四字节一起运算,那么这一题和Xman结营时的re题一模一样!怀疑出题人是同一个(

image-20210912103027685

之前做的时候就是用C语言爆破,因为4字节一起所以运算量变成了256^4,现代计算机很容易就能跑出来

,把之前的代码改一下就能用了。

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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397

锘?include <stdio.h>

unsigned char SBox[] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};

unsigned char RevSbox[] = {
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
};

unsigned char GF_MULT_1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};

unsigned char GF_MULT_2[] = {
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
};

unsigned char GF_MULT_3[] = {
0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
};



unsigned char final_enc[] =
{
0x1d, 0xba,0x82,0x39,
0x1c, 0x25,0x6b,0x8d,
0x5, 0x20,0x99,0xa2,
0x17, 0x6d,0xc, 0x4f
};

#define P1
#undef P1
#define P2
#undef P2
#define P3
#undef P3
#define TEST_RDTSC



void RevSubBytes(unsigned char* Arr) {
for (int i = 0; i < 16; i++) {
Arr[i] = RevSbox[Arr[i]];
}
};


void RevShiftRow(unsigned char* Arr) {
unsigned char m[] = { 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 };
unsigned char ret[16];
for (int i = 0; i < 16; i++) {
ret[i] = Arr[m[i]];
}
for (int j = 0; j < 16; j++) {
Arr[j] = ret[j];
}
};

void RevMixColumn(unsigned char* Arr) {
unsigned char new_b0, new_b1, new_b2, new_b3;
unsigned char tmp[16] = {0};

for (int i = 0; i < 4; )
{
for (int b0 = 0; b0 < 256; b0++)
{
for (int b1 = 0; b1 < 256; b1++)
{
for (int b2 = 0; b2 < 256; b2++)
{
for (int b3 = 0; b3 < 256; b3++)
{
new_b0 = GF_MULT_2[b0] ^ GF_MULT_3[b1] ^ GF_MULT_1[b2] ^ GF_MULT_1[b3];
new_b1 = GF_MULT_1[b0] ^ GF_MULT_2[b1] ^ GF_MULT_3[b2] ^ GF_MULT_1[b3];
new_b2 = GF_MULT_1[b0] ^ GF_MULT_1[b1] ^ GF_MULT_2[b2] ^ GF_MULT_3[b3];
new_b3 = GF_MULT_3[b0] ^ GF_MULT_1[b1] ^ GF_MULT_1[b2] ^ GF_MULT_2[b3];

if (
(new_b0 == Arr[4 * i]) &&
(new_b1 == Arr[4 * i + 1]) &&
(new_b2 == Arr[4 * i + 2]) &&
(new_b3 == Arr[4 * i + 3])
)
{
tmp[4 * i] = b0;
tmp[4 * i + 1] = b1;
tmp[4 * i + 2] = b2;
tmp[4 * i + 3] = b3;
goto END;
}

}
}
}
}
END:

i++;
}

for (int j = 0; j < 16; j++)
{
Arr[j] = tmp[j];
}

};

#define Final
#undef Final

int main(void) {
#ifdef P1
unsigned char tmp2;
unsigned char arr2[16];
for (int k = 0; k <= 0xF; ++k)
{
for (int i = 0; i < 256; ++i) {
tmp2 = *((unsigned __int8*)&DwArr[64 * k + 36864] + i);
if (tmp2 == Enc[k]) {

//printf("i:%d\n", i);
arr2[k] = i;
}
}

}

for (int i = 0; i < 16; i++) {
printf("%02x ", arr2[i]);
}
putchar('\n');
#endif
#ifdef P2
unsigned int tmp;
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
for (int k = 0; k < 256; k++) {
for (int m = 0; m < 256; m++) {
tmp = DwArr[29440 + i] ^ DwArr[29184 + j] ^ DwArr[28928 + k] ^ DwArr[28672 + m];
if (tmp == 0xac110172) {
printf("%d, %d, %d, %d", i, j, k, m);
goto End;
}
}
}
}
}
#endif
#ifdef P3

unsigned char test1[] = {
0x72, 0x01, 0x11, 0xac,
0x65, 0x5f, 0x18, 0x38,
0x30, 0xe2, 0x67, 0xad,
0x5c, 0x42, 0xe7, 0x0d
};
unsigned char test2[] = {
0x72, 0x5f, 0x67, 0x0d,
0x65, 0xe2, 0xe7, 0xac,
0x30, 0x42, 0x11, 0x38,
0x5c, 0x01, 0x18, 0xad
};
/*
unsigned char test1[] = {
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15
};
unsigned char test2[] = {
0, 5,10,15,
4, 9,14, 3,
8,13, 2, 7,
12, 1, 6, 11
};
*/
RevShiftBytes(test2);
for (int i = 0; i < 16; i++) {
printf("%d ", test1[i] - test2[i]);
}
putchar('\n');
#endif


#ifdef TEST
// SBox + Shift
unsigned char test1[] = { 99, 107, 103, 118, 242, 1, 171, 123, 48, 215, 119, 197, 254, 124, 111, 43 };
// SBox
unsigned char test2[] = { 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118 };
// SBox + Shift + Mix
unsigned char test3[] = { 106, 106, 92, 69, 44, 109, 51, 81, 176, 217, 93, 97, 39, 156, 33, 92 };

RevMixColumn(test3);
puts("RevMixColumn");
for (int h = 0; h < 16; h++) {
printf("%d ", test3[h]);
}
putchar('\n');
RevShiftRow(test3);
puts("RevShiftBytes:");
for (int h = 0; h < 16; h++) {
printf("%x ", test3[h]);
}
putchar('\n');
RevSubBytes(test3);
puts("RevSubBytes:");
for (int h = 0; h < 16; h++) {
printf("%x ", test3[h]);
}
putchar('\n');


//for (int i = 0; i < 10; i++) {

//}


#endif

unsigned char final_enc[] =
{
0x1d, 0xba,0x82,0x39,
0x1c, 0x25,0x6b,0x8d,
0x5, 0x20,0x99,0xa2,
0x17, 0x6d,0xc, 0x4f
};

RevShiftRow(final_enc);
puts("RevShiftRow:");
for (int h = 0; h < 16; h++) {
printf("%x ", final_enc[h]);
}
putchar('\n');
RevSubBytes(final_enc);
puts("RevSubBytes:");
for (int h = 0; h < 16; h++) {
printf("%x ", final_enc[h]);
}
putchar('\n');


for (int i = 1; i < 10; i++)
{
RevMixColumn(final_enc);
puts("RevMixColumn");
for (int h = 0; h < 16; h++) {
printf("%x ", final_enc[h]);
}
putchar('\n');

RevShiftRow(final_enc);
puts("RevShiftRow:");
for (int h = 0; h < 16; h++) {
printf("%x ", final_enc[h]);
}
putchar('\n');
RevSubBytes(final_enc);
puts("RevSubBytes:");
for (int h = 0; h < 16; h++) {
printf("%x ", final_enc[h]);
}
putchar('\n');
}
puts("Finally:");
for (int i = 0; i < 16; i++)
{
printf("%02x " ,final_enc[i]);
}
putchar('\n');

puts((const char*)final_enc);



#ifdef Final
unsigned int tmp;

for (int a = 8; a >= 0; --a) {
for (int b = 3; b >= 0; ) {


for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
for (int k = 0; k < 256; k++) {
for (int m = 0; m < 256; m++) {
tmp = DwArr[256 * (4 * b + 3 + 16 * a) + i] ^ // i == out[4*b + 3]
DwArr[256 * (4 * b + 2 + 16 * a) + j] ^ // j == out[4*b + 2]
DwArr[256 * (4 * b + 1 + 16 * a) + k] ^ // k == out[4*b + 1]
DwArr[256 * (4 * b + 0 + 16 * a) + m]; // m == out[4*b + 0]
if (tmp == ((unsigned int*)Enc)[b]) {
printf("a:%2d; b:%2d | ", a, b);
printf("%02x, %02x, %02x, %02x \n", i, j, k, m);
Enc[4 * b] = m;
Enc[4 * b + 1] = k;
Enc[4 * b + 2] = j;
Enc[4 * b + 3] = i;
goto Label1;
}
}
}
}
}



Label1:
--b;
}
RevShiftBytes(Enc);
//putchar('\n');
}
for (int h = 0; h < 16; h++) {
printf("%x ", Enc[h]);
}
putchar('\n');
#endif

return 0;
}

会不会是因为当时没人做所以又丢过来了?2333因为队里的re师傅复盘了这一题所以就有印象了

赛博朋克人

之前打CTFshow的吃瓜杯了解到一个库叫pycipher,内置了enigma函数,可以直接调用。

image-20210912111805833

这个表显示了9月每一天的参数信息,接下来只需要找出是哪一天的参数即可

image-20210912111851723

根据题目给出的提示:当今网络世界有电子越共,那么也会有赛博德国人,而且还喜欢用相同的密码,请找出他们的通信内容(内容是德文,flag是正常的flag,而且通信的格式还原历史,传递密钥的方法为二战中后期改进的)。

之后查询了大量资料,总算是还原出了这些内容所代表的含义:

1
2
3
0911 = 1tle = 1tl = 350 = RZS NAJ =
nkfgp roqad boprv yrdhy zwamf qsrhb owqvt jzotr ffcjq snpqh kpwzm fprru gufez xsuws aohyw xbreu pifbz kagxj blbha jzixj zrasn zxkay lpaza ejwou itcip dfdgp rbjnv xuqzq qhtya xwwik wyybx kdgrc slrkj pgjay aidwa jeszp pbqat njojg jrplb kkhot joqpg vwecj soabm aupsr fenug ybxmr jloch kmjgc tznxl tnrqx pbeph fwymn gpoor pjkkb plkwb kxzeq quorp ipuvs utyae qyzgp mqnai iysse gzsht tsrmv crrkr opuxj tqshv ypdrw rvnzt cstlj

第一行:9月11日的内容,总共一部分,这是第一部分,有350个字母(包括第一组的buchstabenkennngruppe),所谓buchstabenkennngruppe NKFGP显示出了操作者的键位设置,用于加密信息。其中前两个为随机字母,后面三个为某一天的kennngruppe信息,根据上表可以知道这是用的9月10号的参数。于是可以确定rotors,ringstellung,steckers参数,那么初始设置settings呢?

别忘了,我们第一行还有两组字母,其中RZS是操作者的初始设置,而NAJ为结果,那么以RZS为初始键位设置,解密NAJ后得到的信息便是接收者需要设置的settings。reflector参数只可能是ABC,这里可以爆破。

综上,我们已经拿到了解密enigma所需要的全部信息。逐个尝试后发现用B的reflector解密出来的内容重复率很高,一开始卡住了。题目所说的是德国,正好我有个室友会德语,于是让他帮忙看一下,一眼就看出来是德文数字,于是翻译过来拿到结果一串字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pycipher import Enigma
import string

dic = string.ascii_uppercase
c='roqadboprvyrdhyzwamfqsrhbowqvtjzotrffcjqsnpqhkpwzmfprrugufezxsuwsaohywxbreupifbzkagxjblbhajzixjzrasnzxkaylpazaejwouitcipdfdgprbjnvxuqzqqhtyaxwwikwyybxkdgrcslrkjpgjayaidwajeszppbqatnjojgjrplbkkhotjoqpgvwecjsoabmaupsrfenugybxmrjlochkmjgctznxltnrqxpbephfwymngpoorpjkkbplkwbkxzeqquorpipuvsutyaeqyzgpmqnaiiyssegzshttsrmvcrrkropuxjtqshvypdrwrvnztcstlj'.upper()
cc='NAJ'

eng=Enigma(settings=('R','Z','S'),rotors=(2,3,1),reflector='B',
ringstellung=('E','U','Y'),steckers=[('A','T'),('B','V'),
('C','F'),('E','N'),('G','Y'),('H','O'),('I','W'),('L','U'),('M','Z'),('Q','X')])

n = eng.decipher(cc)
eng=Enigma(settings=(n[0],n[1],n[2]),rotors=(2,3,1),reflector='B',
ringstellung=('E','U','Y'),steckers=[('A','T'),('B','V'),
('C','F'),('E','N'),('G','Y'),('H','O'),('I','W'),('L','U'),('M','Z'),('Q','X')])
flag=eng.decipher(c)
flag=flag.lower()
print(flag)
## 475748547berta36623936373230356665373537393566313034383537316366346366623730337dora

这里将erta和ora删去后,再hex转字符串就可以拿到flag了。

1
#GWHT{6b967205fe75795f1048571cf4cfb703}

最后,感谢万能的石神,有个小语种室友真好