狗儿

热爱的话就坚持吧~

0%

CUMTCTF岁末赛

前两天有别的比赛,没怎么打这场,第二天晚上才 开始重点做。第三天晚上九点疯狂上分,攒了三天的flag倾泻而出,得分趋势变成了竖线。队友们TQL~

image-20201226235702989

image-20201227000038023

reverse

签到

ida直接找到flag

zzzz3333333

38*38的矩阵,正则提取系数,然后matlab解。

提取系数:

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
code = '''int __cdecl sub_401500(char *a1)
{
int result; // eax

if ( 48 * a1[7]
+ 64 * a1[5]
+ 4 * a1[4]
+ 59 * a1[1]
+ 85 * *a1
+ 76 * a1[2]
+ 65 * a1[3]
+ 50 * a1[6]
+ 11 * a1[8]
+ 66 * a1[9] != 44858 )
return 0;
if ( 96 * a1[7]
+ 6 * a1[6]
+ 97 * a1[4]
+ 71 * a1[1]
+ 87 * *a1
+ 26 * a1[2]
+ 80 * a1[3]
+ 100 * a1[5]
+ 20 * a1[8]
+ 46 * a1[9] != 54177 )
return 0;
if ( 82 * a1[8]
+ 29 * a1[7]
+ 54 * a1[4]
+ 22 * a1[1]
+ 27 * *a1
+ 92 * a1[2]
+ 9 * a1[3]
+ 35 * a1[5]
+ 36 * a1[6]
+ 90 * a1[9] != 40412 )
return 0;
if ( 60 * a1[7]
+ 31 * a1[5]
+ 47 * *a1
+ 32 * a1[1]
+ 55 * a1[2]
+ 17 * a1[3]
+ 70 * a1[4]
+ 10 * a1[6]
+ 34 * a1[8]
+ 25 * a1[9] != 32362 )
return 0;
if ( 53 * a1[7]
+ 89 * a1[6]
+ 13 * a1[4]
+ 72 * a1[3]
+ 49 * a1[1]
+ 18 * *a1
+ 61 * a1[2]
+ 3 * a1[5]
+ 67 * a1[8]
+ 15 * a1[9] != 37176 )
return 0;
if ( 78 * a1[8]
+ 38 * a1[5]
+ 69 * a1[2]
+ 77 * *a1
+ 16 * a1[1]
+ 99 * a1[3]
+ 33 * a1[4]
+ 8 * a1[6]
+ 5 * a1[7]
+ 91 * a1[9] != 42742 )
return 0;
if ( 62 * a1[8]
+ 52 * a1[7]
+ 58 * a1[2]
+ 45 * a1[1]
+ 40 * *a1
+ 51 * a1[3]
+ 24 * a1[4]
+ 95 * a1[5]
+ 19 * a1[6]
+ 94 * a1[9] != 47553 )
return 0;
if ( 28 * a1[8]
+ 63 * a1[7]
+ 12 * a1[6]
+ 57 * a1[4]
+ 30 * a1[3]
+ 42 * a1[2]
+ a1[1]
+ 88 * *a1
+ 83 * a1[5]
+ 73 * a1[9] != 41059 )
return 0;
if ( 41 * a1[8]
+ 93 * a1[6]
+ 68 * a1[5]
+ 98 * a1[2]
+ 75 * a1[1]
+ 39 * *a1
+ 86 * a1[3]
+ 14 * a1[4]
+ 23 * a1[7]
+ 7 * a1[9] != 43919 )
return 0;
if ( 56 * a1[8] + 74 * a1[5] + 43 * a1[4] + 84 * a1[3] + 44 * a1[2] + 37 * *a1 + 81 * a1[1] + 2 * a1[6] + 21 * a1[9] != 35933 )
return 0;
if ( 36 * a1[16]
+ 98 * a1[14]
+ 79 * a1[10]
+ 97 * a1[11]
+ 33 * a1[12]
+ 60 * a1[15]
+ 24 * a1[17]
+ 78 * a1[18]
+ 72 * a1[19] != 47783 )
return 0;
if ( 74 * a1[17]
+ 39 * a1[16]
+ 51 * a1[15]
+ 8 * a1[14]
+ 77 * a1[13]
+ 69 * a1[12]
+ 16 * a1[11]
+ 73 * a1[10]
+ 64 * a1[18]
+ 28 * a1[19] != 44266 )
return 0;
if ( 47 * a1[18]
+ 52 * a1[17]
+ 53 * a1[16]
+ 99 * a1[15]
+ a1[14]
+ 38 * a1[13]
+ 67 * a1[12]
+ 45 * a1[11]
+ 61 * a1[10]
+ 66 * a1[19] != 44988 )
return 0;
if ( 5 * a1[17]
+ 4 * a1[13]
+ 89 * a1[12]
+ 31 * a1[10]
+ 11 * a1[11]
+ 93 * a1[14]
+ 3 * a1[15]
+ 84 * a1[16]
+ 65 * a1[18]
+ 100 * a1[19] != 46698 )
return 0;
if ( 82 * a1[16]
+ 62 * a1[13]
+ 58 * a1[12]
+ 42 * a1[11]
+ 86 * a1[10]
+ 85 * a1[14]
+ 27 * a1[15]
+ 43 * a1[17]
+ 15 * a1[18]
+ 26 * a1[19] != 45689 )
return 0;
if ( 22 * a1[16]
+ 34 * a1[13]
+ 2 * a1[12]
+ 23 * a1[11]
+ 46 * a1[10]
+ 29 * a1[14]
+ 48 * a1[15]
+ 35 * a1[17]
+ 19 * a1[18]
+ 70 * a1[19] != 27224 )
return 0;
if ( 96 * a1[18]
+ 81 * a1[17]
+ 92 * a1[15]
+ 54 * a1[14]
+ 94 * a1[11]
+ 57 * a1[10]
+ 55 * a1[12]
+ 80 * a1[13]
+ 71 * a1[16]
+ 25 * a1[19] != 58395 )
return 0;
if ( 13 * a1[17]
+ 75 * a1[13]
+ 21 * a1[11]
+ 59 * a1[10]
+ 56 * a1[12]
+ 50 * a1[14]
+ 41 * a1[15]
+ 44 * a1[16]
+ 40 * a1[18]
+ 49 * a1[19] != 40625 )
return 0;
if ( 12 * a1[16]
+ 91 * a1[14]
+ 88 * a1[13]
+ 87 * a1[12]
+ 68 * a1[10]
+ 7 * a1[11]
+ 83 * a1[15]
+ 20 * a1[17]
+ 32 * a1[18]
+ 37 * a1[19] != 45008 )
return 0;
if ( 10 * a1[17]
+ 18 * a1[16]
+ 9 * a1[15]
+ 6 * a1[14]
+ 76 * a1[10]
+ 14 * a1[11]
+ 17 * a1[12]
+ 90 * a1[13]
+ 63 * a1[18]
+ 30 * a1[19] != 32400 )
return 0;
if ( 83 * a1[26]
+ 45 * a1[25]
+ 4 * a1[24]
+ 48 * a1[22]
+ 38 * a1[20]
+ 22 * a1[21]
+ 7 * a1[23]
+ 62 * a1[27]
+ 25 * a1[28]
+ 85 * a1[29] != 37450 )
return 0;
if ( 14 * a1[28]
+ 86 * a1[26]
+ 93 * a1[25]
+ 42 * a1[24]
+ 94 * a1[21]
+ 70 * a1[20]
+ 58 * a1[22]
+ 40 * a1[23]
+ 76 * a1[27]
+ 11 * a1[29] != 48740 )
return 0;
if ( 72 * a1[28]
+ 46 * a1[26]
+ 92 * a1[25]
+ 98 * a1[24]
+ 55 * a1[23]
+ 80 * a1[20]
+ 32 * a1[21]
+ 12 * a1[22]
+ 84 * a1[27]
+ 27 * a1[29] != 53599 )
return 0;
if ( 53 * a1[27]
+ 49 * a1[23]
+ 99 * a1[22]
+ 41 * a1[20]
+ 20 * a1[21]
+ 87 * a1[25]
+ 81 * a1[26]
+ 71 * a1[28]
+ 73 * a1[29] != 52140 )
return 0;
if ( 68 * a1[28]
+ 61 * a1[21]
+ 28 * a1[20]
+ 91 * a1[22]
+ 31 * a1[23]
+ 67 * a1[24]
+ 15 * a1[25]
+ 44 * a1[26]
+ 6 * a1[27]
+ 64 * a1[29] != 44449 )
return 0;
if ( 9 * a1[27]
+ 60 * a1[25]
+ 96 * a1[23]
+ 17 * a1[20]
+ 10 * a1[21]
+ 29 * a1[22]
+ 5 * a1[24]
+ 100 * a1[26]
+ 21 * a1[28]
+ 69 * a1[29] != 35276 )
return 0;
if ( 59 * a1[26]
+ 66 * a1[25]
+ 23 * a1[22]
+ 8 * a1[20]
+ 24 * a1[21]
+ 16 * a1[23]
+ 56 * a1[24]
+ 90 * a1[27]
+ 36 * a1[28]
+ 39 * a1[29] != 35577 )
return 0;
if ( 35 * a1[25]
+ 65 * a1[23]
+ 63 * a1[22]
+ 75 * a1[20]
+ 88 * a1[21]
+ 33 * a1[24]
+ 82 * a1[26]
+ 18 * a1[27]
+ a1[28]
+ 37 * a1[29] != 42004 )
return 0;
if ( 54 * a1[28]
+ 57 * a1[27]
+ 43 * a1[24]
+ 74 * a1[21]
+ 19 * a1[20]
+ 51 * a1[22]
+ 13 * a1[23]
+ 79 * a1[25]
+ 3 * a1[26]
+ 26 * a1[29] != 35802 )
return 0;
if ( 34 * a1[28]
+ 50 * a1[27]
+ 78 * a1[26]
+ 52 * a1[25]
+ 77 * a1[24]
+ 95 * a1[23]
+ 30 * a1[22]
+ 89 * a1[20]
+ 2 * a1[21]
+ 97 * a1[29] != 54527 )
return 0;
if ( 46 * a1[36] + 73 * a1[34] + 15 * a1[30] + 16 * a1[31] + 41 * a1[32] + 94 * a1[33] + 28 * a1[35] + 45 * a1[37] != 34469 )
return 0;
if ( 82 * a1[36] + 10 * a1[32] + 48 * a1[31] + 65 * a1[30] + 6 * a1[33] + 30 * a1[34] + 27 * a1[35] + 32 * a1[37] != 31558 )
return 0;
if ( 62 * a1[36] + 39 * a1[35] + 36 * a1[33] + 97 * a1[31] + 52 * a1[30] + 70 * a1[32] + 13 * a1[34] + 66 * a1[37] != 41820 )
return 0;
if ( 44 * a1[34] + 42 * a1[33] + 78 * a1[32] + 83 * a1[31] + 96 * a1[30] + 4 * a1[35] + 9 * a1[36] + 51 * a1[37] != 38668 )
return 0;
if ( 79 * a1[36] + 37 * a1[33] + 92 * a1[30] + 18 * a1[31] + 86 * a1[32] + 7 * a1[34] + 95 * a1[37] != 45530 )
return 0;
if ( 71 * a1[36] + 43 * a1[35] + 57 * a1[34] + 49 * a1[33] + 88 * a1[32] + 61 * a1[30] + 24 * a1[31] + 91 * a1[37] != 51396 )
return 0;
if ( 34 * a1[36] + 75 * a1[35] + 35 * a1[32] + 23 * a1[30] + 3 * a1[31] + 53 * a1[33] + 14 * a1[34] + 47 * a1[37] != 28874 )
return 0;
if ( 22 * a1[36] + 84 * a1[35] + 26 * a1[34] + 90 * a1[33] + 99 * a1[30] + 98 * a1[31] + 25 * a1[32] + a1[37] != 38231 )
return 0;
}'''
code = code.replace('*a1', 'a1[0]')

