GeekGame2020_部分wp
写在前面
这次比赛过程还是很愉快的,没有撕逼,问题也少,感觉比同时间其他几个比赛正规多了,里面不少题也很有意思,感谢辛苦出题的师傅们。我个人感觉涨知识了的题就写下这篇wp,作为记录。
Reverse
PY交易
相关知识:python字节码指令集,python dis模块
题目描述:众里寻他千百度,PUPU扫描器还是没找到。 作者APU发了一道暗语文本,你知道他在说什么吗?读懂暗语就可以找作者PY下载地址了。
题目下载链接:https://lanzous.com/icx4gbg
其实这一题难度不高,但是因为没有合适的工具很费时间。先看pypypypypy.txt:
1 0 LOAD_NAME 0 (input)
2 LOAD_CONST 0 ('please your flag:')
4 CALL_FUNCTION 1
6 STORE_NAME 1 (inputs)
2 8 LOAD_NAME 1 (inputs)
10 LOAD_CONST 1 (7)
12 LOAD_CONST 18 (-1)
14 BUILD_SLICE 2
16 BINARY_SUBSCR
18 STORE_NAME 1 (inputs)
3 20 LOAD_CONST 3 ('th31_scuctf_eXclus1v3')
22 STORE_NAME 2 (flag)
4 24 LOAD_CONST 4 ('')
26 STORE_NAME 3 (theflag)
5 28 LOAD_CONST 5 (0)
30 STORE_NAME 4 (i)
6 32 LOAD_CONST 5 (0)
34 STORE_NAME 5 (j)
7 36 LOAD_NAME 6 (print)
38 LOAD_NAME 2 (flag)
40 LOAD_CONST 5 (0)
42 BINARY_SUBSCR
44 CALL_FUNCTION 1
46 POP_TOP
8 48 LOAD_NAME 7 (len)
50 LOAD_NAME 2 (flag)
52 CALL_FUNCTION 1
54 LOAD_NAME 7 (len)
56 LOAD_NAME 1 (inputs)
58 CALL_FUNCTION 1
60 COMPARE_OP 3 (!=)
62 POP_JUMP_IF_FALSE 72
9 64 LOAD_NAME 6 (print)
66 LOAD_CONST 6 ('Error!')
68 CALL_FUNCTION 1
70 POP_TOP
10 >> 72 SETUP_LOOP 62 (to 136)
74 LOAD_NAME 8 (range)
76 LOAD_CONST 5 (0)
78 LOAD_NAME 7 (len)
80 LOAD_NAME 2 (flag)
82 CALL_FUNCTION 1
84 LOAD_CONST 7 (14)
86 BINARY_SUBTRACT
88 CALL_FUNCTION 2
90 GET_ITER
>> 92 FOR_ITER 40 (to 134)
94 STORE_NAME 4 (i)
11 96 LOAD_NAME 3 (theflag)
98 LOAD_NAME 9 (chr)
100 LOAD_NAME 10 (ord)
102 LOAD_NAME 2 (flag)
104 LOAD_NAME 4 (i)
106 BINARY_SUBSCR
108 CALL_FUNCTION 1
110 LOAD_NAME 10 (ord)
112 LOAD_NAME 1 (inputs)
114 LOAD_NAME 4 (i)
116 LOAD_CONST 8 (8)
118 BINARY_ADD
120 BINARY_SUBSCR
122 CALL_FUNCTION 1
124 BINARY_ADD
126 CALL_FUNCTION 1
128 INPLACE_ADD
130 STORE_NAME 3 (theflag)
132 JUMP_ABSOLUTE 92
>> 134 POP_BLOCK
12 >> 136 SETUP_LOOP 70 (to 208)
138 LOAD_NAME 8 (range)
140 LOAD_CONST 9 (10)
142 LOAD_NAME 7 (len)
144 LOAD_NAME 2 (flag)
146 CALL_FUNCTION 1
148 LOAD_CONST 10 (6)
150 BINARY_SUBTRACT
152 CALL_FUNCTION 2
154 GET_ITER
>> 156 FOR_ITER 48 (to 206)
158 STORE_NAME 4 (i)
13 160 LOAD_NAME 3 (theflag)
162 LOAD_NAME 9 (chr)
164 LOAD_NAME 10 (ord)
166 LOAD_NAME 2 (flag)
168 LOAD_NAME 4 (i)
170 BINARY_SUBSCR
172 CALL_FUNCTION 1
174 LOAD_NAME 10 (ord)
176 LOAD_NAME 1 (inputs)
178 LOAD_NAME 4 (i)
180 LOAD_CONST 8 (8)
182 BINARY_SUBTRACT
184 BINARY_SUBSCR
186 CALL_FUNCTION 1
188 BINARY_ADD
190 CALL_FUNCTION 1
192 INPLACE_ADD
194 STORE_NAME 3 (theflag)
14 196 LOAD_NAME 4 (i)
198 LOAD_CONST 2 (1)
200 BINARY_ADD
202 STORE_NAME 5 (j)
204 JUMP_ABSOLUTE 156
>> 206 POP_BLOCK
15 >> 208 SETUP_LOOP 58 (to 268)
210 LOAD_NAME 8 (range)
212 LOAD_NAME 5 (j)
214 LOAD_NAME 7 (len)
216 LOAD_NAME 2 (flag)
218 CALL_FUNCTION 1
220 CALL_FUNCTION 2
222 GET_ITER
>> 224 FOR_ITER 40 (to 266)
226 STORE_NAME 4 (i)
16 228 LOAD_NAME 3 (theflag)
230 LOAD_NAME 9 (chr)
232 LOAD_NAME 10 (ord)
234 LOAD_NAME 2 (flag)
236 LOAD_NAME 4 (i)
238 LOAD_CONST 11 (3)
240 BINARY_SUBTRACT
242 BINARY_SUBSCR
244 CALL_FUNCTION 1
246 LOAD_NAME 10 (ord)
248 LOAD_NAME 1 (inputs)
250 LOAD_NAME 4 (i)
252 BINARY_SUBSCR
254 CALL_FUNCTION 1
256 BINARY_ADD
258 CALL_FUNCTION 1
260 INPLACE_ADD
262 STORE_NAME 3 (theflag)
264 JUMP_ABSOLUTE 224
>> 266 POP_BLOCK
17 >> 268 LOAD_NAME 11 (list)
270 LOAD_NAME 3 (theflag)
272 CALL_FUNCTION 1
274 STORE_NAME 12 (flags)
18 276 SETUP_LOOP 52 (to 330)
278 LOAD_NAME 8 (range)
280 LOAD_CONST 5 (0)
282 LOAD_NAME 7 (len)
284 LOAD_NAME 12 (flags)
286 CALL_FUNCTION 1
288 LOAD_CONST 12 (2)
290 BINARY_FLOOR_DIVIDE
292 CALL_FUNCTION 2
294 GET_ITER
>> 296 FOR_ITER 30 (to 328)
298 STORE_NAME 4 (i)
19 300 LOAD_NAME 9 (chr)
302 LOAD_NAME 10 (ord)
304 LOAD_NAME 12 (flags)
306 LOAD_NAME 4 (i)
308 BINARY_SUBSCR
310 CALL_FUNCTION 1
312 LOAD_CONST 13 (20)
314 BINARY_ADD
316 CALL_FUNCTION 1
318 LOAD_NAME 12 (flags)
320 LOAD_NAME 4 (i)
322 STORE_SUBSCR
324 EXTENDED_ARG 1
326 JUMP_ABSOLUTE 296
>> 328 POP_BLOCK
22 >> 330 LOAD_NAME 12 (flags)
332 LOAD_NAME 7 (len)
334 LOAD_NAME 12 (flags)
336 CALL_FUNCTION 1
338 LOAD_CONST 12 (2)
340 BINARY_FLOOR_DIVIDE
342 LOAD_NAME 7 (len)
344 LOAD_NAME 12 (flags)
346 CALL_FUNCTION 1
348 BUILD_SLICE 2
350 BINARY_SUBSCR
352 STORE_NAME 13 (flagt)
23 354 LOAD_CONST 4 ('')
356 LOAD_ATTR 14 (join)
358 LOAD_NAME 13 (flagt)
360 CALL_FUNCTION 1
362 STORE_NAME 3 (theflag)
24 364 SETUP_LOOP 46 (to 412)
366 LOAD_NAME 8 (range)
368 LOAD_CONST 5 (0)
370 LOAD_NAME 7 (len)
372 LOAD_NAME 12 (flags)
374 CALL_FUNCTION 1
376 LOAD_CONST 12 (2)
378 BINARY_FLOOR_DIVIDE
380 CALL_FUNCTION 2
382 GET_ITER
>> 384 FOR_ITER 24 (to 410)
386 STORE_NAME 15 (k)
25 388 LOAD_NAME 3 (theflag)
390 LOAD_CONST 4 ('')
392 LOAD_ATTR 14 (join)
394 LOAD_NAME 12 (flags)
396 LOAD_NAME 15 (k)
398 BINARY_SUBSCR
400 CALL_FUNCTION 1
402 INPLACE_ADD
404 STORE_NAME 3 (theflag)
406 EXTENDED_ARG 1
408 JUMP_ABSOLUTE 384
>> 410 POP_BLOCK
26 >> 412 LOAD_NAME 3 (theflag)
414 LOAD_CONST 14 ('×x8bÙÍx8cÓÜî¤ú±¬¤¤úÖíÒ')
416 COMPARE_OP 2 (==)
418 EXTENDED_ARG 1
420 POP_JUMP_IF_FALSE 432
27 422 LOAD_NAME 6 (print)
424 LOAD_CONST 15 ('You win!')
426 CALL_FUNCTION 1
428 POP_TOP
430 JUMP_FORWARD 8 (to 440)
29 >> 432 LOAD_NAME 6 (print)
434 LOAD_CONST 16 ('Error!!!')
436 CALL_FUNCTION 1
438 POP_TOP
>> 440 LOAD_CONST 17 (None)
442 RETURN_VALUE
### The first character of flag is ‘d’, the second character is ‘1’, and the eighth character is ‘3’.
### scuctf{}
这里涉及到python字节码的知识,其结构是这样的:
源码行号 | 指令在函数中的偏移 | 指令符号 | 指令参数 | 实际参数值
以及这种字节码是可以用以下指令获取:
'python3 -m dis xxx.py'
知道这两点,我们就不难还原出来pypypypypy.py
inputs = input('please your flag:')
inputs = inputs[7:-1]
flag = 'th31_scuctf_eXclus1v3'#21
theflag = ''
i=0
j=0
print(flag[0])
if len(flag)!=len(inputs):
print('Error!')
for i in range(0,len(flag)-14):#0,7 #7 0-6
theflag += chr(ord(flag[i])+ord(inputs[i+8]))
for i in range(10,len(flag)-6):#10,15 #5 7-11
theflag += chr(ord(flag[i])+ord(inputs[i-8]))
j=i+1
for i in range(j,len(flag)):#15,21 #6 12-17
theflag += chr(ord(flag[i-3])+ord(inputs[i]))
flags = list(theflag)#18
for i in range(0,len(flags)//2):#0,9 #9
flags[i] = chr(ord(flags[i])+20)
flagt = flags[len(flags)//2:len(flags)]#9,18 #9
theflag = ''.join(flagt)#9
for k in range(0,len(flags)//2):#0,9 #9
theflag = theflag + ''.join(flags[k])#9+9=19
if theflag == '×x8bÙÍx8cÓÜî¤ú±¬¤¤úÖíÒ':#18
print('You win!')
else:
print('Error!!!')
这一步又一个小坑,在调用join的时候,他写的是LOAD_ATTR......CALL_FUNCTION ,但是python3.7实测是LOAD_METHOD......CALL_METHOD
得到pypypypypy.py以后,我们就可以写逆过程脚本了。pypypypypy-slove.py内容如下:
theflag = '×x8bÙÍx8cÓÜî¤ú±¬¤¤úÖíÒ'
flag = 'th31_scuctf_eXclus1v3'
inputs=['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0']
flagt = theflag[9:18]#9,18 #9
flags = ''.join(flagt)#9
for k in range(0,9):#0,9 #9
flags = flags + ''.join(theflag[k])#9+9=19
flags = list(flags)
for i in range(0,9):#0,9 #9
flags[i] = chr(ord(flags[i])-20)
flags = ''.join(flags)
theflag = list(flags)
for i in range(15,21):#15,21 #6 15-20
inputs[i] = chr(ord(theflag[i-3])-ord(flag[i-3]))
for i in range(10,15):#10,15 #5 2-6
inputs[i-8] = chr(ord(theflag[i-3])-ord(flag[i]))
for i in range(0,7):#0,7 #7 8-14
inputs[i+8] = chr(ord(theflag[i])-ord(flag[i]))
inputs[0]='d'#这里三位在pypypypypy.txt里面提到了
inputs[1]='1'
inputs[7]='3'
print(''.join(inputs))
脚本写的很乱,但是因为时间原因就没再改了。脚本还原出来是
d1s_r3v3r5e_1s_h4ppy1
参考链接:https://www.cnblogs.com/fortwo/archive/2013/05/13/3076780.html
Crypto
自创觅马
题目描述:自创觅马就是这么简单 flag{}
题目下载链接:https://geekgame.scuctf.com/files/a3e8ec1f6dc5da065bab4523af60c596/encrypt.py
相关知识:仿射变换密码解密
下载附件,是一个很简单的加密脚本:
def c2i(c):
return ord(c)-ord('a')
def i2c(i):
return chr(i+ord('a'))
def affine(x):
return (5 *x +8)%26
flag = input()
assert(flag.startswith('flag'))
result = "".join([i2c(affine(c2i(i))) for i in flag ] )
print(result)
encrypt = "hlimiuaxhiurxhefwxehyiatumx"
if (encrypt == result):
print("correct!")
else:
print("wrong!")
这道题也是要写逆过程,其难点就在于affine函数的仿射变换:
c = Ea,b(m) ≡ a, + b(mod 26)#仿射加密
m = Da,b(c) ≡ a^-1(c - b)(mod 26)#仿射解密
这里我们要先求a^-1,也就是逆元:
def get(a, b):
k = a //b
remainder = a % b
x1, y1 = get(b, remainder)
x, y =y1, x1 - k * y1
return x, y
a = input("a=")
b = input("b=")
a,b = get(a,b)
ny = x%y
print(ny)
然后写解密脚本:
def c2i(c):
return ord(c)-ord('a')
def i2c(i):
return chr(i+ord('a'))
def reaffine(x):
return 21*(x-8)%26
result = "hlimiuaxhiurxhefwxehyiatumx"
flag = "".join([i2c(deaffine(c2i(i))) for i in result])
print(flag)
参考链接:https://blog.csdn.net/x_yhy/article/details/83756908
MISC
假的签到
题目描述:来签到,建议MineCraft版本1.12.2,版本错误可能字加载不出来,不会真有人手动敲砖吧,不会吧不会吧。
题目下载链接:https://geekgame.scuctf.com/files/aa3a88257fb57d6b99c1e20a8094ab23/signup.zip
相关知识:minecraft1.12指令或McEdit或minecraft透视技巧或minecraft相关功能模组
其实这题解法真的很多,范围也不大,不超过15格,没什么好说。最近比赛minecraft的题还蛮常见的。(不会真有人还没玩过minecraft吧,不会吧不会吧。)