这道来自BUUCTF [SWPU2019]的二维码迷宫题目,堪称CTF隐写类题目的经典之作。初次接触时,我完全没想到一个看似简单的二维码背后竟隐藏着如此复杂的通关路径。题目给出的初始线索是一张名为BitcoinPay.png的图片,表面上看只是个普通二维码,但实际暗藏玄机。
作为CTF老手,我习惯性地先用QR research工具扫描了这个二维码,结果得到了"swpuctf{flag_is_not_here}"的提示。这种"此地无银三百两"的提示反而激起了我的兴趣,因为经验告诉我,真正的flag往往就藏在最显眼的地方背后。果然,接下来的分析验证了我的猜想。
当常规扫描无果后,我立即转向更专业的工具——010 Editor和binwalk。在Kali Linux环境下运行binwalk检测后,发现了四个rar压缩包隐藏在图片中:
bash复制binwalk -e BitcoinPay.png
# 如果遇到权限问题可以尝试
binwalk -e BitcoinPay.png --run-as=root
这里有个小技巧:binwalk的-e参数会自动提取发现的文件,但有时会因为权限问题失败。加上--run-as=root参数通常能解决问题。解压后得到了encode.txt、flag.doc、flag.jpg以及一个需要密码的rar压缩包。
面对多个文件,我决定先处理不需要密码的部分。encode.txt文件内容看似是Base64编码:
code复制YXNkZmdoamtsMTIzNDU2Nzg5MA==
使用在线Base64解码工具轻松得到明文"asdfghjkl1234567890"。但flag.doc文件就没这么简单了,打开后发现它包含多层Base64编码,需要循环解密。
最初我尝试手动复制粘贴解密,但很快就发现这是个无底洞。于是改用Python脚本自动化处理:
python复制import re
from base64 import b64decode
def process_data(data):
try:
data = re.sub(r'flag|[一-龥]', '', data)
decoded_data = b64decode(data)
return decoded_data.decode(), True
except:
return data, False
with open('flag.txt', 'r', encoding='utf-8') as file:
data = file.read()
iterations = 0
while True:
data, can_decode = process_data(data)
iterations += 1
if not can_decode:
print("最终结果:", data)
print("循环次数:", iterations)
break
这个脚本的关键在于:
最终解密得到字符串"comEON_YOuAreSOSoS0great"。
用之前得到的两个字符串"asdfghjkl1234567890"和"comEON_YOuAreSOSoS0great"尝试解压加密的rar文件,成功获取good.mp3音频文件和另一张flag.jpg图片。
将good.mp3导入Audacity后,放大波形可以看到明显的长短脉冲组合。这些脉冲分组呈现规律性,极可能是莫尔斯电码。通过观察波形特征,我将其转换为莫尔斯码:
code复制-- --- .-. ... . .. ... ...- . .-. -.-- ...- . .-. -.-- . .- ... -.--
使用在线莫尔斯解码器转换后得到"morseisveryveryeasy"。这里有个细节需要注意:题目要求将结果转换为小写后作为flag提交。最终的flag格式为:
code复制flag{morseisveryveryeasy}
这道题目综合考察了多种CTF技能:二维码分析、文件隐写、Base64多层编码、密码破解、音频隐写和莫尔斯电码。在实际比赛中,这类"套娃"式题目很常见,解题时需要保持耐心,逐步深入。
几个关键技巧值得注意:
这道题最精彩的部分在于它将多种隐写技术有机串联,每一步的解密都为下一步提供线索,最终构成一个完整的解题链条。这种设计既考验选手的技术广度,也测试解题的系统性思维。