python字节码反编译

Posted by nop on 2020-04-20
Words 2.9k In Total

在虎符上面看到一道逆向题,主要是python的字节码反汇编的问题,以前没遇到过,这里记录一下

python 字节码的反汇编

python提供了工具库 dis 可以将字节码显示成可读的形式

从变量赋值到常见情况

1
2
3
def func(arg):
arg = 12
return arg+12

对应的字节码:

1
2
3
4
5
6
7
8
9
import dis
dis.dis(func)
# 2 0 LOAD_CONST 1 (12)
# 2 STORE_FAST 0 (arg)

# 3 4 LOAD_FAST 0 (arg)
# 6 LOAD_CONST 1 (12)
# 8 BINARY_ADD
# 10 RETURN_VALUE

对应的格式如下:

源码行号 | 指令偏移量 | 指令符号 | 指令参数 | 实际参数值

不同版本的CPython 指令长度可能不同,但是 3.7的每条指令是2个字节,所以我们去看dis 生成的字节码指令集的时候,指令偏移量总是从0开始,每增加一条在原来的偏移量上增加2    故,指令偏移量的值,一般都是: 0 , 2 , 4, 6 , 8 , … , 2n ( n>=0 )

实际上,python的字节码经函数处理之后阅读并不是很复杂,只需要点耐心
看题目前先来看一下几种常见的情况:

  • for 循环
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
def func():
for i in range(32,128):
t = i + i
print(t)
dis.dis(func)
# 2 0 SETUP_LOOP 34 (to 36)
# 2 LOAD_GLOBAL 0 (range)
# 4 LOAD_CONST 1 (32)
# 6 LOAD_CONST 2 (128)
# 8 CALL_FUNCTION 2
# 10 GET_ITER
# >> 12 FOR_ITER 20 (to 34)
# 14 STORE_FAST 0 (i)

# 3 16 LOAD_FAST 0 (i)
# 18 LOAD_FAST 0 (i)
# 20 BINARY_ADD
# 22 STORE_FAST 1 (t)

# 4 24 LOAD_GLOBAL 1 (print)
# 26 LOAD_FAST 1 (t)
# 28 CALL_FUNCTION 1
# 30 POP_TOP
# 32 JUMP_ABSOLUTE 12
# >> 34 POP_BLOCK
# >> 36 LOAD_CONST 0 (None)
# 38 RETURN_VALUE
  • while 循环
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
def func():
t = 0
while(True):
a = 'hello'
b = 'world'
print(a+b)
t += 1
if t == 3:
break
dis.dis(func)
# 3 0 LOAD_CONST 1 (0)
# 2 STORE_FAST 0 (t)

# 4 4 SETUP_LOOP 42 (to 48)

# 5 >> 6 LOAD_CONST 2 ('hello')
# 8 STORE_FAST 1 (a)

# 6 10 LOAD_CONST 3 ('world')
# 12 STORE_FAST 2 (b)

# 7 14 LOAD_GLOBAL 0 (print)
# 16 LOAD_FAST 1 (a)
# 18 LOAD_FAST 2 (b)
# 20 BINARY_ADD
# 22 CALL_FUNCTION 1
# 24 POP_TOP

# 8 26 LOAD_FAST 0 (t)
# 28 LOAD_CONST 4 (1)
# 30 INPLACE_ADD
# 32 STORE_FAST 0 (t)

# 9 34 LOAD_FAST 0 (t)
# 36 LOAD_CONST 5 (3)
# 38 COMPARE_OP 2 (==)
# 40 POP_JUMP_IF_FALSE 6

# 10 42 BREAK_LOOP
# 44 JUMP_ABSOLUTE 6
# 46 POP_BLOCK
# >> 48 LOAD_CONST 0 (None)
# 50 RETURN_VALUE
# None

这里只列举for、while、if三种情况,可以发现其实我们看到的字节码并不复杂,很容易理解

game(2020 虎符)

题目给了一段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
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
# Python 2.7
# Embedded file name: game.py

