HGAME 2020 Week2 wp

武汉加油!

Reverse

1. Classic_CrackMe

file查看文件类型


.net的逆向可以用dnSpy
核心代码为

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
private void button1_Click(object sender, EventArgs e)
{
if (this.status == 1)
{
MessageBox.Show("你已经激活成功啦,快去提交flag吧~~~");
return;
}
string text = this.textBox1.Text;
if (text.Length != 46 || text.IndexOf("hgame{") != 0 || text.IndexOf("}") != 45)
{
MessageBox.Show("Illegal format");
return;
}
string base64iv = text.Substring(6, 24);
string str = text.Substring(30, 15);
try
{
Aes aes = new Aes("SGc0bTNfMm8yMF9XZWVLMg==", base64iv);
Aes aes2 = new Aes("SGc0bTNfMm8yMF9XZWVLMg==", "MFB1T2g5SWxYMDU0SWN0cw==");
string text2 = aes.DecryptFromBase64String("mjdRqH4d1O8nbUYJk+wVu3AeE7ZtE9rtT/8BA8J897I=");
if (text2.Equals("Same_ciphertext_"))
{
byte[] array = new byte[16];
Array.Copy(aes2.EncryptToByte(text2 + str), 16, array, 0, 16);
if (Convert.ToBase64String(array).Equals("dJntSWSPWbWocAq4yjBP5Q=="))
{
MessageBox.Show("注册成功!");
this.Text = "已激活,欢迎使用!";
this.status = 1;
}
else
{
MessageBox.Show("注册失败!\nhint: " + aes2.DecryptFromBase64String("mjdRqH4d1O8nbUYJk+wVu3AeE7ZtE9rtT/8BA8J897I="));
}
}
else
{
MessageBox.Show("注册失败!\nhint: " + aes2.DecryptFromBase64String("mjdRqH4d1O8nbUYJk+wVu3AeE7ZtE9rtT/8BA8J897I="));
}
}
catch
{
MessageBox.Show("注册失败!");
}
}

flag由字符串base64iv和str拼接而成。
AES加密类型可看出为CBC加密,填补方式为PKCS7.

例子中的第一次AES加密明文长度为块大小,填充一个与块大小相同,内容为块大小的数据,因而第二次加密数据的明文和密文均不需要进行分析。根据AES-CBC加密的流程,先将明文P与初始化向量IV进行异或,再进行AES加密置换,解密流程为先将密文C进行AES解密置换,再与初始化向量IV进行异或。密文已知,只取前16字节(块大小)。

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Cipher import AES
import base64

def xor(s1, s2):
return bytes(map( (lambda x: x[0]^x[1]), zip(s1, s2) ))

key = base64.b64decode(b"SGc0bTNfMm8yMF9XZWVLMg==")
cipher = base64.b64decode(b"mjdRqH4d1O8nbUYJk+wVu3AeE7ZtE9rtT/8BA8J897I=")
aes = AES.new(key, AES.MODE_ECB)
msg = aes.decrypt(cipher)[:16]
target = b"Same_ciphertext_"
iv = xor(msg, target)

即可获得IV。
第二次加密总共两块,已知第二块的密文,第一块的明文,求第二块的明文。要注意解密后的为填补后的(15填补为16),应去除最后一字节。

1
2
3
aes2 = AES.new(key, AES.MODE_CBC, base64.b64decode(b"MFB1T2g5SWxYMDU0SWN0cw=="))
cipher1 = aes2.encrypt(target)
msg = aes.decrypt(base64.b64decode(b"dJntSWSPWbWocAq4yjBP5Q=="))

综合一下,即可得到对应的flag

1
print(b"hgame{" + base64.b64encode(iv) + xor(msg, cipher1)[:-1] + b"}")

2. babyPy

https://docs.python.org/zh-cn/3/library/dis.html
根据官方文档,可还原Python字节码。

1
2
3
4
5
6
7
8
def encrypt(OOo):
O0O = OOo[::-1]
O0o = list(O0O)
for O0 in range(1, len(O0o)):
Oo = O0o[O0 - 1] ^ O0o[O0]
O0o[O0] = Oo
O = bytes(O0o)
return O.hex()

