BuckeyeCTF2023
# PREFACE: 和 maple 一个时间段的比赛,似乎是大学新生赛… 感觉 比 maple 难呢…
# 或者换一种说法… 怎么大学新生赛都喜欢搞抽象呢…
# 8ball
直接动调把前面全 nop 掉拿就行: bctf{Aw_$hucK$_Y0ur3_m@k1Ng_m3_bLu$h}
# Converter
就在里面: bctf{o0ps_y0u_fOuNd_mE}
# Emotional_Damage
确实给我 damage 了,总归就是猜 emoji 代表的符号然后恢复流程逆 flag,大部分可以 gpt 一把梭
# Skribl
需要配置 docker 环境把 python313 环境搞出来,拿到 backend 字节码
# backend.pyc | |
0 0 RESUME 0 | |
1 2 LOAD_CONST 0 (0) | |
4 LOAD_CONST 1 (None) | |
6 IMPORT_NAME 0 (string) | |
8 STORE_NAME 0 (string) | |
2 10 LOAD_CONST 0 (0) | |
12 LOAD_CONST 1 (None) | |
14 IMPORT_NAME 1 (random) | |
16 STORE_NAME 1 (random) | |
3 18 LOAD_CONST 0 (0) | |
20 LOAD_CONST 1 (None) | |
22 IMPORT_NAME 2 (time) | |
24 STORE_NAME 2 (time) | |
4 26 LOAD_CONST 0 (0) | |
28 LOAD_CONST 1 (None) | |
30 IMPORT_NAME 3 (math) | |
32 STORE_NAME 3 (math) | |
5 34 LOAD_CONST 0 (0) | |
36 LOAD_CONST 1 (None) | |
38 IMPORT_NAME 4 (os) | |
40 STORE_NAME 4 (os) | |
8 42 LOAD_CONST 2 ('return') | |
44 LOAD_NAME 5 (str) | |
46 BUILD_TUPLE 2 | |
48 LOAD_CONST 3 (<code object create_skribl at 0x7f763b846970, file "/home/rene/Documents/Java/OSUCyberSecurityClub/buckeyectf23/buckeyectf-challenges/chals/rev-pycache/dist/chal/backend.py", line 8>) | |
50 MAKE_FUNCTION | |
52 SET_FUNCTION_ATTRIBUTE 4 (annotations) | |
54 STORE_NAME 6 (create_skribl) | |
18 56 LOAD_CONST 4 (<code object init_backend at 0x7f763b734670, file "/home/rene/Documents/Java/OSUCyberSecurityClub/buckeyectf23/buckeyectf-challenges/chals/rev-pycache/dist/chal/backend.py", line 18>) | |
58 MAKE_FUNCTION | |
60 STORE_NAME 7 (init_backend) | |
62 RETURN_CONST 1 (None) | |
Disassembly of <code object create_skribl at 0x7f763b846970, file "/home/rene/Documents/Java/OSUCyberSecurityClub/buckeyectf23/buckeyectf-challenges/chals/rev-pycache/dist/chal/backend.py", line 8>: | |
8 0 RESUME 0 | |
9 2 LOAD_GLOBAL 1 (print + NULL) | |
12 LOAD_CONST 1 ('Creating skribl ') | |
14 LOAD_FAST 1 (message) | |
16 FORMAT_SIMPLE | |
18 BUILD_STRING 2 | |
20 CALL 1 | |
28 POP_TOP | |
11 30 LOAD_GLOBAL 2 (string) | |
40 LOAD_ATTR 4 (ascii_lowercase) | |
60 LOAD_GLOBAL 2 (string) | |
70 LOAD_ATTR 6 (ascii_uppercase) | |
90 BINARY_OP 0 (+) | |
94 LOAD_GLOBAL 2 (string) | |
104 LOAD_ATTR 8 (digits) | |
124 BINARY_OP 0 (+) | |
128 STORE_FAST 3 (alphabet) | |
12 130 LOAD_GLOBAL 11 (range + NULL) | |
140 LOAD_CONST 2 (40) | |
142 CALL 1 | |
150 GET_ITER | |
152 LOAD_FAST_AND_CLEAR 4 (i) | |
154 SWAP 2 | |
156 BUILD_LIST 0 | |
158 SWAP 2 | |
>> 160 FOR_ITER 25 (to 214) | |
164 STORE_FAST 4 (i) | |
166 LOAD_GLOBAL 12 (random) | |
176 LOAD_ATTR 14 (choice) | |
196 PUSH_NULL | |
198 LOAD_FAST 3 (alphabet) | |
200 CALL 1 | |
208 LIST_APPEND 2 | |
210 JUMP_BACKWARD 27 (to 160) | |
>> 214 END_FOR | |
216 STORE_FAST 5 (key_list) | |
218 STORE_FAST 4 (i) | |
14 220 LOAD_CONST 3 ('') | |
222 LOAD_ATTR 17 (join + NULL|self) | |
242 LOAD_FAST 5 (key_list) | |
244 CALL 1 | |
252 STORE_FAST 6 (key) | |
15 254 LOAD_FAST_LOAD_FAST 18 (message, author) | |
256 BUILD_TUPLE 2 | |
258 LOAD_FAST_LOAD_FAST 6 (skribls, key) | |
260 STORE_SUBSCR | |
16 264 LOAD_FAST 6 (key) | |
266 RETURN_VALUE | |
None >> 268 SWAP 2 | |
270 POP_TOP | |
12 272 SWAP 2 | |
274 STORE_FAST 4 (i) | |
276 RERAISE 0 | |
ExceptionTable: | |
156 to 214 -> 268 [2] | |
Disassembly of <code object init_backend at 0x7f763b734670, file "/home/rene/Documents/Java/OSUCyberSecurityClub/buckeyectf23/buckeyectf-challenges/chals/rev-pycache/dist/chal/backend.py", line 18>: | |
18 0 RESUME 0 | |
19 2 LOAD_GLOBAL 0 (random) | |
12 LOAD_ATTR 2 (seed) | |
32 PUSH_NULL | |
34 LOAD_GLOBAL 4 (math) | |
44 LOAD_ATTR 6 (floor) | |
64 PUSH_NULL | |
66 LOAD_GLOBAL 8 (time) | |
76 LOAD_ATTR 8 (time) | |
96 PUSH_NULL | |
98 CALL 0 | |
106 CALL 1 | |
114 CALL 1 | |
122 POP_TOP | |
21 124 LOAD_GLOBAL 11 (create_skribl + NULL) | |
134 LOAD_FAST 0 (skribls) | |
136 LOAD_GLOBAL 12 (os) | |
146 LOAD_ATTR 14 (environ) | |
166 LOAD_CONST 1 ('FLAG') | |
168 BINARY_SUBSCR | |
172 LOAD_CONST 2 ('rene') | |
174 CALL 3 | |
182 POP_TOP | |
184 RETURN_CONST 0 (None) |
这里的字节码简单手动反编译一下
import string | |
import random | |
import time | |
import math | |
import os | |
def create_skribl(skribls, message, author) -> str: | |
print (f'Creating skribl {message}') | |
alphabet = string.ascii_lowercase + string.ascii_uppercase + string.digits | |
key_list = [random.choice(alphabet) for i in range(40)] | |
key = ''.join(key_list) | |
skribls[key] = (message, author) | |
return key | |
def init_backend(skribls): | |
random.seed(math.floor(time.time())) | |
create_skribl(skribls, os.environ['FLAG'], 'rene') |
结合前面的代码,可以看到生成的四十个随机串有一个 seed,是可以获取的(当前时间 - 网页持续时间,可以拿到这个环境的创建时间,flag 是环境创建后立刻从环境变量中提取并写入的,所以可以直接获得 key)
使用 key 访问 view api 即可
import string | |
import random | |
import time | |
import math | |
import os | |
import re | |
import requests | |
a = re.findall("duration\((\d+)",requests.get("https://skribl.chall.pwnoh.io/").text) | |
b = math.floor(time.time()) | |
random.seed(math.floor(int(a[0]) - b)) | |
alphabet = string.ascii_lowercase + string.ascii_uppercase + string.digits | |
key_list = [random.choice(alphabet) for i in range(40)] | |
key = ''.join(key_list) | |
url = 'https://skribl.chall.pwnoh.io/view/' + key | |
response = requests.get(url) | |
lines = response.text.split('\n') | |
for line in lines: | |
if 'bctf{' in line: | |
print(line) | |
break | |
# <p>bctf{wHy_d0_w3_Ne3d_s0_m@ny_N0T3$_aNyW@y}</p> |