import re

l = []
right = []
r = re.finditer(r'if.+?;', code, re.S)
for line in r:
tmp = [0] * 38
rr = re.finditer(r'(\d+?) \* a1\[(\d+?)\]', line.group())
for i in rr:
a, b = int(i.group(1)), int(i.group(2))
tmp[b] = a
_rr = re.search(r'\+ a1\[(\d+?)\]', line.group())
if _rr:
a, b = 1, int(_rr.group(1))
tmp[b] = a
l.append(tmp)

rrr = re.search(r'!\= (\d+)', line.group())
right.append(int(rrr.group(1)))


for i in l:
print(str(i)[1:-1] + ';')

print()

print(str(right).replace(',', ';'))

matlab部分截图:

image-20201227000606741

能用matlab解的最好不要用z3。z3基本靠爆破,matlab解线性方程是直接调用数学公式,不是一个时间复杂度哦。

奇怪的exe

pyinstaller打包的python程序,用pyinstxtractor.py解包,uncomlyle6提取python代码。

源码:

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
# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)]
# Embedded file name: 3.py
# Compiled at: 2020-12-24 10:52:17
# Size of source mod 2**32: 14 bytes
import base64
from binascii import *
c = [35, 101, 131, 114, 38]
enc = [122, 17, 205, 28, 104, 106, 80, 219, 39, 81, 98, 87, 214, 75, 112, 100, 63, 244, 32, 99, 110, 3, 187, 8, 114, 17, 9, 176, 22, 22, 87, 84, 206, 20, 104, 19, 49, 244, 39, 23]
print('please input your flag:')
key = input()
a = base64.b64encode(key.swapcase().encode('utf-8'))
print(a)
print(hexlify(a))
f = 1
s = []
for x in range(3):
for i in range(len(a)):
if (i + x) % 3 == 0:
s.append(a[i])
print(s)
for i in range(len(s)):
print(enc[i] ^ c[(i % 5)], s[i] )
if enc[i] != s[i] ^ c[(i % 5)]:
f = 0
break

if f == 1:
print('RIGHT')
else:
print('WRONG')
# okay decompiling 3.pyc

难度不大,我就不解释了,直接放解题脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
c = [ 35, 101, 131, 114, 38]
enc = [122, 17, 205, 28, 104, 106, 80, 219, 39, 81, 98, 87, 214, 75, 112, 100, 63, 244, 32, 99, 110, 3, 187, 8, 114, 17, 9, 176, 22, 22, 87, 84, 206, 20, 104, 19, 49, 244, 39, 23]
for i in range(len(enc)):
enc[i] ^= c[i%5]
print(enc)
new = [0] * len(enc)
o = 0

for x in range(3):
for i in range(len(enc)):
if (i + x) % 3 == 0:
new[i] = enc[o]
print(enc[o],end=' ')
o+=1
print()
print(new)
b = b''
import struct
for i in range(len(new)):
b += struct.pack('B', new[i])
print(b)
import base64
r = base64.b64decode(b)
print(r.swapcase())

swapcase()大小写互换有点意思哦。我和炜昊都倒在这里。

ez_code

python字节码。

分析大概是这样的,只是分析的草稿,注释可能有小疏漏哦。

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
 3           0 LOAD_GLOBAL              0 (print)
2 LOAD_CONST 1 ('please input your flag:')
4 CALL_FUNCTION 1
6 POP_TOP

4 8 LOAD_GLOBAL 1 (input)
10 CALL_FUNCTION 0
12 STORE_FAST 0 (flag)

5 14 LOAD_GLOBAL 2 (len)
16 LOAD_FAST 0 (flag)
18 CALL_FUNCTION 1
20 LOAD_CONST 2 (36)
22 COMPARE_OP 3 (!=) # len = 36
24 POP_JUMP_IF_FALSE 30

6 26 LOAD_CONST 3 (0)
28 RETURN_VALUE

7 >> 30 BUILD_LIST 0
32 STORE_FAST 1 (a)

8 34 LOAD_CONST 3 (0)
36 STORE_FAST 2 (t) # t = 0

12 38 LOAD_FAST 0 (flag)
40 GET_ITER
>> 42 FOR_ITER 58 (to 102)
44 STORE_FAST 3 (i)

13 46 LOAD_FAST 2 (t)
48 LOAD_CONST 4 (1)
50 BINARY_AND
52 LOAD_CONST 4 (1)
54 COMPARE_OP 2 (==) # t & 1 == 1 奇数则跳
56 POP_JUMP_IF_FALSE 78

14 58 LOAD_FAST 1 (a)
60 LOAD_METHOD 3 (append)
62 LOAD_GLOBAL 4 (ord)
64 LOAD_FAST 3 (i)
66 CALL_FUNCTION 1
68 LOAD_CONST 5 (128) # 偶数则a.append(ord(i)+128)
70 BINARY_ADD
72 CALL_METHOD 1
74 POP_TOP
76 JUMP_FORWARD 14 (to 92)

16 >> 78 LOAD_FAST 1 (a)
80 LOAD_METHOD 3 (append)
82 LOAD_GLOBAL 4 (ord)
84 LOAD_FAST 3 (i)
86 CALL_FUNCTION 1
88 CALL_METHOD 1 # 奇数则a.append(ord(i))
90 POP_TOP

17 >> 92 LOAD_FAST 2 (t)
94 LOAD_CONST 4 (1)
96 INPLACE_ADD
98 STORE_FAST 2 (t) # t+1
100 JUMP_ABSOLUTE 42 # 跳回循环开始

21 >> 102 LOAD_FAST 1 (a)
104 LOAD_CONST 3 (0)
106 BINARY_SUBSCR
108 LOAD_CONST 6 (5)
110 BINARY_RSHIFT
112 STORE_FAST 4 (b) # a[0] >> 5

