CTF_WPs 帕鲁杯 第二届 “Parloo” CTF 应急响应挑战赛 Aristore 2025-05-18 2025-05-19 Misc 量子迷宫 Challenge 未来量子实验室的 AI 将机密数据加密成了量子迷宫,每一行代表一个量子比特操作。只有通过逆向坍缩观测,才能还原出被量子噪声掩盖的密钥。实验室遗留的日志文件似乎隐藏着关键线索(flag 格式:palu {32 位 md5})
Solution
提取出 QUBIT | 后面的字符(索引为 6)并连接 -> 二进制转字符(字节长度为 8)
1 2 3 4 5 6 7 8 9 10 11 12 data = """ QUBIT|0⟩ → X Gate QUBIT|1⟩ → Y Gate PHOTON: 2492° QUBIT|1⟩ → X Gate ... """ bits = '' .join([line[6 ] for line in data.splitlines() if len (line) > 6 ]) for i in range (0 , len (bits), 8 ): chunk = bits[i:i+8 ] char = chr (int (chunk, 2 )) print (char,end="" )
1 palu{aea437c12b149750383fe56727ec5344}
时间折叠 Challenge 某服务器系统日志中发现异常的时间戳记录,所有时间均显示为 "1970-01-01 08:00:00"。技术员发现日志中存在与时间无关的二进制干扰信号,你能从被折叠的时空中找到隐藏的 flag 吗?
Solution 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 data = """ [1970-01-01 08:00:00] System boot sequence initiated [1970-01-01 08:00:00] SYSTEM ALERT: Time anomaly detected at 00000000fe ns [1970-01-01 08:00:00] SYSTEM ALERT: Time anomaly detected at 10000000ef ns ... [1970-01-01 08:00:00] SYSTEM ALERT: Time anomaly detected at 380000000f3 ns [1970-01-01 08:00:00] System entering chronostasis mode """ result = ' ' .join([line[-5 :-3 ] for line in data.splitlines() if len (line) > 60 ]) byte_data = bytes .fromhex(result) def xor_decrypt (data, key ): return bytes ([b ^ key for b in data]) for key in range (256 ): decrypted_data = xor_decrypt(byte_data, key) try : decrypted_string = decrypted_data.decode('utf-8' ) if decrypted_string.startswith("palu" ): print (f"找到匹配的密钥: {key} " ) print ("还原的目标字符串:" , decrypted_string) break except UnicodeDecodeError: continue else : print ("未找到以 'palu' 开头的字符串" )
XOR 解密,爆破得到密钥为 142
1 palu{This_is_A_Sample_Flag_Change_Me!!}
TopSecret Challenge 你从某机密设施偷取了一份文件,但你被发现了,最后只收到一份乱码,你能从中提取到有用的信息吗?
Solution 看着就像 base64,直接搜 cGFsd
cGFsdXtZb3VfcmVfYV9yZWFsXzUwd30=
复制下来拿去解码
screenshot Challenge 有个笨比截图 flag 的时候不小心发到群里了,细心和反回撤的群友已经偷偷记录下来了
Solution 苹果手机的无效打码还挺有名的,改一下曝光亮度那些就能出
不过因为我懒得调参数所以就用 StegSolve 了
几何闪烁的秘密 Challenge 我们找到了一张神秘的 GIF 图片,里面似乎隐藏着重要信息。仔细观察,你会发现四个几何体在不同时刻闪现出一些奇怪的字符。你能从中提取出完整的 Flag 吗?
Solution 在蓝色圆圈发现 flag 头经过 base64 编码后的结果 cGFsd
分别提取图片里的字母
圆形:cGFsXttcFsdXtcGFdXtt
方形:YXN0XJfYN0ZXfYXNZXJf
三角形:b2Zf2VvbZfZ2vb2ZZ2Vv
五边形:bWV0nl9bV0cn9bWVcnl9
这里拿圆形举例
cGFsXttcFsdXtcGFdXtt ->
cGFsXtt cFsdXt cGFdXtt ->
求同存异得到 cGFsdXtt
同理得到其他几个图形对应的字符串,拼接得到 cGFsdXttYXN0ZXJfb2ZfZ2VvbWV0cnl9
解码得到 flag
1 palu{master_of_geometry}
dorodoro Challenge Solution
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 import requestsurl = "http://challenge.qsnctf.com:31868/check" data_template = { "part1" : "" , "part2" : "" , "part3" : "" , "part4" : "" } def orange (part ): for n in range (1 , 100 ): data_template[f"part{part} " ] = "哦润吉" * n response = requests.post(url, json=data_template) result = response.json() if result.get("feedback" , {}).get(f"part{part} " ) == True : print (f"[*] 找到了正确的 part{part} 值!" ) print (data_template[f'part{part} ' ]) return result print (orange(4 ))
时间循环的信使 Challenge 某神秘组织通过时间循环传递加密信息,我们在捕获的流量日志中发现异常时间戳。日志文件显示:“在错误的时间做正确的事,在正确的时间解开谜题”,flag 格式为 palu
Solution 先把附件丢给 AI 让它帮忙按时间从小到大排序,然后手动清理数据,只留下循环的
然后把循环的数字拼起来(这里的操作是取每行的最后一个字符)
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 data = """ 1745396077|77777777 1745396138|00000000 1745396199|66666666 1745396260|11111111 1745396321|66666666 1745396382|cccccccc 1745396443|77777777 1745396504|55555555 1745396565|77777777 1745396626|bbbbbbbb 1745396687|55555555 1745396748|44444444 1745396809|66666666 1745396870|99999999 1745396931|66666666 1745396992|dddddddd 1745397053|66666666 1745397114|55555555 1745397175|55555555 1745397236|ffffffff 1745397297|33333333 1745397358|11111111 1745397419|77777777 1745397480|33333333 1745397541|55555555 1745397602|ffffffff 1745397663|66666666 1745397724|33333333 1745397785|77777777 1745397846|99999999 1745397907|66666666 1745397968|33333333 1745398029|66666666 1745398090|cccccccc 1745398151|33333333 1745398212|11111111 1745398273|66666666 1745398334|33333333 1745398395|44444444 1745398456|00000000 1745398517|66666666 1745398578|cccccccc 1745398639|55555555 1745398700|ffffffff 1745398761|33333333 1745398822|00000000 1745398883|77777777 1745398944|88888888 1745399005|77777777 1745399066|dddddddd """ last_chars = [line[-1 ] for line in data.splitlines() if line] print ('' .join(last_chars))
拼起来得到 70616c757b54696d655f31735f6379636c3163406c5f30787d
,拿去 CyberChef 十六进制转字符串
1 palu{Time_1s_cycl1c@l_0x}
时间交织的密语 Challenge 我们在暗网服务器中发现了一个神秘文件,据说是某个黑客组织的「时空密钥」,文件内容似乎由大量时间戳构成。情报显示,只有将时间维度与二进制低语结合才能解开秘密。线索隐藏在时空的起点与终点之间。
Solution “文件内容似乎由大量时间戳构成” 提示了要把十六进制转为十进制得到时间戳
“将时间维度与二进制低语结合” 提示了要取时间戳的最后两位
“线索隐藏在时空的起点与终点之间” 提示了最终解出来的结果要把第一个和最后一个字符去除,保留中间的部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import structwith open ("timestream.bin" , 'rb' ) as f: data = f.read() hex_result = '' for i in range (0 , len (data), 4 ): chunk = data[i:i+4 ] timestamp, = struct.unpack('>I' , chunk) hex_digit = format (timestamp % 100 , 'x' ) hex_result += hex_digit flag = bytes .fromhex(hex_result[1 :-1 ]).decode('utf-8' ) print (flag)
1 palu{Time_1s_B1nary_Whisper}
最弱帕鲁 Challenge 刚学习网络安全的帕鲁下班回来天塌了,自己珍藏的文件居然忘记了密码!不对… 知道密码也没用啊!
Solution jsteg 隐写,工具下载 lukechampine/jsteg
jsteg.exe reveal 弱帕鲁.jpg SuperPassw0rdNeverGuess
得到解压密码 SuperPassw0rdNeverGuess
Web CatBank Challenge 🐱 欢迎光临猫猫银行!一家由 喵星人 运营的银行!你励志要 赚一百万,但…… 这家银行的代码是猫爪写的 🐾💻,好像有漏洞?猫猫银行最近有网络波动 在被未知势力攻击!!!
Solution 先注册两个号,就分别叫 1 和 2 吧
登录账号 2 给 1 转账 0.01 元
抓包找到这条记录,修改金额后重新发送(金额要大于等于一百万)
然后登录账号 1,此时给任意一个用户转账一百万就会显示 flag
1 palu{4e730efb2ca3433e806f150c53f4bfa2}
Reverse PosltionalXOR Chall qcoqVh{e bccocH^@Lgt{gt|g
Solution 根据加密算法分析,每个字符的加密密钥为其在字符串中的位置索引加 1。因此,解密时需将每个密文字符与其位置索引加 1 后的值进行异或运算。
1 2 3 4 5 6 7 8 9 ciphertext = "qcoq~Vh{e~bccocH^@Lgt{gt|g" transformed = [] for idx, char in enumerate (ciphertext): position = idx + 1 original_ascii = ord (char) new_ascii = original_ascii ^ position transformed_char = chr (new_ascii) transformed.append(transformed_char) print ('' .join(transformed))
1 palu{PosltionalXOR_sample}
PaluFlat Challenge 帕鲁不是死肥宅,帕鲁不胖!帕鲁头晕目眩绝对不是炫多了!
Solution 用 010editor 打开附件发现是 7z 压缩包,改后缀解压后用 IDA 分析。
我们通过静态分析发现,函数的大致流程如下:
对于每个字符 a1[i]
:
使用 "flat"
或 "palu"
中的一个字符串循环异或:
1 2 char key = flat_or_palu[i % len];char tmp = a1[i] ^ key;
对异或后的 tmp
做一些变换:
可能是 nibble swap(交换高低 4 位) 可能减去 85 可能按位取反 这些操作根据 n12345
的比特位动态选择。
不过,由于 n12345 = 12345
是固定的,因此每一步的操作是固定的。
既然整个过程是确定性的,我们可以直接暴力枚举所有可能的 ASCII 字符,找到经过 sub_401550 () 后等于 v5 [i] 的字符即可。
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 def encrypt_char (c, index ): key_str = "flat" if (index & 1 ) else "palu" key = key_str[index % len (key_str)] tmp = c ^ ord (key) tmp = ((tmp << 4 ) & 0xF0 ) | ((tmp >> 4 ) & 0x0F ) tmp -= 85 tmp = ~tmp & 0xFF return tmp v5 = [ 84 , -124 , 84 , 68 , -92 , -78 , -124 , 84 , 98 , 50 , -113 , 84 , 98 , -78 , 84 , 3 , 20 , -128 , 67 , 19 ] v5_bytes = [b & 0xFF for b in v5] flag = '' for i in range (len (v5_bytes)): target = v5_bytes[i] found = False for c in range (32 , 127 ): if encrypt_char(c, i) == target: flag += chr (c) found = True break if not found: flag += '?' print (flag)