1 0 LOAD_CONST 249
3 LOAD_CONST 91
6 LOAD_CONST 149
9 LOAD_CONST 113
12 LOAD_CONST 16
15 LOAD_CONST 91
18 LOAD_CONST 53
21 LOAD_CONST 41
24 BUILD_LIST_8 8
27 STORE_NAME 0 'arr0'

2 30 LOAD_CONST 43
33 LOAD_CONST 1
36 LOAD_CONST 6
39 LOAD_CONST 69
42 LOAD_CONST 20
45 LOAD_CONST 62
48 LOAD_CONST 6
51 LOAD_CONST 44
54 LOAD_CONST 24
57 LOAD_CONST 113
60 LOAD_CONST 6
63 LOAD_CONST 35
66 LOAD_CONST 0
69 LOAD_CONST 3
72 LOAD_CONST 6
75 LOAD_CONST 44
78 LOAD_CONST 20
81 LOAD_CONST 22
84 LOAD_CONST 127
87 LOAD_CONST 60
90 BUILD_LIST_20 20
93 STORE_NAME 1 'arr1'

3 96 LOAD_CONST 90
99 LOAD_CONST 100
102 LOAD_CONST 87
105 LOAD_CONST 109
108 LOAD_CONST 86
111 LOAD_CONST 108
114 LOAD_CONST 86
117 LOAD_CONST 105
120 LOAD_CONST 90
123 LOAD_CONST 104
126 LOAD_CONST 88
129 LOAD_CONST 102
132 BUILD_LIST_12 12
135 STORE_NAME 2 'arr2'

5 138 LOAD_CODE <code_object check0>
141 MAKE_FUNCTION_0 0 None
144 STORE_NAME 3 'check0'

8 147 LOAD_CODE <code_object check1>
150 MAKE_FUNCTION_0 0 None
153 STORE_NAME 4 'check1'

14 156 LOAD_CODE <code_object check2>
159 MAKE_FUNCTION_0 0 None
162 STORE_NAME 5 'check2'

20 165 LOAD_CODE <code_object check3>
168 MAKE_FUNCTION_0 0 None
171 STORE_NAME 6 'check3'

37 174 LOAD_NAME 7 'raw_input'
177 CALL_FUNCTION_0 0 None
180 STORE_NAME 8 'flag'

38 183 LOAD_NAME 3 'check0'
186 LOAD_NAME 8 'flag'
189 CALL_FUNCTION_1 1 None
192 POP_JUMP_IF_FALSE 239 'to 239'
195 LOAD_NAME 4 'check1'
198 LOAD_NAME 8 'flag'
201 CALL_FUNCTION_1 1 None
204 POP_JUMP_IF_FALSE 239 'to 239'
207 LOAD_NAME 5 'check2'
210 LOAD_NAME 8 'flag'
213 CALL_FUNCTION_1 1 None
216 POP_JUMP_IF_FALSE 239 'to 239'
219 LOAD_NAME 6 'check3'
222 LOAD_NAME 8 'flag'
225 CALL_FUNCTION_1 1 None
228_0 COME_FROM 216 '216'
228_1 COME_FROM 204 '204'
228_2 COME_FROM 192 '192'
228 POP_JUMP_IF_FALSE 239 'to 239'

39 231 LOAD_CONST 'ok'
234 PRINT_ITEM
235 PRINT_NEWLINE_CONT
236 JUMP_FORWARD 5 'to 244'

41 239 LOAD_CONST 'no'
242 PRINT_ITEM
243 PRINT_NEWLINE_CONT
244_0 COME_FROM 236 '236'
244 LOAD_CONST None
247 RETURN_VALUE

# check0 line 5 of game.py

6 0 LOAD_GLOBAL 0 'all'
3 LOAD_GENEXPR '<code_object <genexpr>>'
6 MAKE_FUNCTION_0 0 None
9 LOAD_FAST 0 's'
12 GET_ITER
13 CALL_FUNCTION_1 1 None
16 CALL_FUNCTION_1 1 None
19 RETURN_VALUE

# check1 line 8 of game.py