22 114 LOAD_GLOBAL 5 (range)
116 LOAD_GLOBAL 2 (len)
118 LOAD_FAST 1 (a)
120 CALL_FUNCTION 1
122 CALL_FUNCTION 1
124 GET_ITER
>> 126 FOR_ITER 82 (to 210)
128 STORE_FAST 3 (i)

23 130 LOAD_FAST 3 (i)
132 LOAD_GLOBAL 2 (len)
134 LOAD_FAST 1 (a)
136 CALL_FUNCTION 1
138 LOAD_CONST 4 (1)
140 BINARY_SUBTRACT # len(a) - 1
142 COMPARE_OP 2 (==)
144 POP_JUMP_IF_FALSE 172 # 循环体在172,而146是循环后运行的

24 146 LOAD_FAST 1 (a)
148 LOAD_FAST 3 (i)
150 BINARY_SUBSCR
152 LOAD_CONST 7 (8)
154 BINARY_MULTIPLY # a[i] * 8
156 LOAD_CONST 8 (255)
158 BINARY_AND # (a[i] * 8) & 0xff
160 LOAD_FAST 4 (b)
162 BINARY_OR
164 LOAD_FAST 1 (a)
166 LOAD_FAST 3 (i)
168 STORE_SUBSCR # a[i] = (a[0] >> 5) | ((a[i] << 3) & 0xff)
170 JUMP_ABSOLUTE 126

26 >> 172 LOAD_FAST 1 (a)
174 LOAD_FAST 3 (i)
176 BINARY_SUBSCR
178 LOAD_CONST 7 (8)
180 BINARY_MULTIPLY
182 LOAD_CONST 8 (255)
184 BINARY_AND # (a[i] * 8) & 0xff
186 LOAD_FAST 1 (a)
188 LOAD_FAST 3 (i)
190 LOAD_CONST 4 (1)
192 BINARY_ADD
194 BINARY_SUBSCR
196 LOAD_CONST 6 (5)
198 BINARY_RSHIFT # a[i+1] >> 5
200 BINARY_OR
202 LOAD_FAST 1 (a)
204 LOAD_FAST 3 (i)
206 STORE_SUBSCR # a[i] = (a[i+1] >> 5) | ((a[i] << 3) & 0xff)
208 JUMP_ABSOLUTE 126

28 >> 210 BUILD_LIST 0
212 STORE_FAST 5 (num)

32 214 LOAD_GLOBAL 5 (range)
216 LOAD_CONST 9 (2)
218 LOAD_CONST 10 (129)
220 CALL_FUNCTION 2
222 GET_ITER
>> 224 FOR_ITER 60 (to 286)
226 STORE_FAST 3 (i) # for i in range(2, 129)

33 228 LOAD_CONST 11 (False)
230 STORE_FAST 2 (t)

34 232 LOAD_GLOBAL 5 (range)
234 LOAD_CONST 9 (2)
236 LOAD_FAST 3 (i)
238 CALL_FUNCTION 2
240 GET_ITER
>> 242 FOR_ITER 26 (to 270)
244 STORE_FAST 6 (j)

35 246 LOAD_FAST 3 (i)
248 LOAD_FAST 6 (j)
250 BINARY_MODULO
252 LOAD_CONST 3 (0)
254 COMPARE_OP 2 (==) # i % j == 0
256 POP_JUMP_IF_FALSE 242

36 258 LOAD_CONST 12 (True)
260 STORE_FAST 2 (t) # t = True

37 262 POP_TOP
264 EXTENDED_ARG 1
266 JUMP_ABSOLUTE 270
268 JUMP_ABSOLUTE 242

38 >> 270 LOAD_FAST 2 (t)
272 POP_JUMP_IF_TRUE 224 # not t

39 274 LOAD_FAST 5 (num)
276 LOAD_METHOD 3 (append)
278 LOAD_FAST 3 (i) # num.append(i)
280 CALL_METHOD 1
282 POP_TOP
284 JUMP_ABSOLUTE 224

40 >> 286 LOAD_CONST 3 (0)
288 BUILD_LIST 1
290 LOAD_GLOBAL 2 (len)
292 LOAD_FAST 1 (a)
294 CALL_FUNCTION 1
296 BINARY_MULTIPLY
298 STORE_FAST 7 (c)

41 300 LOAD_GLOBAL 5 (range)
302 LOAD_GLOBAL 2 (len)
304 LOAD_FAST 1 (a)
306 CALL_FUNCTION 1
308 CALL_FUNCTION 1
310 GET_ITER
>> 312 FOR_ITER 78 (to 392)
314 STORE_FAST 3 (i) # for i in range(len(a))

42 316 LOAD_FAST 1 (a)
318 LOAD_FAST 3 (i)
320 BINARY_SUBSCR
322 LOAD_CONST 13 (4)
324 BINARY_RSHIFT # a[i] >> 4
326 LOAD_FAST 5 (num)
328 LOAD_FAST 3 (i)
330 LOAD_CONST 14 (31)
332 BINARY_MODULO
334 BINARY_SUBSCR # num[i % 31]
336 LOAD_CONST 15 (15)
338 BINARY_AND # num[i % 31] & 0xf
340 BINARY_XOR
342 STORE_FAST 8 (x1) # x1 = (a[i] >> 4) ^ (num[i % 31] & 0xf)

43 344 LOAD_FAST 1 (a)
346 LOAD_FAST 3 (i)
348 BINARY_SUBSCR
350 LOAD_CONST 15 (15)
352 BINARY_AND # a[i] & 0xf
354 LOAD_FAST 5 (num)
356 LOAD_FAST 3 (i)
358 LOAD_CONST 14 (31)
360 BINARY_MODULO
362 BINARY_SUBSCR # num[i % 31]
364 LOAD_CONST 13 (4)
366 BINARY_RSHIFT # num[i % 31] >> 4
368 BINARY_XOR
370 STORE_FAST 9 (x2) # x2 = (a[i] & 0xf) ^ (num[i % 31] >> 4)

44 372 LOAD_FAST 9 (x2)
374 LOAD_CONST 16 (16)
376 BINARY_MULTIPLY # 16 * x2
378 LOAD_FAST 8 (x1)
380 BINARY_ADD # 16 * x2 + x1
382 LOAD_FAST 7 (c)
384 LOAD_FAST 3 (i)
386 STORE_SUBSCR # c[i] = 16 * x2 + x1
388 EXTENDED_ARG 1
390 JUMP_ABSOLUTE 312

47 >> 392 LOAD_CONST 17 (227) # 密文
394 LOAD_CONST 18 (169)
396 LOAD_CONST 17 (227)
398 LOAD_CONST 19 (45)
400 LOAD_CONST 20 (234)
402 LOAD_CONST 21 (39)
404 LOAD_CONST 22 (98)
406 LOAD_CONST 23 (190)
408 LOAD_CONST 24 (197)
410 LOAD_CONST 25 (7)
412 LOAD_CONST 26 (229)
414 LOAD_CONST 27 (137)
416 LOAD_CONST 24 (197)
418 LOAD_CONST 28 (132)
420 LOAD_CONST 29 (119)
422 LOAD_CONST 30 (142)
424 LOAD_CONST 31 (97)
426 LOAD_CONST 32 (167)
428 LOAD_CONST 33 (59)
430 LOAD_CONST 34 (96)
432 LOAD_CONST 35 (166)
434 LOAD_CONST 36 (94)
436 LOAD_CONST 37 (136)
438 LOAD_CONST 17 (227)
440 LOAD_CONST 38 (131)
442 LOAD_CONST 39 (202)
444 LOAD_CONST 37 (136)
446 LOAD_CONST 40 (250)
448 LOAD_CONST 41 (21)
450 LOAD_CONST 42 (99)
452 LOAD_CONST 43 (20)
454 LOAD_CONST 44 (173)
456 LOAD_CONST 45 (121)
458 LOAD_CONST 46 (41)
460 LOAD_CONST 47 (125)
462 LOAD_CONST 48 (165)
464 BUILD_LIST 36
466 STORE_FAST 10 (d)

48 468 LOAD_CONST 4 (1)
470 STORE_FAST 11 (e)

49 472 LOAD_GLOBAL 5 (range)
474 LOAD_GLOBAL 2 (len)
476 LOAD_FAST 10 (d)
478 CALL_FUNCTION 1
480 CALL_FUNCTION 1
482 GET_ITER
>> 484 FOR_ITER 34 (to 520)
486 STORE_FAST 3 (i)

50 488 LOAD_FAST 10 (d)
490 LOAD_FAST 3 (i)
492 BINARY_SUBSCR
494 LOAD_FAST 7 (c)
496 LOAD_FAST 3 (i)
498 BINARY_SUBSCR
500 COMPARE_OP 3 (!=)
502 EXTENDED_ARG 1
504 POP_JUMP_IF_FALSE 484

51 506 LOAD_CONST 3 (0)
508 STORE_FAST 11 (e)