因此,脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from binascii import unhexlify
def encrypt(OOo):
O0O = OOo[::-1]
O0o = list(O0O)
for O0 in range(1, len(O0o)):
Oo = O0o[O0 - 1] ^ O0o[O0]
O0o[O0] = Oo
O = bytes(O0o)
return O.hex()
def decrypt(bhstr):
bhstr = unhexlify(bhstr)
bhstr = list(bhstr)
for i in range(len(bhstr)-1, 0, -1):
bhstr[i] = bhstr[i-1] ^ bhstr[i]
return bytes(bhstr[::-1])
print(decrypt('7d037d045717722d62114e6a5b044f2c184c3f44214c2d4a22'))

3. babyPyc

使用uncompyle6反编译代码失败。

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
# uncompyle6 version 3.6.2
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: task.py
# Size of source mod 2**32: 1056 bytes


# file babyPyc_task_a1f4a8cf21.cpython-37.pyc
# --- This code section failed: ---

3 0 JUMP_ABSOLUTE 2 'to 2'
2 LOAD_CONST 0
4 LOAD_CONST None
6 IMPORT_NAME os
8 STORE_NAME os
10 LOAD_CONST 0
12 LOAD_CONST None
14 IMPORT_NAME sys

4 16 STORE_NAME sys
18 LOAD_CONST 0
20 LOAD_CONST ('b64encode',)
22 IMPORT_NAME base64
24 IMPORT_FROM b64encode
26 STORE_NAME b64encode

6 28 POP_TOP
30 LOAD_CONST b'/KDq6pvN/LLq6tzM/KXq59Oh/MTqxtOTxdrqs8OoR3V1X09J'

8 32 STORE_GLOBAL O0o
34 LOAD_CODE <code_object getFlag>
36 LOAD_STR 'getFlag'
38 MAKE_FUNCTION_0 ''

16 40 STORE_NAME getFlag
42 LOAD_NAME getFlag
44 CALL_FUNCTION_0 0 ''

18 46 STORE_NAME flag
48 LOAD_NAME flag
50 LOAD_CONST None
52 LOAD_CONST 6
54 BUILD_SLICE_2 2
56 BINARY_SUBSCR
58 LOAD_CONST b'hgame{'
60 COMPARE_OP !=
62 POP_JUMP_IF_TRUE 76 'to 76'
64 LOAD_NAME flag
66 LOAD_CONST -1
68 BINARY_SUBSCR
70 LOAD_CONST 125
72 COMPARE_OP !=

19 74 POP_JUMP_IF_FALSE 94 'to 94'
76_0 COME_FROM 62 '62'
76 LOAD_NAME print
78 LOAD_STR 'Incorrect format!'
80 CALL_FUNCTION_1 1 ''

20 82 POP_TOP
84 LOAD_NAME sys
86 LOAD_METHOD exit
88 LOAD_CONST 1
90 CALL_METHOD_1 1 ''

22 92 POP_TOP
94_0 COME_FROM 74 '74'
94 LOAD_NAME flag
96 LOAD_CONST 6
98 LOAD_CONST -1
100 BUILD_SLICE_2 2
102 BINARY_SUBSCR

23 104 STORE_NAME raw_flag
106 LOAD_NAME len
108 LOAD_NAME flag
110 CALL_FUNCTION_1 1 ''
112 LOAD_CONST 7
114 BINARY_SUBTRACT
116 LOAD_CONST 36
118 COMPARE_OP !=

24 120 POP_JUMP_IF_FALSE 140 'to 140'
122 LOAD_NAME print
124 LOAD_STR 'Wrong length!'
126 CALL_FUNCTION_1 1 ''

25 128 POP_TOP
130 LOAD_NAME sys
132 LOAD_METHOD exit
134 LOAD_CONST 2
136 CALL_METHOD_1 1 ''

27 138 POP_TOP
140_0 COME_FROM 120 '120'
140 LOAD_NAME raw_flag
142 LOAD_CONST None
144 LOAD_CONST None
146 LOAD_CONST -1
148 BUILD_SLICE_3 3
150 BINARY_SUBSCR

28 152 STORE_NAME raw_flag
154 LOAD_LISTCOMP '<code_object <listcomp>>'
156 LOAD_STR '<listcomp>'
158 MAKE_FUNCTION_0 ''
160 LOAD_NAME range
162 LOAD_CONST 6
164 CALL_FUNCTION_1 1 ''
166 GET_ITER
168 CALL_FUNCTION_1 1 ''