9 0 LOAD_GLOBAL 0 'len'
3 LOAD_FAST 0 's'
6 CALL_FUNCTION_1 1 None
9 LOAD_CONST 100
12 COMPARE_OP 0 <
15 POP_JUMP_IF_FALSE 58 'to 58'
18 LOAD_GLOBAL 0 'len'
21 LOAD_FAST 0 's'
24 CALL_FUNCTION_1 1 None
27 LOAD_GLOBAL 0 'len'
30 LOAD_FAST 0 's'
33 CALL_FUNCTION_1 1 None
36 BINARY_MULTIPLY
37 LOAD_CONST 777
40 BINARY_MODULO
41 LOAD_CONST 233
44 BINARY_XOR
45 LOAD_CONST 513
48 COMPARE_OP 2 ==
51_0 COME_FROM 15 '15'
51 POP_JUMP_IF_FALSE 58 'to 58'

10 54 LOAD_GLOBAL 1 'True'
57 RETURN_END_IF
58_0 COME_FROM 51 '51'

12 58 LOAD_GLOBAL 2 'False'
61 RETURN_VALUE
62 LOAD_CONST None
65 RETURN_VALUE

# check2 line 14 of game.py

15 0 LOAD_GLOBAL 0 'ord'
3 LOAD_FAST 0 's'
6 LOAD_CONST 0
9 BINARY_SUBSCR
10 CALL_FUNCTION_1 1 None
13 LOAD_CONST 128
16 BINARY_MULTIPLY
17 LOAD_GLOBAL 0 'ord'
20 LOAD_FAST 0 's'
23 LOAD_CONST 1
26 BINARY_SUBSCR
27 CALL_FUNCTION_1 1 None
30 BINARY_ADD
31 LOAD_CONST 128
34 BINARY_MULTIPLY
35 LOAD_GLOBAL 0 'ord'
38 LOAD_FAST 0 's'
41 LOAD_CONST 2
44 BINARY_SUBSCR
45 CALL_FUNCTION_1 1 None
48 BINARY_ADD
49 LOAD_CONST 128
52 BINARY_MULTIPLY
53 LOAD_GLOBAL 0 'ord'
56 LOAD_FAST 0 's'
59 LOAD_CONST 3
62 BINARY_SUBSCR
63 CALL_FUNCTION_1 1 None
66 BINARY_ADD
67 LOAD_CONST 128
70 BINARY_MULTIPLY
71 LOAD_GLOBAL 0 'ord'
74 LOAD_FAST 0 's'
77 LOAD_CONST 4
80 BINARY_SUBSCR
81 CALL_FUNCTION_1 1 None
84 BINARY_ADD
85 LOAD_CONST 128
88 BINARY_MULTIPLY
89 LOAD_GLOBAL 0 'ord'
92 LOAD_FAST 0 's'
95 LOAD_CONST 5
98 BINARY_SUBSCR
99 CALL_FUNCTION_1 1 None
102 BINARY_ADD
103 LOAD_CONST 3533889469877L
106 COMPARE_OP 2 ==
109 POP_JUMP_IF_FALSE 138 'to 138'
112 LOAD_GLOBAL 0 'ord'
115 LOAD_FAST 0 's'
118 LOAD_CONST -1
121 BINARY_SUBSCR
122 CALL_FUNCTION_1 1 None
125 LOAD_CONST 125
128 COMPARE_OP 2 ==
131_0 COME_FROM 109 '109'
131 POP_JUMP_IF_FALSE 138 'to 138'

16 134 LOAD_GLOBAL 1 'True'
137 RETURN_END_IF
138_0 COME_FROM 131 '131'

18 138 LOAD_GLOBAL 2 'False'
141 RETURN_VALUE
142 LOAD_CONST None
145 RETURN_VALUE

# check3 line 20 of game.py

21 0 LOAD_GLOBAL 0 'map'
3 LOAD_GLOBAL 1 'ord'
6 LOAD_FAST 0 's'
9 CALL_FUNCTION_2 2 None
12 STORE_FAST 1 'arr'