52 510 POP_TOP
512 EXTENDED_ARG 2
514 JUMP_ABSOLUTE 520
516 EXTENDED_ARG 1
518 JUMP_ABSOLUTE 484

53 >> 520 LOAD_FAST 11 (e)
522 LOAD_CONST 4 (1)
524 COMPARE_OP 2 (==)
526 EXTENDED_ARG 2
528 POP_JUMP_IF_FALSE 540

54 530 LOAD_GLOBAL 0 (print)
532 LOAD_CONST 49 ('YOU ARE RIGHT')
534 CALL_FUNCTION 1
536 POP_TOP
538 JUMP_FORWARD 8 (to 548)

56 >> 540 LOAD_GLOBAL 0 (print)
542 LOAD_CONST 50 ('WRONG')
544 CALL_FUNCTION 1
546 POP_TOP
>> 548 LOAD_CONST 0 (None)
550 RETURN_VALUE

手写其逻辑:

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
flag = input()

if len(flag) != 36:
exit()

t = 0
a = []
for i in flag:
if t & 1 == 1:
a.append(ord(i)+128)
else:
a.append(ord(i))
t += 1

a[len(a)-1] = ((a[len(a)-1] << 3) & 0xff) | (a[0] >> 5)
for i in range(len(a)-1):
a[i] = ((a[i] << 3) & 0xff) | (a[i+1] >> 5)

num = []
for i in range(2, 129):
t = False
for j in range(2, i):
if i % j == 0:
t = True
if not t:
num.append(i)

c = [0] * len(flag)
for i in range(len(a)):
x1 = (a[i] >> 4) ^ (num[i % 31] & 0xf)
x2 = (a[i] & 0xf) ^ (num[i % 31] >> 4)
c[i] = (x2 << 4) + x1

d=[227, 169, 227, 45, 234, 39, 98, 190, 197, 7, 229, 137, 197, 132, 119, 142, 97, 167, 59, 96, 166, 94, 136, 227, 131, 202, 136, 250, 21, 99, 20, 173, 121, 41, 125, 165]
for i in range(len(d)):
if d[i] != c[i]:
print('WRONG')
exit()
print('YOU ARE RIGHT')

逆向主要是两段,第一段就是简单的左移3右移5。

第二段简单分析下见下图,就是a[i]交换高低4bit后与num[i%31]异或。

0cf3d7ca7bcb0a467b731a657c63f6246b60af1d

逆向脚本:

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
num=[]
for i in range(2,129):
t=False
for j in range(2,i):
if i%j==0:
t=True
if not t:
num.append(i)
print(len(num))

c=d=[227, 169, 227, 45, 234, 39, 98, 190, 197, 7, 229, 137, 197, 132, 119, 142, 97, 167, 59, 96, 166, 94, 136, 227, 131, 202, 136, 250, 21, 99, 20, 173, 121, 41, 125, 165]
print(c)
a = []
for i in range(len(c)):
tmp = d[i] ^ num[i % 31]
tmp = (tmp >> 4) + ((tmp & 0xf) << 4)
a.append(tmp)

s = ''
for i in range(len(a)):
s += bin(a[i])[2:].zfill(8)
print(s)
s = s[-3:] + s[:-3]
print(s)
flag = []
for i in range(len(a)):
tmp = int(s[i*8: i*8+8], 2)
if i % 2 == 0:
flag.append(tmp)
else:
flag.append(tmp-128)
print(flag)
print(''.join(list(map(chr, flag))))

time

这题很有意思哦。

输入flag前会验证时间,必须在特定的年月日时分秒才能继续。但是还不能简单地patch掉这些验证。因为会把这些参数计算出一个int后传入验证flag的函数,并参与flag验证的逻辑。所以需要计算出这个int,然后patch掉时间验证之后,进入flag验证函数前,手动修改传入的这个参数 55*7*903274960*9*2018*32 = 0xec48d400

image-20201227010317187