30 170 STORE_NAME ciphers
172 SETUP_LOOP 260 'to 260'
174 LOAD_NAME range
176 LOAD_CONST 5
178 CALL_FUNCTION_1 1 ''
180 GET_ITER
182 FOR_ITER 258 'to 258'

31 184 STORE_NAME row
186 SETUP_LOOP 256 'to 256'
188 LOAD_NAME range
190 LOAD_CONST 6
192 CALL_FUNCTION_1 1 ''
194 GET_ITER
196 FOR_ITER 254 'to 254'

32 198 STORE_NAME col
200 LOAD_NAME ciphers
202 LOAD_NAME row
204 BINARY_SUBSCR
206 LOAD_NAME col
208 DUP_TOP_TWO
210 BINARY_SUBSCR
212 LOAD_NAME ciphers
214 LOAD_NAME row
216 LOAD_CONST 1
218 BINARY_ADD
220 BINARY_SUBSCR
222 LOAD_NAME col
224 BINARY_SUBSCR
226 INPLACE_ADD
228 ROT_THREE

33 230 STORE_SUBSCR
232 LOAD_NAME ciphers
234 LOAD_NAME row
236 BINARY_SUBSCR
238 LOAD_NAME col
240 DUP_TOP_TWO
242 BINARY_SUBSCR
244 LOAD_CONST 256
246 INPLACE_MODULO
248 ROT_THREE
250 STORE_SUBSCR
252 JUMP_BACK 196 'to 196'
254 POP_BLOCK
256_0 COME_FROM_LOOP 186 '186'
256 JUMP_BACK 182 'to 182'

35 258 POP_BLOCK
260_0 COME_FROM_LOOP 172 '172'
260 LOAD_CONST b''

36 262 STORE_NAME cipher
264 SETUP_LOOP 336 'to 336'
266 LOAD_NAME range
268 LOAD_CONST 6
270 CALL_FUNCTION_1 1 ''
272 GET_ITER
274 FOR_ITER 334 'to 334'

37 276 STORE_NAME row
278 LOAD_CONST 0

38 280 STORE_NAME col
282 SETUP_LOOP 330 'to 330'
284 LOAD_NAME col
286 LOAD_CONST 6
288 COMPARE_OP <
290 POP_JUMP_IF_FALSE 328 'to 328'
294 LOAD_NAME cipher
296 LOAD_NAME bytes
298 LOAD_NAME ciphers
300 LOAD_NAME row
302 BINARY_SUBSCR
304 LOAD_NAME col
306 BINARY_SUBSCR
308 BUILD_LIST_1 1
310 CALL_FUNCTION_1 1 ''
312 INPLACE_ADD

40 314 STORE_NAME cipher
316 LOAD_NAME col
318 LOAD_CONST 1
320 INPLACE_ADD
322 STORE_NAME col
324 JUMP_BACK 284 'to 284'
328_0 COME_FROM 290 '290'
328 POP_BLOCK
330_0 COME_FROM_LOOP 282 '282'
330 JUMP_BACK 274 'to 274'

42 334 POP_BLOCK
336_0 COME_FROM_LOOP 264 '264'
336 LOAD_NAME b64encode
338 LOAD_NAME cipher
340 CALL_FUNCTION_1 1 ''

44 342 STORE_NAME cipher
344 LOAD_NAME cipher
346 LOAD_GLOBAL O0o
348 COMPARE_OP ==
350 POP_JUMP_IF_FALSE 364 'to 364'
354 LOAD_NAME print
356 LOAD_STR 'Great, this is my flag.'
358 CALL_FUNCTION_1 1 ''
360 POP_TOP

47 362 JUMP_FORWARD 372 'to 372'
364_0 COME_FROM 350 '350'
364 LOAD_NAME print
366 LOAD_STR 'Wrong flag.'
368 CALL_FUNCTION_1 1 ''
370 POP_TOP
372_0 COME_FROM 362 '362'