22 15 LOAD_FAST 1 'arr'
18 LOAD_CONST 6
21 LOAD_CONST 30
24 LOAD_CONST 3
27 BUILD_SLICE_3 3
30 BINARY_SUBSCR
31 STORE_FAST 2 'a'

23 34 SETUP_LOOP 62 'to 99'
37 LOAD_GLOBAL 2 'range'
40 LOAD_GLOBAL 3 'len'
43 LOAD_FAST 2 'a'
46 CALL_FUNCTION_1 1 None
49 CALL_FUNCTION_1 1 None
52 GET_ITER
53 FOR_ITER 42 'to 98'
56 STORE_FAST 3 'i'

24 59 LOAD_FAST 2 'a'
62 LOAD_FAST 3 'i'
65 BINARY_SUBSCR
66 LOAD_CONST 17684
69 BINARY_MULTIPLY
70 LOAD_CONST 372511
73 BINARY_ADD
74 LOAD_CONST 257
77 BINARY_MODULO
78 LOAD_GLOBAL 4 'arr0'
81 LOAD_FAST 3 'i'
84 BINARY_SUBSCR
85 COMPARE_OP 3 !=
88 POP_JUMP_IF_FALSE 53 'to 53'

25 91 LOAD_GLOBAL 5 'False'
94 RETURN_END_IF
95_0 COME_FROM 88 '88'
95 JUMP_BACK 53 'to 53'
98 POP_BLOCK
99_0 COME_FROM 34 '34'

26 99 LOAD_FAST 1 'arr'
102 LOAD_CONST -2
105 LOAD_CONST 33
108 LOAD_CONST -1
111 BUILD_SLICE_3 3
114 BINARY_SUBSCR
115 LOAD_CONST 5
118 BINARY_MULTIPLY
119 STORE_FAST 4 'b'

27 122 LOAD_GLOBAL 0 'map'
125 LOAD_LAMBDA '<code_object <lambda>>'
128 MAKE_FUNCTION_0 0 None
131 LOAD_GLOBAL 6 'zip'
134 LOAD_FAST 4 'b'
137 LOAD_FAST 1 'arr'
140 LOAD_CONST 7
143 LOAD_CONST 27
146 SLICE+3
147 CALL_FUNCTION_2 2 None
150 CALL_FUNCTION_2 2 None
153 STORE_FAST 5 'c'

28 156 LOAD_FAST 5 'c'
159 LOAD_GLOBAL 7 'arr1'
162 COMPARE_OP 3 !=
165 POP_JUMP_IF_FALSE 172 'to 172'

29 168 LOAD_GLOBAL 5 'False'
171 RETURN_END_IF
172_0 COME_FROM 165 '165'

30 172 LOAD_CONST 0
175 STORE_FAST 6 'p'

31 178 SETUP_LOOP 105 'to 286'
181 LOAD_GLOBAL 2 'range'
184 LOAD_CONST 28
187 LOAD_CONST 34
190 CALL_FUNCTION_2 2 None
193 GET_ITER
194 FOR_ITER 88 'to 285'
197 STORE_FAST 3 'i'

32 200 LOAD_FAST 1 'arr'
203 LOAD_FAST 3 'i'
206 BINARY_SUBSCR
207 LOAD_CONST 107
210 BINARY_ADD
211 LOAD_CONST 16
214 BINARY_DIVIDE
215 LOAD_CONST 77
218 BINARY_ADD
219 LOAD_GLOBAL 8 'arr2'
222 LOAD_FAST 6 'p'
225 BINARY_SUBSCR
226 COMPARE_OP 3 !=
229 POP_JUMP_IF_TRUE 268 'to 268'
232 LOAD_FAST 1 'arr'
235 LOAD_FAST 3 'i'
238 BINARY_SUBSCR
239 LOAD_CONST 117
242 BINARY_ADD
243 LOAD_CONST 16
246 BINARY_MODULO
247 LOAD_CONST 99
250 BINARY_ADD
251 LOAD_GLOBAL 8 'arr2'
254 LOAD_FAST 6 'p'
257 LOAD_CONST 1
260 BINARY_ADD
261 BINARY_SUBSCR
262 COMPARE_OP 3 !=
265_0 COME_FROM 229 '229'
265 POP_JUMP_IF_FALSE 272 'to 272'