这题应该是用了一些C语言没有的函数,伪代码有点奇怪,但没有特别的c++的特征(其实是有点的。不知道怎么编译的。识别不出来这些奇怪的库函数,只能动调慢慢推测。

输入flag后,创建一个flag备份,记作buffer,并通过下面逻辑,将传入的与时间有关的int进行转换,生成0~4的字节,并拼接到buffer的首部。

image-20201227010525135

从int中分出4个byte, &0x7f后如果满足上述逻辑,就添加到buffer的头部。可能添加0~3个字节,这取决于时间参数。对于通过验证的唯一参数0xec48d400,会添加3个字节。

创建一个table,长62,值为0-9a-zA-Z

image-20201227011123392

从buffer(3个时间参数导出的字节+flag)中找到每个字符在table0-9a-zA-Z中首次出现的索引:

image-20201227011411306

然后主要的逻辑在sub_401541。

image-20201227011500106

这次是从flag中找到每个字符在table0-9a-zA-Z中首次出现的索引,然后与上一步的table_from_find_first_index_by_buffer[i]模62相加。

什么意思呢?

一个数组是3个时间参数相关字节+flag,一个”数组“是flag,这两个数组对于元素模62相加,然后作为索引取table0-9a-zA-Z的字符。

所以其实就是个错位相加。

动调到这个函数,拿到这3个时间参数相关字节0x0d, 0x0c, 0x38。然后错位计算。

解密脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import string
from z3 import *

time = 55*7*903274960*9*2018*32
print(hex(time&0xffffffff))

cipher = 'P6GvwFypZN1BbFn5tVgoWeK81LkeQ6uvuiovDgO'
print(len(cipher))
table = string.digits + string.ascii_lowercase + string.ascii_uppercase
print(table)

a = (table.find(cipher[0]) - 0x0d + 62) % 62
b = (table.find(cipher[1]) - 0x0c + 62) % 62
c = (table.find(cipher[2]) - 0x38 + 62) % 62
index = [a, b, c]
print(index)
for i in range(3, len(cipher)):
tmp = (table.find(cipher[i]) - index[i-3] + 62) % 62
index.append(tmp)
for i in index[:-3]:
print(table[i],end='')
print()

baby_encrypt

把flag主体按-分割拆成3部分,分别进入函数验证

image-20201227012124185

三个main都是md5,逐渐魔改递进。

main是原版md5,然后把md5走一些古典算法,然后比较密文。

从密文可以逆回md5。然后可以查彩虹表。

main1算法:

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
int __cdecl main1(char *part1)
{
int v1; // eax
int v2; // eax
unsigned int k; // eax
int v5[16]; // [esp+10h] [ebp-D8h]
char Src[8]; // [esp+50h] [ebp-98h] BYREF
int md5_ctx[2]; // [esp+58h] [ebp-90h] BYREF
int ctx_state; // [esp+60h] [ebp-88h] BYREF
char md5_digest[16]; // [esp+B0h] [ebp-38h] BYREF
const char *v10; // [esp+C0h] [ebp-28h]
int tmp; // [esp+C4h] [ebp-24h]
int low; // [esp+C8h] [ebp-20h]
int high; // [esp+CCh] [ebp-1Ch]
int v14; // [esp+D0h] [ebp-18h]
unsigned int v15; // [esp+D4h] [ebp-14h]
int j; // [esp+D8h] [ebp-10h]
int i; // [esp+DCh] [ebp-Ch]

md5_init(md5_ctx);
v1 = strlen(part1);
MD5Update((int)md5_ctx, part1, v1);
v14 = 0; // 以下是MD5Final
v15 = ((unsigned int)md5_ctx[0] >> 3) & 0x3F;
if ( v15 > 0x37 )
v2 = 120 - v15;
else
v2 = 56 - v15;
v14 = v2;
MD5Encode((int)Src, (int)md5_ctx, 8u);
MD5Update((int)md5_ctx, &padding, v14);
MD5Update((int)md5_ctx, Src, 8);
MD5Encode((int)md5_digest, (int)&ctx_state, 0x10u);// 以上是MD5Final
for ( i = 0; i <= 15; ++i )
{
high = (unsigned __int8)md5_digest[i] >> 4;
low = md5_digest[i] & 0xF;
md5_digest[i] = 16 * low + (high ^ low);
*((_BYTE *)&v5[8] + 2 * i) = (unsigned __int8)md5_digest[i] >> 4;// = low, 0~15
*((_BYTE *)&v5[8] + 2 * i + 1) = md5_digest[i] & 0xF;// = high ^ low
}
for ( i = 0; i <= 31; i += 8 )
{
for ( j = 0; j <= 3; ++j )
{
tmp = *((char *)&v5[8] + i + j);
*((_BYTE *)&v5[8] + j + i) = *((_BYTE *)&v5[8] + i + 7 - j);
*((_BYTE *)&v5[8] + i + 7 - j) = tmp;
} // 07,16,25,34互换
}
for ( k = 0; k < 8; ++k ) // memset(v5, 0, 8)
v5[k] = 0;
for ( i = 0; i <= 31; ++i )
{
if ( *((char *)&v5[8] + i) > 9 || *((char *)&v5[8] + i) < 0 )// num2char
{
if ( *((char *)&v5[8] + i) > 9 && *((char *)&v5[8] + i) <= 15 )
*((_BYTE *)v5 + i) = *((_BYTE *)&v5[8] + i) + 87;
}
else
{
*((_BYTE *)v5 + i) = *((_BYTE *)&v5[8] + i) + 48;
}
}
v10 = "e0c1942932d5845b5128552378fb20bf";
for ( i = 0; i <= 31; ++i )
{
if ( *((_BYTE *)v5 + i) != v10[i] )
return 0;
}
return 1;
}

逆向脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
a = 'e0c1942932d5845b5128552378fb20bf'
a = [ord(i) for i in a]
#print(a)
for i in range(0, 32, 8):
for j in range(4):
a[i+j], a[i+7-j] = a[i+7-j], a[i+j]
#print(a)
a = [int(str(chr(i)), 16) for i in a]
#print(a)
for i in range(16):
t1 = a[i*2]
t2 = a[i*2+1]
t1, t2 = t1 ^ t2, t1
a[i*2], a[i*2+1] = t1, t2
hash1 = ''
for i in a:
hash1 += str(hex(i)[2:])
print(hash1)

# md5 = b9d4d1e0ebc485121305a8414f204bf8
# plain = R2e

main2算法(只比main1多了一步)

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
int __cdecl main2(char *Str)
{
int v1; // eax
int v2; // eax
unsigned int k; // eax
unsigned int m; // eax
int v6[16]; // [esp+14h] [ebp-E4h]
char Src[8]; // [esp+54h] [ebp-A4h] BYREF
int md5_ctx[2]; // [esp+5Ch] [ebp-9Ch] BYREF
int v9; // [esp+64h] [ebp-94h] BYREF
char digest[16]; // [esp+B4h] [ebp-44h] BYREF
const char *v11; // [esp+C4h] [ebp-34h]
int v12; // [esp+C8h] [ebp-30h]
int v13; // [esp+CCh] [ebp-2Ch]
int v14; // [esp+D0h] [ebp-28h]
unsigned int v15; // [esp+D4h] [ebp-24h]
int *ctx_state; // [esp+D8h] [ebp-20h]
int len; // [esp+DCh] [ebp-1Ch]
unsigned int v18; // [esp+E0h] [ebp-18h]
int l; // [esp+E4h] [ebp-14h]
int j; // [esp+E8h] [ebp-10h]
int i; // [esp+ECh] [ebp-Ch]

md5_init(md5_ctx);
v1 = strlen(Str);
MD5Update((int)md5_ctx, Str, v1);
len = 0;
v18 = ((unsigned int)md5_ctx[0] >> 3) & 0x3F;
if ( v18 > 0x37 )
v2 = 0x78 - v18;
else
v2 = 0x38 - v18;
len = v2;
MD5Encode((int)Src, (int)md5_ctx, 8u);
MD5Update((int)md5_ctx, &padding, len);
MD5Update((int)md5_ctx, Src, 8);
ctx_state = &v9; // 比main1多了这块
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 2; ++j )
{
v15 = (unsigned int)ctx_state[i] >> 28;
ctx_state[i] = 16 * ctx_state[i] + v15; // << 4 | >> 28
} // <<12 | >> 20
ctx_state[i] ^= 0xA3DFA1DB;
}
MD5Encode((int)digest, (int)ctx_state, 0x10u);
for ( k = 0; k < 8; ++k )
v6[k + 8] = 0;
for ( i = 0; i <= 15; ++i )
{
v14 = (unsigned __int8)digest[i] >> 4;
v13 = digest[i] & 0xF;
*((_BYTE *)&v6[8] + 2 * i) = v13;
*((_BYTE *)&v6[8] + 2 * i + 1) = v14 ^ v13;
}
for ( i = 0; i <= 31; i += 8 )
{
for ( l = 0; l <= 3; ++l )
{
v12 = *((char *)&v6[8] + i + l);
*((_BYTE *)&v6[8] + l + i) = *((_BYTE *)&v6[8] + i + 7 - l);
*((_BYTE *)&v6[8] + i + 7 - l) = v12;
}
}
for ( m = 0; m < 8; ++m )
v6[m] = 0;
for ( i = 0; i <= 31; ++i )
{
if ( *((char *)&v6[8] + i) > 9 || *((char *)&v6[8] + i) < 0 )
{
if ( *((char *)&v6[8] + i) > 9 && *((char *)&v6[8] + i) <= 15 )
*((_BYTE *)v6 + i) = *((_BYTE *)&v6[8] + i) + 87;
}
else
{
*((_BYTE *)v6 + i) = *((_BYTE *)&v6[8] + i) + 48;
}
}
v11 = "d039a1b9c6daa1b450b044aeb2696a44";
for ( i = 0; i <= 31; ++i )
{
if ( *((_BYTE *)v6 + i) != v11[i] )
return 0;
}
return 1;
}

逆向脚本(注意MD5Encode的大小端转换哦)

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
b = 'd039a1b9c6daa1b450b044aeb2696a44'
b = [ord(i) for i in b]
print(b)
for i in range(0, 32, 8):
for j in range(4):
b[i+j], b[i+7-j] = b[i+7-j], b[i+j]
print(b)
b = [int(str(chr(i)), 16) for i in b]
print(b)
for i in range(16):
t1 = b[i*2]
t2 = b[i*2+1]
t1, t2 = t1 ^ t2, t1
b[i*2], b[i*2+1] = t1, t2
b_data = []
for i in range(16):
tmp = (b[i*2]<<4) + b[i*2+1]
b_data.append(tmp)
print(b_data)
for i in range(4):
tmp = b_data[i*4] + (b_data[i*4+1]<<8) + (b_data[i*4+2]<<16) + (b_data[i*4+3]<<24)
tmp ^= 0xA3DFA1DB
#print(bin(tmp)[2:].zfill(32))
tmp = ((tmp<<20)&0xffffffff) + (tmp>>12)
#print(bin(tmp)[2:].zfill(32))
#print()
b_data[i*4] = tmp&0xff
b_data[i*4+1] = (tmp>>8)&0xff
b_data[i*4+2] = (tmp>>16)&0xff
b_data[i*4+3] = (tmp>>24)&0xff
print(b_data)
b_md5 = ''
for i in b_data:
b_md5 += hex(i)[2:].zfill(2)
print(b_md5)

# md5 = 6137270f515af002fa365f596612f3bd
# plain = 1S