Parse error at or near `None' instruction at offset -1

根据以上,可还原出部分代码。

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
import os
import sys
from base64 import b64encode
O0o = b'/KDq6pvN/LLq6tzM/KXq59Oh/MTqxtOTxdrqs8OoR3V1X09J'
flag = getFlag()
if b'hgame{' != flag[:6] or flag[-1] != b'}':
print('Incorrect format!')
sys.exit(1)
raw_flag = flag[6:-1]
if len(flag) - 7 != 36:
print('Wrong length!')
sys.exit(2)
raw_flag = raw_flag[::-1]
# ciphers = 一个列表推导式
for row in range(5):
for col in range(6):
ciphers[row][col] += ciphers[row + 1][col]
ciphers[row][col] %= 256
cipher = b''
for row in range(6):
col = 0
while col < 6:
cipher += bytes([ciphers[row][col]])
col += 1
# assert O0o == b64encode(cipher)

中间的列表推导式部分无法使用uncompyle6查看,但可使用dis和marshal来反编译代码。
结合资料可知,3.7的pyc文件,头部大小为16字节,因此略过16字节,获得的字节码对象如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
>>> import dis, marshal
>>> f = open("babyPyc_task_a1f4a8cf21.cpython-37.pyc", "rb")
>>> f.read(16)
b'B\r\r\n\x00\x00\x00\x00\xdaR%^ \x04\x00\x00'
>>> code = marshal.load(f)
>>> code
<code object <module> at 0x000001E7C7F45C90, file "task.py", line 3>
>>> dis.dis(code)
3 0 JUMP_ABSOLUTE 2
>> 2 LOAD_CONST 0 (0)
4 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (os)
8 STORE_NAME 0 (os)
10 LOAD_CONST 0 (0)
12 LOAD_CONST 1 (None)
14 IMPORT_NAME 1 (sys)

4 16 STORE_NAME 1 (sys)
18 LOAD_CONST 0 (0)
20 LOAD_CONST 2 (('b64encode',))
22 IMPORT_NAME 2 (base64)
24 IMPORT_FROM 3 (b64encode)
26 STORE_NAME 3 (b64encode)

6 28 POP_TOP
30 LOAD_CONST 3 (b'/KDq6pvN/LLq6tzM/KXq59Oh/MTqxtOTxdrqs8OoR3V1X09J')

8 32 STORE_GLOBAL 4 (O0o)
34 LOAD_CONST 4 (<code object getFlag at 0x000001E7C7F23030, file "task.py", line 8>)
36 LOAD_CONST 5 ('getFlag')
38 MAKE_FUNCTION 0

16 40 STORE_NAME 5 (getFlag)
42 LOAD_NAME 5 (getFlag)
44 CALL_FUNCTION 0

18 46 STORE_NAME 6 (flag)
48 LOAD_NAME 6 (flag)
50 LOAD_CONST 1 (None)
52 LOAD_CONST 6 (6)
54 BUILD_SLICE 2
56 BINARY_SUBSCR
58 LOAD_CONST 7 (b'hgame{')
60 COMPARE_OP 3 (!=)
62 POP_JUMP_IF_TRUE 76
64 LOAD_NAME 6 (flag)
66 LOAD_CONST 8 (-1)
68 BINARY_SUBSCR
70 LOAD_CONST 9 (125)
72 COMPARE_OP 3 (!=)

19 74 POP_JUMP_IF_FALSE 94
>> 76 LOAD_NAME 7 (print)
78 LOAD_CONST 10 ('Incorrect format!')
80 CALL_FUNCTION 1

20 82 POP_TOP
84 LOAD_NAME 1 (sys)
86 LOAD_METHOD 8 (exit)
88 LOAD_CONST 11 (1)
90 CALL_METHOD 1

22 92 POP_TOP
>> 94 LOAD_NAME 6 (flag)
96 LOAD_CONST 6 (6)
98 LOAD_CONST 8 (-1)
100 BUILD_SLICE 2
102 BINARY_SUBSCR

23 104 STORE_NAME 9 (raw_flag)
106 LOAD_NAME 10 (len)
108 LOAD_NAME 6 (flag)
110 CALL_FUNCTION 1
112 LOAD_CONST 12 (7)
114 BINARY_SUBTRACT
116 LOAD_CONST 13 (36)
118 COMPARE_OP 3 (!=)

24 120 POP_JUMP_IF_FALSE 140
122 LOAD_NAME 7 (print)
124 LOAD_CONST 14 ('Wrong length!')
126 CALL_FUNCTION 1

25 128 POP_TOP
130 LOAD_NAME 1 (sys)
132 LOAD_METHOD 8 (exit)
134 LOAD_CONST 15 (2)
136 CALL_METHOD 1

27 138 POP_TOP
>> 140 LOAD_NAME 9 (raw_flag)
142 LOAD_CONST 1 (None)
144 LOAD_CONST 1 (None)
146 LOAD_CONST 8 (-1)
148 BUILD_SLICE 3
150 BINARY_SUBSCR

28 152 STORE_NAME 9 (raw_flag)
154 LOAD_CONST 16 (<code object <listcomp> at 0x000001E7C7F280C0, file "task.py", line 28>)
156 LOAD_CONST 17 ('<listcomp>')
158 MAKE_FUNCTION 0
160 LOAD_NAME 11 (range)
162 LOAD_CONST 6 (6)
164 CALL_FUNCTION 1
166 GET_ITER
168 CALL_FUNCTION 1

30 170 STORE_NAME 12 (ciphers)
172 SETUP_LOOP 86 (to 260)
174 LOAD_NAME 11 (range)
176 LOAD_CONST 18 (5)
178 CALL_FUNCTION 1
180 GET_ITER
>> 182 FOR_ITER 74 (to 258)

31 184 STORE_NAME 13 (row)
186 SETUP_LOOP 68 (to 256)
188 LOAD_NAME 11 (range)
190 LOAD_CONST 6 (6)
192 CALL_FUNCTION 1
194 GET_ITER
>> 196 FOR_ITER 56 (to 254)

32 198 STORE_NAME 14 (col)
200 LOAD_NAME 12 (ciphers)
202 LOAD_NAME 13 (row)
204 BINARY_SUBSCR
206 LOAD_NAME 14 (col)
208 DUP_TOP_TWO
210 BINARY_SUBSCR
212 LOAD_NAME 12 (ciphers)
214 LOAD_NAME 13 (row)
216 LOAD_CONST 11 (1)
218 BINARY_ADD
220 BINARY_SUBSCR
222 LOAD_NAME 14 (col)
224 BINARY_SUBSCR
226 INPLACE_ADD
228 ROT_THREE

33 230 STORE_SUBSCR
232 LOAD_NAME 12 (ciphers)
234 LOAD_NAME 13 (row)
236 BINARY_SUBSCR
238 LOAD_NAME 14 (col)
240 DUP_TOP_TWO
242 BINARY_SUBSCR
244 LOAD_CONST 19 (256)
246 INPLACE_MODULO
248 ROT_THREE
250 STORE_SUBSCR
252 JUMP_ABSOLUTE 196
>> 254 POP_BLOCK
>> 256 JUMP_ABSOLUTE 182

35 >> 258 POP_BLOCK
>> 260 LOAD_CONST 20 (b'')

36 262 STORE_NAME 15 (cipher)
264 SETUP_LOOP 70 (to 336)
266 LOAD_NAME 11 (range)
268 LOAD_CONST 6 (6)
270 CALL_FUNCTION 1
272 GET_ITER
>> 274 FOR_ITER 58 (to 334)

37 276 STORE_NAME 13 (row)
278 LOAD_CONST 0 (0)

38 280 STORE_NAME 14 (col)
282 SETUP_LOOP 46 (to 330)
>> 284 LOAD_NAME 14 (col)
286 LOAD_CONST 6 (6)
288 COMPARE_OP 0 (<)
290 EXTENDED_ARG 1

39 292 POP_JUMP_IF_FALSE 328
294 LOAD_NAME 15 (cipher)
296 LOAD_NAME 16 (bytes)
298 LOAD_NAME 12 (ciphers)
300 LOAD_NAME 13 (row)
302 BINARY_SUBSCR
304 LOAD_NAME 14 (col)
306 BINARY_SUBSCR
308 BUILD_LIST 1
310 CALL_FUNCTION 1
312 INPLACE_ADD

40 314 STORE_NAME 15 (cipher)
316 LOAD_NAME 14 (col)
318 LOAD_CONST 11 (1)
320 INPLACE_ADD
322 STORE_NAME 14 (col)
324 EXTENDED_ARG 1
326 JUMP_ABSOLUTE 284
>> 328 POP_BLOCK
>> 330 EXTENDED_ARG 1
332 JUMP_ABSOLUTE 274

42 >> 334 POP_BLOCK
>> 336 LOAD_NAME 3 (b64encode)
338 LOAD_NAME 15 (cipher)
340 CALL_FUNCTION 1

44 342 STORE_NAME 15 (cipher)
344 LOAD_NAME 15 (cipher)
346 LOAD_GLOBAL 4 (O0o)
348 COMPARE_OP 2 (==)
350 EXTENDED_ARG 1

45 352 POP_JUMP_IF_FALSE 364
354 LOAD_NAME 7 (print)
356 LOAD_CONST 21 ('Great, this is my flag.')
358 CALL_FUNCTION 1
360 POP_TOP

47 362 JUMP_FORWARD 8 (to 372)
>> 364 LOAD_NAME 7 (print)
366 LOAD_CONST 22 ('Wrong flag.')
368 CALL_FUNCTION 1
370 POP_TOP
>> 372 LOAD_CONST 1 (None)
374 RETURN_VALUE

Disassembly of <code object getFlag at 0x000001E7C7F23030, file "task.py", line 8>:
10 0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('Give me the flag')
4 CALL_FUNCTION 1
6 POP_TOP

11 8 LOAD_GLOBAL 1 (input)
10 LOAD_CONST 2 ('> ')
12 CALL_FUNCTION 1
14 STORE_FAST 0 (flag)

12 16 LOAD_FAST 0 (flag)
18 LOAD_METHOD 2 (encode)
20 CALL_METHOD 0
22 STORE_FAST 0 (flag)

13 24 LOAD_CONST 3 (b'Qn/ZgNOeWqXCoNKYceeX3NO8n7h0lL+tzrdbkM2pZ3IwZX5Q')
26 STORE_GLOBAL 3 (O0o)

14 28 LOAD_FAST 0 (flag)
30 RETURN_VALUE

Disassembly of <code object <listcomp> at 0x000001E7C7F280C0, file "task.py", line 28>:
28 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 26 (to 32)
6 STORE_DEREF 0 (col)
8 LOAD_CLOSURE 0 (col)
10 BUILD_TUPLE 1
12 LOAD_CONST 0 (<code object <listcomp> at 0x000001E7C7F28B70, file "task.py", line 28>)
14 LOAD_CONST 1 ('<listcomp>.<listcomp>')
16 MAKE_FUNCTION 8
18 LOAD_GLOBAL 0 (range)
20 LOAD_CONST 2 (6)
22 CALL_FUNCTION 1
24 GET_ITER
26 CALL_FUNCTION 1
28 LIST_APPEND 2
30 JUMP_ABSOLUTE 4
>> 32 RETURN_VALUE

Disassembly of <code object <listcomp> at 0x000001E7C7F28B70, file "task.py", line 28>:
28 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 20 (to 26)
6 STORE_FAST 1 (row)
8 LOAD_GLOBAL 0 (raw_flag)
10 LOAD_CONST 0 (6)
12 LOAD_FAST 1 (row)
14 BINARY_MULTIPLY
16 LOAD_DEREF 0 (col)
18 BINARY_ADD
20 BINARY_SUBSCR
22 LIST_APPEND 2
24 JUMP_ABSOLUTE 4
>> 26 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
import os
import sys
from base64 import b64encode
O0o = b'/KDq6pvN/LLq6tzM/KXq59Oh/MTqxtOTxdrqs8OoR3V1X09J'
flag = input()
O0o = b'Qn/ZgNOeWqXCoNKYceeX3NO8n7h0lL+tzrdbkM2pZ3IwZX5Q'
if b'hgame{' != flag[:6] or flag[-1] != b'}':
print('Incorrect format!')
sys.exit(1)
raw_flag = flag[6:-1]
if len(flag) - 7 != 36:
print('Wrong length!')
sys.exit(2)
raw_flag = raw_flag[::-1]
ciphers = [ [ raw_flag[6*j+i] for j in range(6) ] for i in range(6) ]
for row in range(5):
for col in range(6):
ciphers[row][col] += ciphers[row + 1][col]
ciphers[row][col] %= 256
cipher = b''
for row in range(6):
col = 0
while col < 6:
cipher += bytes([ciphers[row][col]])
col += 1
assert O0o == b64encode(cipher)

因此,脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from base64 import b64decode
cipher = b'Qn/ZgNOeWqXCoNKYceeX3NO8n7h0lL+tzrdbkM2pZ3IwZX5Q'
cipher = b64decode(cipher)
ciphers = [ [ cipher[j + 6*i] for j in range(6)] for i in range(6) ]
for row in range(5):
for col in range(6):
ciphers[4 - row][col] -= ciphers[5 - row][col]
ciphers[4 - row][col] %= 256
cipher = b""
for row in range(6):
col = 0
while col < 6:
cipher += bytes([ciphers[col][row]])
col += 1
cipher = cipher[::-1]
print(b"hgame{" + cipher + b"}")

Crypto

1. Verification_code

爆破就好啦

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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import string
import time
from hashlib import sha256
from socket import socket

L = string.ascii_letters+string.digits
sock = socket()
sock.connect(("47.98.192.231", 25678))
s = sock.recv(1024).split(b"\n")[0]
_hexdigest = s[-64:].decode()
sub = s[12:28]
print(sock.recv(1024))
for a in L:
for b in L:
for c in L:
for d in L:
pre = (a+b+c+d).encode()
hexstr = sha256(pre + sub).hexdigest()
if hexstr == _hexdigest:
print(pre)
sock.send(pre)
print(sock.recv(1024))
sock.recv(1024)
sock.send(b"I like playing Hgame")
print(sock.recv(1024))
print(sock.recv(1024))
exit()
  1. Remainder
    中国剩余定理就Vans啦
    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
    #!/usr/bin/env python2
    # -*- coding: utf-8 -*-
    from Crypto.Util.number import inverse

    p = 94598296305713376652540411631949434301396235111673372738276754654188267010805522542068004453137678598891335408170277601381944584279339362056579262308427544671688614923839794522671378559276784734758727213070403838632286280473450086762286706863922968723202830398266220533885129175502142533600559292388005914561
    q = 150088216417404963893679242888992998793257903343994792697939121738029477790454833496600101388493792476973514786401036309378542808470513073408894727406158296404360452232777491992630316999043165374635001806841520490997788796152678742544032835808854339130676283497122770901196468323977265095016407164510827505883
    r = 145897736096689096151704740327665176308625097484116713780050311198775607465862066406830851710261868913835866335107146242979359964945125214420821146670919741118254402096944139483988745450480989706524191669371208210272907563936516990473246615375022630708213486725809819360033470468293100926616729742277729705727
    e = 65537

    cp = 78430786011650521224561924814843614294806974988599591058915520397518526296422791089692107488534157589856611229978068659970976374971658909987299759719533519358232180721480719635602515525942678988896727128884803638257227848176298172896155463813264206982505797613067215182849559356336015634543181806296355552543
    cq = 49576356423474222188205187306884167620746479677590121213791093908977295803476203510001060180959190917276817541142411523867555147201992480220531431019627681572335103200586388519695931348304970651875582413052411224818844160945410884130575771617919149619341762325633301313732947264125576866033934018462843559419
    cr = 48131077962649497833189292637861442767562147447040134411078884485513840553188185954383330236190253388937785530658279768620213062244053151614962893628946343595642513870766877810534480536737200302699539396810545420021054225204683428522820350356470883574463849146422150244304147618195613796399010492125383322922
    m = p*q*r
    Mp = q*r
    Mq = p*r
    Mr = p*q
    dp = inverse(Mp, p)
    dq = inverse(Mq, q)
    dr = inverse(Mr, r)
    msg = (dp*Mp*cp+dq*Mq*cq+dr*Mr*cr) % m
    phim = (p-1)*(q-1)*(r-1)
    de = inverse(e, phim)
    msg = pow(msg, de, m)
    msg = hex(msg)[2:-1]
    if len(msg) % 2 == 1:
    msg = "0" + msg
    msg = msg.decode("hex")
    print(msg)
    s = ""
    for st in msg.split("\n")[3:-3]:
    s += st[:2]
    print(s)

3. Inv

求置换群的逆元,之后仿照欧几里得除法。

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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def Subs(S, X):
return bytes([ S[x] for x in X ])

def Mul(A, B):
assert len(A)==len(B)
return Subs(A, B)

def Pow(X, E):
Y = X
E = bin(E)[3:]
for e in E:
Y = Mul(Y, Y)
if e=='1':
Y = Mul(X, Y)
return Y

def Inv(G : bytes):
ans = [0] * 256
for i in range(256):
ans[G[i]] = i.to_bytes(1, "little")
return b"".join(ans)

A = b'\xc8&\xc1E\xbe*\xc5\x84\xdb1\x05\x9b\xc0\xf2\xac/\x0b0\x8d\'\xc2b\x89\x93\xa6\xcd\xe1\x1b\xf4H\xffa\x90A\xf7,(\xea?\xa8\xa0\x8b\xf1\xf9"X\n\x86fj\x074\x7fBO\xd4F\xbd\xe6\xd9\xa7\xaf\x8a\x8c\xde\xab;!PT\x15)+w\xbc\x00>\xc6g\xc3\x85=9K\xb6<\xb7x\xaeUG\x83vk\xa9\xf6{\x03Y\x87\x14e\xfd\xed@i\xcc.\xd1\xebo\x106\xe2\xe7\xd7\xeeu\x9e\xfe\x95^R\xfb8\x04\xb4S\x16\xe0\xad\xd8\x98n\xca\xe4\xdd\xd2\xc7\x99l\xb3\\2L\xa3\x1d:_\x12\xb87\x17\x01\xb1#~q\x1c\t\xe8\xdar\xef\xcb\x0c\xe5\x80\xdf\xc9y\x0e`\xe9\x94\xd0\xcfW\x1f5\xf5h\xbf\xba\x91\xb9d\xfcM\x81\xec\x88\xb2c\x9f\xa4J|\xd3m\xd6s\xd5\x92\x9d\x9a3\xa2\xb5\xfa\x19N\xa1\x82][\xf8\x06\x13\xdcC\x1e\x1a\xaa\xc4tz\x08\x8f%$D\xbb\x97 \xce\x96V\xe3\x02I\x18\x11\x0f\r\xf3p\x8e\xa5Z-\xf0}\xb0Q\x9c'
B = b'U\x17\x8aE\xa6\x19\xab\x7fd0\xd2)\xc0\xae\xcc/G_\xe3\'\r\xfb\xaf\x00\xb1hgi-\xc1\xffa\x8d\t&\x99k\x95\x93\xa8.\x07\xcd\x87\x01\xe8\x89\x86\xf6f48F\xdc\x96\xd4`P\xd6!\xfe\xc4B:\xd31C\x9f\x1dT{2c9\x0bY5#\xf7\xb8H\xe0Db\xb6wv\xe1\xbbI\x8f\x83l\x80\xa9\x04q\x03\xf0m\xf4\x1bp\x8e\xc6u\xfd\x16$\x06\xf9Z\xec\xa2\xcb\xd7V\xb9\xd1\xbdt^\xe7\xe2\xac\x18\xb4\x15=n\xad\xd8S+\xca\xeb\xdd\xd0;\x84\xe6\x08\x8c3\xb3\x90\x02\xc8}\xee\xea7K\x98\xde\x8b~\xcf\xfa\x11\n\xda\xa4L\xa3\x0cWQ\xdf\xc9yj\x9d\xe9\xfcJO\x1a\x1f\xdb\xf5M\xbf\x9e e\x1c*\x9b\x85\xe5\x88\xb2\xc7\xf2\x91\x10\x0e,\xd9<s\xd5\xef\xb0@|\xc3\xbc(\xb5"\xa1\x82\xa7[\xf8A\x13\x14\xc2\x1eN\xaao\xedr\xba\xcex]\x92\x05\x97\x12\xc5%\\\xb7>R\x9a\x94\x0fX\xf3\xbe?\xa5\xe4\xa0z\xf16\x81\x9c'
E = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
a = 595
b = 739
enc = b"\\-\xa5{\xb9\x85J @\xfa\x91\x0b\x88\r4I\x7f\xb9\xe5\r\xc0\x84\x8f\xa6\xc0i\xb0\xa4\x1b\x8fIw\x84'\xa2\xa4\x00\x91\x87\x10\r\\\x8c\x12"
a, b = b, a
A, B = B, A
q = a // b
r = a - b*q
R = B
while True:
B_ = Inv(B)
R = Mul(A, Pow(B_, q))
a, b = b, r
A, B = B, R
if b <= 1:
break
q = a // b
r = a - b*q
S = B
print(S)
flag = b""
for c in enc:
index = S.find(c)
flag += index.to_bytes(1, "little")
print(flag)

MISC

2.所见即为假

ZIP伪加密,之后F5-JPG隐写,最后出来base16,之后RAR,之后出FLAG。

作者

Uchiha Kakashi

发布于

2020-01-31

更新于

2020-05-23

许可协议