33 268 LOAD_GLOBAL 9 'false'
271 RETURN_END_IF
272_0 COME_FROM 265 '265'

34 272 LOAD_FAST 6 'p'
275 LOAD_CONST 2
278 INPLACE_ADD
279 STORE_FAST 6 'p'
282 JUMP_BACK 194 'to 194'
285 POP_BLOCK
286_0 COME_FROM 178 '178'

35 286 LOAD_GLOBAL 10 'True'
289 RETURN_VALUE

# <genexpr> line 6 of game.py

6 0 LOAD_FAST 0 '.0'
3 FOR_ITER 32 'to 38'
6 STORE_FAST 1 'x'
9 LOAD_GLOBAL 0 'ord'
12 LOAD_FAST 1 'x'
15 CALL_FUNCTION_1 1 None
18 LOAD_GLOBAL 1 'range'
21 LOAD_CONST 32
24 LOAD_CONST 128
27 CALL_FUNCTION_2 2 None
30 COMPARE_OP 6 in
33 YIELD_VALUE
34 POP_TOP
35 JUMP_BACK 3 'to 3'
38 LOAD_CONST None
41 RETURN_VALUE

# <lambda> line 27 of game.py

27 0 LOAD_FAST 0 'x'
3 LOAD_CONST 0
6 BINARY_SUBSCR
7 LOAD_FAST 0 'x'
10 LOAD_CONST 1
13 BINARY_SUBSCR
14 BINARY_XOR
15 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
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
arr0 = [249,91,149,113,16,91,53,41]
arr1 = [43,1,6,69,20,62,6,44,24,113,6,35,0,3,6,44,20,22,127,60]
arr2 = [90,100,87,109,86,108,86,105,90,104,88,102]

def check0(s):
x = map(ord,s)
for i in x:
if (not (i in range(32,128))):
return False
return True

def check1(s):
length = len(s)
if length<100 :
if((((\
length*length)\
%777)\
^233) == 513):
return True
else:
return False
else:
return False

def check2(s):
t1 = ord(s[0])*128 + ord(s[1])
t2 = t1*128 + ord(s[2])
t3 = t2*128 + ord(s[3])
t4 = t3*128 + ord(s[4])
t5 = t4*128 + ord(s[5])
if t5 != 3533889469877:
return False
if s[-1] != '}':
return False
return True

def check3(s):
arr = map(ord,s)
a = arr[6:30:3]
for i in range(len(a)):
if((((\
a[i]*17684)\
+372511)\
%257) == arr0[i]):
continue
else return False

b = arr[-2:33:-1] *5
c = map(lambda x:x[0]^x[1],zip(b,arr[7:27]))
if not (c==arr1):
return False

p = 0
for i in range(28,34):
if(((arr[i]+107)/16 + 77) != arr2[p]):
return False
if(((arr[i]+117)%16 + 99) != arr2[p+1]):
return False
p += 2

flag = ''

if(!check0(flag)):
print('no')
elif(!check1(flag)):
print('no')
elif(!check2(flag)):
print('no')
elif(!check3(flag)):
print('no')
else:
print('ok')

可以发现程序处理flag分组很明显,先看check0

这个函数将输入限制在(32,128)即课件字符的范围,所以在后面几个check中我们可以采取爆破的形式(刚开始尝试根据所给表反推,但是失败了,又一次被自己菜到)

对于check1,用于判断flag长度,我们可以根据这部分得到flag的长度为 39:

1
2
3
length = 39
arr = [0 for i in range(length)]
arr[-1] = '}'

接着到check2,判断flag前6个字符,因为格式为flag{},所以可以得到前5个字符,然后通过条件得到第六个字符为5