main3算法:

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
int __cdecl main3(char *part3)
{
int v1; // eax
int v2; // eax
unsigned int l; // eax
int result; // eax
int Buffer; // [esp+18h] [ebp-120h] BYREF
int f_part3[20]; // [esp+20h] [ebp-118h] BYREF
char Src[8]; // [esp+70h] [ebp-C8h] BYREF
int ctx[2]; // [esp+78h] [ebp-C0h] BYREF
_BYTE v9[80]; // [esp+80h] [ebp-B8h] BYREF
char digest[16]; // [esp+D0h] [ebp-68h] BYREF
char _part3[16]; // [esp+E0h] [ebp-58h] BYREF
const char *cipher; // [esp+F0h] [ebp-48h]
int v13; // [esp+F4h] [ebp-44h]
size_t v14; // [esp+F8h] [ebp-40h]
FILE *fFLAG; // [esp+FCh] [ebp-3Ch]
FILE *fdata; // [esp+100h] [ebp-38h]
int v17; // [esp+104h] [ebp-34h]
int v18; // [esp+108h] [ebp-30h]
int v19; // [esp+10Ch] [ebp-2Ch]
int v20; // [esp+110h] [ebp-28h]
_BYTE *v21; // [esp+114h] [ebp-24h]
int padlen; // [esp+118h] [ebp-20h]
unsigned int v23; // [esp+11Ch] [ebp-1Ch]
int k; // [esp+120h] [ebp-18h]
char part3_b3; // [esp+126h] [ebp-12h]
char part3_b1; // [esp+127h] [ebp-11h]
int j; // [esp+128h] [ebp-10h]
int i; // [esp+12Ch] [ebp-Ch]

strcpy(_part3, part3);
md5_init(ctx);
v1 = strlen(part3);
MD5Update((int)ctx, part3, v1);
padlen = 0;
v23 = ((unsigned int)ctx[0] >> 3) & 0x3F;
if ( v23 > 0x37 )
v2 = 120 - v23;
else
v2 = 56 - v23;
padlen = v2;
MD5Encode((int)Src, (int)ctx, 8u);
MD5Update((int)ctx, &padding, padlen);
MD5Update((int)ctx, Src, 8);
v21 = v9;
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 2; ++j )
{
v20 = *(_DWORD *)&v21[4 * i] >> 28;
*(_DWORD *)&v21[4 * i] = 16 * *(_DWORD *)&v21[4 * i] + v20;
}
*(_DWORD *)&v21[4 * i] ^= 0xA3DFA1DB;
}
MD5Encode((int)digest, (int)v9, 0x10u);
for ( i = 0; i <= 15; ++i )
{
v19 = (unsigned __int8)digest[i] >> 4;
v18 = digest[i] & 0xF;
*((_BYTE *)&f_part3[12] + 2 * i) = v18;
*((_BYTE *)&f_part3[12] + 2 * i + 1) = v19 ^ v18;
}
part3_b1 = _part3[1] & 0x7F; // 差异
part3_b3 = _part3[3] & 0x7F;
for ( i = 0; i <= 31; ++i )
{
if ( i != 1 )
part3_b1 ^= *((_BYTE *)&f_part3[12] + i);
if ( i )
part3_b3 ^= *((_BYTE *)&f_part3[12] + i);
} // 上 差异
for ( i = 0; i <= 31; i += 8 )
{
for ( k = 0; k <= 3; ++k )
{
v17 = *((char *)&f_part3[12] + i + k);
*((_BYTE *)&f_part3[12] + k + i) = *((_BYTE *)&f_part3[12] + i + 7 - k);
*((_BYTE *)&f_part3[12] + i + 7 - k) = v17;
}
}
for ( l = 0; l < 8; ++l )
f_part3[l + 4] = 0;
for ( i = 0; i <= 31; ++i )
{
if ( *((char *)&f_part3[12] + i) > 9 || *((char *)&f_part3[12] + i) < 0 )
{
if ( *((char *)&f_part3[12] + i) > 9 && *((char *)&f_part3[12] + i) <= 15 )
*((_BYTE *)&f_part3[4] + i) = *((_BYTE *)&f_part3[12] + i) + 87;
}
else
{
*((_BYTE *)&f_part3[4] + i) = *((_BYTE *)&f_part3[12] + i) + 48;
}
}
fdata = fopen("data", "rb");
fFLAG = fopen("FLAG", "w+b");
if ( fdata && fFLAG )
{
f_part3[2] = 0;
f_part3[3] = 0;
v14 = 0;
v13 = 0;
i = 0;
while ( 1 )
{
v14 = fread(f_part3, 1u, 1u, fdata);
if ( !v14 )
break;
if ( (i & 1) == 0 ) // 偶
Buffer = f_part3[0] ^ part3_b1;
if ( i % 2 == 1 ) // 奇
Buffer = f_part3[0] ^ part3_b3;
++i;
fwrite(&Buffer, 1u, 1u, fFLAG);
}
fclose(fdata);
fclose(fFLAG);
cipher = "46f627c53e41fc2a2182ba286295bc35";
for ( i = 0; i <= 31; ++i )
{
if ( *((_BYTE *)&f_part3[4] + i) != cipher[i] )
return 0;
}
result = 1;
}
else
{
puts("error!");
result = 0;
}
return result;
}

main3是在main2基础上改的。

hint中有提示jpg。答案就是,第三段的md5查表查不出来,长度是13,爆破也不太容易。但是第三段flag就在jpg里面写着(data是jpg的密文)

那data的密钥是啥呢?来看下逻辑。

image-20201227013420150

首先flag的第三部分&0x7f后,分奇偶分别与md5计算后但是验证前的中间值循环异或。

好的,中间值我们可以逆向得到,但是这个输入值拿不到啊。这里不是突破点。

那再来看下,从data读入密文,异或后,buffer是解密的明文。

image-20201227013726366

buffer是输出,f_part3[0]是从data文件中读入的一个字节,part3_b1是密钥。

如果是jpg,那么文件头是固定(ffd8ffe0)的,所以buffer已知一定的字节。然后是f_part3[0],这是异或和的密文,就在data里,也已知。所以我们可求密钥。

解密脚本:

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
b = '46f627c53e41fc2a2182ba286295bc35'
b = [ord(i) for i in b]
print(b)
for i in range(0, 32, 8):
for j in range(4):
b[i+j], b[i+7-j] = b[i+7-j], b[i+j]
print(b)
b = [int(str(chr(i)), 16) for i in b]
print(b)


part3_b1 = 0xbd ^ 0xff
part3_b3 = 0x8b ^ 0xd8
print(part3_b1, part3_b3)
with open('data', 'rb')as f:
b = f.read()
b = list(b)
for i in range(len(b)):
if i % 2 == 0:
b[i] ^= part3_b1
else:
b[i] ^= part3_b3
bb = b''
import struct
for i in b:
bb += struct.pack('B', i)
with open(r'data.jpg', 'wb')as f:
f.write(bb)

data

crypto

RSA签到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
n = 807862607863494903203347547751222668477246136996519972166847
c = 6525071913169990474785757170304035615411828876052879070297
e = 65537

from Crypto.Util.number import *
from gmpy2 import *

P31 = 1034526559407993507734818408829
P30 = 780900790334269659443297956843
phi = (P31-1) * (P30-1)
d = inverse(e, phi)
m = pow(c, d, n)
print(m)
print(long_to_bytes(m))

简单的密码学

task.py

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import libnum
import random
e=libnum.s2n(flag)
n = 2 ** 514
m = random.randint(2, n-1) | 1
c = pow(m, e, n)
print('m = ' + str(m))
print('c = ' + str(c))
# m = 45930439493588458217814199095166325056793804285450102007731089001050571514856332627851425138364361016243889773238664380678029627984235001868004334568770697
# c = 5057805883715955343508948629802682033540608675113624374337084633322875196538392521768197949724904990019045804655058020268973563802830621371118940310488041

flag是e,所以是离散对数的求解。

贴个资料:

img

直接上sympy的轮子:

1
2
3
4
5
6
7
from sympy.ntheory import *
from Crypto.Util.number import *
n = 2 ** 514
m = 45930439493588458217814199095166325056793804285450102007731089001050571514856332627851425138364361016243889773238664380678029627984235001868004334568770697
c = 5057805883715955343508948629802682033540608675113624374337084633322875196538392521768197949724904990019045804655058020268973563802830621371118940310488041
flag = discrete_log(n,c,m)
print(long_to_bytes(flag))

名字不重要

给出一个pyc,一个流量包。

pyc改成python3.8.5的魔数,然后转成python代码。

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
# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)]
# Embedded file name: res.py
# Compiled at: 2020-12-26 02:08:16
# Size of source mod 2**32: 5 bytes
import hmac, hashlib, random, struct
KIDING_SIZE = 32
SIG_SIZE = 16
TOTAL_SIZE = set((c for c in range(256)))
KEY = b'af5f76f605a700ae8c0895c3e6175909'

def func1(v):
return bytes([v])


def sign_sign_sign(val, key):
return hmac.new(key,
val, digestmod=(hashlib.sha256)).digest()[:SIG_SIZE]


def chaff_chaff_chaff_b(val, key):
messgs = {}
messgs[val[0]] = sign_sign_sign(val, key)
while len(messgs) < KIDING_SIZE:
arg1 = list(TOTAL_SIZE - set(messgs.keys()))
c = random.choice(arg1)
if c == val:
raise ValueError('C~h~o~s~e d~u~p~l~i~c~a~t~e~!')
bad_sig = bytes(random.choices((list(TOTAL_SIZE)), k=SIG_SIZE))
messgs[c] = bad_sig

block = []
for k, v in messgs.items():
block.append(b'%s%s' % (func1(k), v))
else:
random.shuffle(block)
return ''.join(block)


def chaff_chaff_chaff_m(val, key):
if not isinstance(val, bytes):
val = val.encode('utf-8')
the_out = []
for b in val:
the_out.append(chaff_chaff_chaff_b(func1(b), key))
else:
out1 = ''.join(the_out)
return struct.pack('>I', len(val)) + out1


def winnow_winnow_winnow_m(val, key):
if not isinstance(val, bytes):
val = val.encode('utf-8')
msglen = struct.unpack('>I', val[:4])[0]
val = val[4:]
block_len = (SIG_SIZE + 1) * KIDING_SIZE
expected_len = block_len * msglen
if len(val) != expected_len:
raise ValueError('E~x~p~e~c~t~e~d l~e~n~g~t~h %d, saw %d.' % (expected_len, len(val)))
pieces = []
for c in range(msglen):
chunk = val[block_len * c:block_len * (c + 1)]
res = winnow_winnow_winnow_b(chunk, key)
pieces.append(res)
else:
return ''.join(pieces)


def winnow_winnow_winnow_b(val, key):
while val:
c = func1(val[0])
sig = val[1:SIG_SIZE + 1]
if sign_sign_sign(c, key) == sig:
return c
val = val[SIG_SIZE + 1:]

raise ValueError('~N~o v~a~l~i~d s~i~g f~o~u~n~d!')


def main():
inp = b'~T~h~i~s i~s a t~e~s~t m~e~s~s~a~g~e!'
msg = chaff_chaff_chaff_m(inp, KEY)
ret = winnow_winnow_winnow_m(msg, KEY)
if inp != ret:
print('W~r~o~n~g r~e~t: %s' % ret)


if __name__ == '__main__':
main()
# okay decompiling just_a_name.pyc

传输模型为首先4个字节是消息长度。然后是消息,每32*17字节为一组,每组的有效信息只有1字节。对该字节求hash,取前16byte添加在有效信息这一字节后面,这是共17字节。然后随机选31字节,这是非有效的垃圾信息,重复上述步骤,共得到32*17字节,最后随机打乱32小组的相对顺序。有效信息其实只有一字节。然后后面的有效信息同理。

另一端取出一组后,共3217字节,循环32次。利用提前约定好的key,计算32个字节的hash,共32\16字节,对比计算结果和每个小组中的第2~17个字节的签名是否相符,相符则是有效信息,其余31字节则是垃圾信息。

但我们没有key怎么办呢?统计。

由于一个字节的签名永远是相同的。所以如果一组中的签名也在其余组中出现,那么这大概率就是有效信息及其签名。

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
from Crypto.Util.number import *
from scapy.all import rdpcap


packets = rdpcap("message.pcap")
sport=3199
src="127.0.0.1"
f = b''
for packet in packets:
if "TCP" in packet and packet['TCP'].payload:
if packet["IP"].src==src and packet["TCP"].sport==sport:
f += packet['TCP'].payload.load
f = f[4:]


packets = []
for i in range(0, len(f), 32*17):
packets.append(f[i:i+32*17])

data = []
all_value = []
for packet in packets:
tmp = []
for i in range(0, 32*17, 17):
group = packet[i:i+17]
ch, sig = group[0], group[1:]
all_value.append((ch, sig))
tmp.append((ch, sig))
data.append(tmp)

result = []
for item in data:
for m in item:
if all_value.count(m) > 1:
result.append(m)
break

print(b''.join([long_to_bytes(item[0]) for item in result]))

名字没想好

task.py

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

#part1
flag1 = b'CUMTCTF{**********'
m1 = bytes_to_long(flag1)
p1 = getPrime(1024)
q1 = getPrime(1024)
e1 = 103738
n1 = p1 * q1
gift = lcm(p1 - 1, q1 - 1)
c1 = pow(m1, e1, n1)
print('n1 = ', n1)
print('c1 = ', c1)
print('gift = ', gift)

#part2
flag2 = b'**********************'
e2 = 65537
m2 = bytes_to_long(flag2)
p2 = getPrime(1024)
q2 = sympy.nextprime(p2)
n2 = p2 * q2
phi2 = (p2 - 1) * (q2 - 1)
d2 = gmpy2.invert(e2, phi2)
c2 = pow(m2, e2, n2)
print('d = ', d2)
print('c2 = ', c2)

data:

1
2
3
4
5
n1 =  24511956296934419790810802924028121267308277322350201914243748724443965915830044792139346496470216715543376102606906727287935669186132061565360428924230740995935556111187855700300365517739695893842582114724005232045077425187550801509268664723237890122110051088839310003135672964413501812829310021228720112275276180469100308793523051405119335989674132224715582989624204590983857159312466387546505666052162775188773736419909262619409755848412558718676873188073997893894862353873441073313610102773845304906678909624700529896455885309546409645526387707907518497436045821973310653257012148438207441605902771515486273283273
c1 = 7357116532209949285136310518084676100522798730487701269950303460540634127932201594120600757671807456790592531487713433579926404640474277692592102315472760853853767347752080563508622523821339163225554653816787201616233932746815764392729597579461985789538131853246938443458331139199802764554726447278501492140335824365867574318693890007499638038064582031311613039571335453968072426153706431456149868515230310567240569544961967582304893471240728585336273245259533905230737876248875784828430507371662455796543123714325161987112223947057481814610592300979207673818538093532100233028106442070524965861451563388404227738574
gift = 12255978148467209895405401462014060633654138661175100957121874362221982957915022396069673248235108357771688051303453363643967834593066030782680214462115370497967778055593927850150182758869847946921291057362002616022538712593775400754634332361618945061055025544419655001567836482206750906414655010614360056137481173664901476116870144816992211793902146834987166288769615612767704010592138813256140678199511291489394523989294805910740127557682458229594376211232977501267410539674224065875285801753027816046254818608535462445306054117075379711073762930279723764342988824053970592468109679774789092077979655857748513636834
d = 14519297697723031496224953772301033569165883208616356699837703756220717249229195213146695656923357394378868735444167631602696573904678412172248043414276910206086892084385988564720914312238316434518024995169814463252129242492227202678878240875905293369168263909256455159691392124769949072754243536472227070447391890140409479709945084894060833468804156778720190688101601664725009609222256314873780002770605127043596912060811904733471592387441742111474341938658516761896926403628885365926903655309306738689809023277824030268579979837642613499180913999651379232105756338399243024739524553588216117189742912479604441636257
c2 = 23574157314515030841894399693996910252287747536395985840285410194536546768646580704111053676040921830550019965767796038280932469005359270920519250763405535872475345625907947986452218739530197421244240070129909526493952916306821311836861766221812155261751444946282559677005557815746813525162411907545113665605490915464367483833005576787591204417525937745572210195816236947103271664048065491627347939268785403334419989160034526164012966888952162714736497312282011026789187871221751240709801544484784941178786820290118585681595783245449236394480319395321877182096839866054466492123200354772280398476167002177544154960579

一共两关。

首先观察到e明显不是素数,但是e/2是。所以rsa的公司转换成m的平方的e/2方。套公式的时候,要把e/2当成e代入,求出的是m的平方。然后开方可得m。

然后得想办法求phi。很明显题目给出了p-1和q-1的最小公倍数。由于lcm(p-1, q-1) * gcd(p-1, q-1) = (p-1)*(q-1)

简记为lcm * gcd = phi

phi和n的长度差不太多,n的长度是2048,而lcm的长度是2047,所以gcd只需要爆个位数就行。爆出phi就可以求第一段flag.

那第二关呢?

已知e, d, c。求n。

很明显p和q是相邻素数,在这前提下p约等于根号下n约等于根号下phi。

phi可以表示成(e*d-1)/k,e和d已知。所以可以爆破k。ed乘积是2063,phi必然比d要大,而d的长度是2047,所以爆破上限是2的16次方。

稍微约束下就开始爆破。对phi开根号,可以得到p的近似值tmp。然后next_prime(tmp)必然是p或者q。为啥呢?因为p<q,如果p和q都在tmp的左侧,那么p*q<tmp的平方即phi。矛盾哦。

脚本:

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

n1 = 24511956296934419790810802924028121267308277322350201914243748724443965915830044792139346496470216715543376102606906727287935669186132061565360428924230740995935556111187855700300365517739695893842582114724005232045077425187550801509268664723237890122110051088839310003135672964413501812829310021228720112275276180469100308793523051405119335989674132224715582989624204590983857159312466387546505666052162775188773736419909262619409755848412558718676873188073997893894862353873441073313610102773845304906678909624700529896455885309546409645526387707907518497436045821973310653257012148438207441605902771515486273283273
c1 = 7357116532209949285136310518084676100522798730487701269950303460540634127932201594120600757671807456790592531487713433579926404640474277692592102315472760853853767347752080563508622523821339163225554653816787201616233932746815764392729597579461985789538131853246938443458331139199802764554726447278501492140335824365867574318693890007499638038064582031311613039571335453968072426153706431456149868515230310567240569544961967582304893471240728585336273245259533905230737876248875784828430507371662455796543123714325161987112223947057481814610592300979207673818538093532100233028106442070524965861451563388404227738574
_lcm = gift = 12255978148467209895405401462014060633654138661175100957121874362221982957915022396069673248235108357771688051303453363643967834593066030782680214462115370497967778055593927850150182758869847946921291057362002616022538712593775400754634332361618945061055025544419655001567836482206750906414655010614360056137481173664901476116870144816992211793902146834987166288769615612767704010592138813256140678199511291489394523989294805910740127557682458229594376211232977501267410539674224065875285801753027816046254818608535462445306054117075379711073762930279723764342988824053970592468109679774789092077979655857748513636834
e1 = 103738 // 2

for _gcd in range(1, 10):
try:
phi = _lcm * _gcd
d1 = inverse(e1, phi)
m1 = pow(c1, d1, n1)
m1 = iroot(m1, 2)[0]
msg = long_to_bytes(m1)

if b'CUMTCTF{' in msg:
print(msg)
break
except:
pass