1
2
3
4
5
6
7
8
9
10
11
s = [ord(i) for i in 'flag{']
t1 = s[0]*128 + s[1]
t2 = t1*128 + s[2]
t3 = t2*128 + s[3]
t4 = t3*128 + s[4]
t5 = t4*128
res = 3533889469877 - t5
# print(chr(res))
t = 'flag{' + chr(res)
for i in range(6):
arr[i] = t[i]

接着看check3,check3分为三部分即将flag分为三组处理

第一部分,通过运算和arr0依次判断,因为输入限制在(32,128)所以这里采取爆破的方式:

1
2
3
4
5
6
7
8
9
10
temp = []
for check in arr0:
for res in range(32,128):
if (((res*17684+372511)%257) == check):
temp.append(res)
break
t = 0
for i in range(6,30,3):
arr[i] = temp[t]
t += 1

第二部分,主要过程为将flag后4个字符(不包括’}’)扩展成20个字符,然后分别于flag的第7到第27异或之后与arr1比对

通过这部分我们可以先还原出 flag的后四个字符(这里需要注意得到的后四个字符的顺序):

1
2
3
4
b = [i for i in map(lambda x:x[0]^x[1],[(arr[7:27][i],arr1[i]) for i in range(2,20,3)])]
b =[b[3]]+ b[:-3]
arr[-2:33:-1] = b[-1::-1]
b = b[-1::-1]*5

接着再计算得到flag第7到27个字符

1
arr[7:27] = [ chr(i) for i in map(lambda x:x[0]^x[1],zip(b,arr1))]

最后一部分就是除和取余的操作,这里同样采取爆破的形式:

1
2
3
4
5
6
7
8
9
10
temp = []
for check in range(0,len(arr2),2):
for res in range(32,129):
if((res+107)//16 +77) == arr2[check] \
and ((res+117)%16 + 99) == arr2[check+1]:
temp.append(res)
t = 0
for i in range(28,34):
arr[i] = temp[t]
t += 1

最后得到flag

1
2
3
4
5
for i in range(len(arr)):
if isinstance(arr[i],int):
arr[i] = chr(arr[i])
flag = ''.join(arr)
print(flag)

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
from math import pow

arr0 = [249,91,149,113,16,91,53,41]
arr1 = [43,1,6,69,20,62,6,44,24,113,6,35,0,3,6,44,20,22,127,60]
arr2 = [90,100,87,109,86,108,86,105,90,104,88,102]

# check1
# for i in range(100):
# if (int(pow(i,2)%777)^233) == 513:
# print(i)
length = 39
arr = [0 for i in range(length)]
arr[-1] = '}'

# check2
s = [ord(i) for i in 'flag{']
t1 = s[0]*128 + s[1]
t2 = t1*128 + s[2]
t3 = t2*128 + s[3]
t4 = t3*128 + s[4]
t5 = t4*128
res = 3533889469877 - t5
# print(chr(res))
t = 'flag{' + chr(res)
for i in range(6):
arr[i] = t[i]

# check3
# part 1
temp = []
for check in arr0:
for res in range(32,128):
if (((res*17684+372511)%257) == check):
temp.append(res)
break
t = 0
for i in range(6,30,3):
arr[i] = temp[t]
t += 1

# part 2
b = [i for i in map(lambda x:x[0]^x[1],[(arr[7:27][i],arr1[i]) for i in range(2,20,3)])]
b =[b[3]]+ b[:-3]
arr[-2:33:-1] = b[-1::-1]
b = b[-1::-1]*5

arr[7:27] = [ chr(i) for i in map(lambda x:x[0]^x[1],zip(b,arr1))]

# part 3
temp = []
for check in range(0,len(arr2),2):
for res in range(32,129):
if((res+107)//16 +77) == arr2[check] \
and ((res+117)%16 + 99) == arr2[check+1]:
temp.append(res)

t = 0
for i in range(28,34):
arr[i] = temp[t]
t += 1

# final
for i in range(len(arr)):
if isinstance(arr[i],int):
arr[i] = chr(arr[i])
flag = ''.join(arr)
print(flag)

You are welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them.