d2 = 14519297697723031496224953772301033569165883208616356699837703756220717249229195213146695656923357394378868735444167631602696573904678412172248043414276910206086892084385988564720914312238316434518024995169814463252129242492227202678878240875905293369168263909256455159691392124769949072754243536472227070447391890140409479709945084894060833468804156778720190688101601664725009609222256314873780002770605127043596912060811904733471592387441742111474341938658516761896926403628885365926903655309306738689809023277824030268579979837642613499180913999651379232105756338399243024739524553588216117189742912479604441636257
c2 = 23574157314515030841894399693996910252287747536395985840285410194536546768646580704111053676040921830550019965767796038280932469005359270920519250763405535872475345625907947986452218739530197421244240070129909526493952916306821311836861766221812155261751444946282559677005557815746813525162411907545113665605490915464367483833005576787591204417525937745572210195816236947103271664048065491627347939268785403334419989160034526164012966888952162714736497312282011026789187871221751240709801544484784941178786820290118585681595783245449236394480319395321877182096839866054466492123200354772280398476167002177544154960579
e2 = 65537
ed = e2 * d2
print(len(bin(ed)[2:]))

for k in range(2**14, 2**15):
if (ed - 1) % k == 0:
phi2 = (ed - 1) // k
tmp = iroot(phi2, 2)[0]
p2 = next_prime(tmp)
#print(k)
#print(phi2 % (p2-1))
if phi2 % (p2-1) == 0:
q2 = phi2 // (p2-1) + 1
n2 = p2 * q2
m2 = pow(c2, d2, n2)
msg = long_to_bytes(m2)
print(msg)
break

Merry_Christmas

task.py

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
from Crypto.Util.number import *
from gmpy2 import *
#from secret import flag
bit_length = 1024
p = getPrime(bit_length)
q = getPrime(bit_length)
n = p*q
m = bytes_to_long(flag)
n= p * q
e = 65537
c = pow(m,e,n)

p1 = getPrime(bit_length)
q1 = getPrime(bit_length)
n1 = p1*q1
e1 = 979691
c1 = pow(p,e1,n1)
gift1 = pow(907*p1+q1,587,n1)
gift2 = pow(p1+q1,691,n1)

print('n={}'.format(n))
print('c={}'.format(c))
print('n1={}'.format(n1))
print('c1={}'.format(c1))
print('gift1={}'.format(gift1))
print('gift2={}'.format(gift2))

data:

1
2
3
4
5
6
n=17539423546879883396629573776616418986256902147283732214295946312835113344061142956076117932720247053739715326040027048199629442201144987405090572982720131052885163184811793669071684926986445262835990861167700118224153436202178098707759605979066475651999711718728200184335695206586643579499656822346329750835696158561669170301767928780361376643304324731146650458384564533895090608529488304659924485356518526226061081943815971670656857778229528022465452008890430046982169571771039198877713729197033434033303723925335811353531172899520232033290866272195248554656110282928669639257994965701208856346298076998993772423097
c=5560694632613114538708358450844738346732427106497566176686415566542021811907746171660858360055720615188679328728275250111979427060322426593068123630729075838980217642604281020733578019517061369665467249555496690538379316251258553434263030485822069081031041121329559075841297923650799241347196473466430248261213536319894271629049899379974582453405472218720572088937075254938460083046946717784821298765199164644879680847984441166684509290675197526982405556980540919856072198191306527746754844792294221564010770506298266272017613487725494001276623402987809305696759434595799863487759478902384039066714073292949058853003
n1=21465819616864492551767155722996412718832402997933699784091937387760830726039866762857450959675228856561597024318920734312362144261628290737563681759442171285581931041622345778933572673367607809994811354957971820829401430301563611970709279094237597394734599103937206689348004861322161582747568764567491894069565665829828570957338594421227530701263883322496237907509301547209937444268813162260988374157151529111924866290775985684107622034449136081744171954609262107449388993051611516007232903948144186151363436032658716266030263647775582015141329829060294352706551807295555026827381280240539020513044515406829846588787
c1=19585478304129650368934167685581947379018238627360258251578178648406399091655911309790559870365866290321783969820131014958701556570645863667895395615377725655139970869868226237575462206775170966585306390686724869174973947234608655786245191308423334769172394586099003865664934720651493266130413617892286830586179842568659758155132923079476873190047514962385696606866440573294836559927597496331643346032100075257329902065785369011323134807157288931237650262052445952481912276967263237183320639027956890814569212814115581834172475173790422964999583755677956698930811772293980516268488171908878145019531149798750799613142
gift1=21073862899796816496314528055339279280335681203948249072101881208021752125789533267427994742277358208178070970462447090818216561770563907183494712376741842209323406667050344266668347773728401520981152006053958337605219297650281680615939792818684114311810254344598007357629176456353064311734075462353266893546853648829947081541158912147691654438830914577857503519080776224006347318623082457516638594584206488534978134212723395494600005197454325625290580653432901204502054226866606652982669196910942405139803194404497913820850500332680877820694279428529873469583387698995104411071804749202120283361058269192420218572231
gift2=7634352822409241151514235360777296908269419654786551951076299092182838191720014827302929726661609788893676185300000003824161794580145215813570705896440007085639728197111313542046542236060921056046727832889041640187683808320443684484085665265794806366182119574554965179974119587542057100849953753232435527244682735108194058759240757296546820383552711669453408694460188770050594702462736564767783116432265746800810795602828775783509056534518928775187835786128676790426643882842096826044057116388930041087679950264956074503205229333151001519229166174531496272703271636344792947552939606533888390978361247276796123693665

之前上海市ctf的题,原地tp我之前的wp

解题脚本:

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

n=17539423546879883396629573776616418986256902147283732214295946312835113344061142956076117932720247053739715326040027048199629442201144987405090572982720131052885163184811793669071684926986445262835990861167700118224153436202178098707759605979066475651999711718728200184335695206586643579499656822346329750835696158561669170301767928780361376643304324731146650458384564533895090608529488304659924485356518526226061081943815971670656857778229528022465452008890430046982169571771039198877713729197033434033303723925335811353531172899520232033290866272195248554656110282928669639257994965701208856346298076998993772423097
c=5560694632613114538708358450844738346732427106497566176686415566542021811907746171660858360055720615188679328728275250111979427060322426593068123630729075838980217642604281020733578019517061369665467249555496690538379316251258553434263030485822069081031041121329559075841297923650799241347196473466430248261213536319894271629049899379974582453405472218720572088937075254938460083046946717784821298765199164644879680847984441166684509290675197526982405556980540919856072198191306527746754844792294221564010770506298266272017613487725494001276623402987809305696759434595799863487759478902384039066714073292949058853003
n1=21465819616864492551767155722996412718832402997933699784091937387760830726039866762857450959675228856561597024318920734312362144261628290737563681759442171285581931041622345778933572673367607809994811354957971820829401430301563611970709279094237597394734599103937206689348004861322161582747568764567491894069565665829828570957338594421227530701263883322496237907509301547209937444268813162260988374157151529111924866290775985684107622034449136081744171954609262107449388993051611516007232903948144186151363436032658716266030263647775582015141329829060294352706551807295555026827381280240539020513044515406829846588787
c1=19585478304129650368934167685581947379018238627360258251578178648406399091655911309790559870365866290321783969820131014958701556570645863667895395615377725655139970869868226237575462206775170966585306390686724869174973947234608655786245191308423334769172394586099003865664934720651493266130413617892286830586179842568659758155132923079476873190047514962385696606866440573294836559927597496331643346032100075257329902065785369011323134807157288931237650262052445952481912276967263237183320639027956890814569212814115581834172475173790422964999583755677956698930811772293980516268488171908878145019531149798750799613142
gift1=21073862899796816496314528055339279280335681203948249072101881208021752125789533267427994742277358208178070970462447090818216561770563907183494712376741842209323406667050344266668347773728401520981152006053958337605219297650281680615939792818684114311810254344598007357629176456353064311734075462353266893546853648829947081541158912147691654438830914577857503519080776224006347318623082457516638594584206488534978134212723395494600005197454325625290580653432901204502054226866606652982669196910942405139803194404497913820850500332680877820694279428529873469583387698995104411071804749202120283361058269192420218572231
gift2=7634352822409241151514235360777296908269419654786551951076299092182838191720014827302929726661609788893676185300000003824161794580145215813570705896440007085639728197111313542046542236060921056046727832889041640187683808320443684484085665265794806366182119574554965179974119587542057100849953753232435527244682735108194058759240757296546820383552711669453408694460188770050594702462736564767783116432265746800810795602828775783509056534518928775187835786128676790426643882842096826044057116388930041087679950264956074503205229333151001519229166174531496272703271636344792947552939606533888390978361247276796123693665
e1 = 979691
e = 65537


#gift1 = pow(907*p1+q1,587,n1)
#gift2 = pow(p1+q1,691,n1)

tmp = pow(gift2, 587, n1) - pow(gift1, 691, n1)
p1 = gcd(tmp, n1)
q1 = n1 // p1
phi1 = (p1 - 1) * (q1 - 1)
d1 = inverse(e1, phi1)
p = pow(c1, d1, n1)

q = n // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
msg = long_to_bytes(m)
print(msg)