PIZZA-CTF 赛后分析&复盘#
原帖子链接:https://www.nodeseek.com/post-625709-1
运用到的关卡(在对应level运用到的)#
不排序
一、正式关卡(levels/)#
Level 1:SSTV 慢扫描电视 ★☆☆☆☆#
分发文件: level1_sstv.wav
出题原理:
SSTV(Slow Scan Television)是业余无线电爱好者用来通过音频信道传输静态图像的技术。本关使用 Robot36 格式——一种将彩色图像编码为音频信号的协议。图像的每一行被转换为一系列频率在 1500–2300Hz 之间变化的音调,其中频率的高低对应像素的亮度。
生成过程:
- 创建一张 320×256 的图片,上面写有密钥文字
- 将图片转为 YCrCb 色彩空间
- 按 Robot36 规范逐行扫描:先发送 VIS 码标识格式,然后每行由同步脉冲(1200Hz)+ 亮度扫描(88ms)+ 色度扫描(44ms)组成
- 使用连续相位正弦波生成,避免频率切换时的爆音
解题思路:
- 直接用手机 APP "Robot36" 对着扬声器播放即可解码出图片
- 也可使用 PC 端的 RX-SSTV 或 MMSSTV
- 图片上直接显示密钥
Level 2:摩尔斯电码 ★★☆☆☆#
分发文件: level2_morse.wav
出题原理:
最经典的电子通信编码。每个字母/数字对应一组"点"(短音)和"划"(长音)的组合,不同符号之间有固定的时间间隔规则:
- 点(dit):1 单位时长
- 划(dah):3 单位时长
- 符号内间隔:1 单位
- 字符间间隔:3 单位
- 单词间间隔:7 单位
生成过程:
以 12 WPM(每分钟 12 个单词)的速度,将密钥每个字符查表转为点划序列,再用 800Hz 正弦波生成音调,加上平滑包络避免爆音。
解题思路:
- 耳听:短音为点(·),长音为划(—),对照摩尔斯码表逐字解码
- 使用在线摩尔斯解码器直接上传音频
- Audacity 打开也能从波形直观看出点划模式
Level 3:音频频谱隐写 ★★★☆☆#
分发文件: level3_spectrogram.wav
出题原理:
将一张黑白文字图片"画"进音频的频谱图中。图片的每一列对应一个时间片段,每一行对应一个频率。像素越亮,该频率的振幅就越大。直接听只能听到噪音,但用频谱分析工具查看就能看到隐藏的文字。
生成过程:
- 创建一张 600×128 的黑白图片,白色文字写着密钥
- 遍历图片每个像素,对于亮像素,在对应的时间位置叠加对应频率(800–8000Hz)的正弦波
- 像素亮度控制振幅大小
- 最终归一化并保存为 WAV
解题思路:
- 用 Audacity 打开 → 点击音轨名称 → 选择"频谱图"视图 → 密钥直接显示在频谱中
- 也可使用 Spek 或 Sonic Visualiser
Level 4:LSB 图片隐写 ★★★☆☆#
分发文件: level4_image.png
出题原理:
LSB(Least Significant Bit,最低有效位)隐写是最经典的图片隐写术。由于人眼无法分辨像素值相差 1 的颜色(例如 RGB(100,200,50) 与 RGB(101,200,51)),可以利用每个颜色通道的最低位来存储秘密信息。
生成过程:
- 创建一张 640×480 的渐变装饰图作为封面
- 将密钥转为二进制串,末尾加 NULL 终止符(8 个 0)
- 依次修改每个像素的 R、G、B 通道最低位为消息比特
- 必须保存为 PNG(无损格式),JPEG 压缩会破坏最低位
解题思路:
- 使用
zsteg工具一键提取:zsteg level4_image.png - 或用 stegsolve 逐通道查看
- 或写几行 Python:提取所有像素 RGB 最低位,每 8 位组合成一个 ASCII 字符
Level 5:DTMF 电话拨号音 ★★★☆☆#
分发文件: level5_dtmf.wav
出题原理:
DTMF(Dual-Tone Multi-Frequency,双音多频)是电话拨号使用的信号编码。每按一个按键,电话会同时发出两个特定频率的音调——一个来自低频组(697/770/852/941 Hz),一个来自高频组(1209/1336/1477/1633 Hz)。两个频率的组合唯一确定一个按键。
生成过程:
将密钥的每个数字查 DTMF 频率表,生成 0.25 秒的双频叠加音,按键之间留 0.15 秒间隔,加包络平滑处理。
解题思路:
- 使用在线 DTMF decoder 上传音频
- 或用 Audacity 频谱分析,手动识别每段音频的两个峰值频率,查表得到对应数字
- 验证脚本使用 Goertzel 算法(比完整 FFT 更高效地检测特定频率)
Level 6:多重编码 ★★★★☆#
分发文件: level6_cipher.png、level6_ciphertext.txt
出题原理:
三层套娃编码,玩家需要像剥洋葱一样逐层解开:
明文 → ROT13 → Base64 → Hex = 密文
玩家看到的是一串十六进制字符串,需要反向操作:
密文(Hex) → Hex解码 → Base64解码 → ROT13解码 = 明文
生成过程:
- 对密钥先做 ROT13(字母替换,A↔N、B↔O...)
- 结果做 Base64 编码
- 再将 Base64 字符串转为十六进制
- 同时生成一张"终端风格"的密文图片和纯文本文件
解题思路:
- 观察密文全是十六进制字符 → 尝试 Hex 解码 → 得到看起来像 Base64 的字符串(有
=填充)→ Base64 解码 → 结果仍然是乱码字母 → 尝试 ROT13 → 得到明文 - CyberChef 一站式解决:拖入 From Hex + From Base64 + ROT13 三个操作
Level 7:二维码碎片 + 频谱隐写(终极关)★★★★★#
分发文件: level7_piece1~4.png、level7_mystery.wav、level7_puzzle_map.png
出题原理:
综合前面所学的技能。一张完整的二维码被切成 5 块:4 块直接给玩家作为图片碎片,第 5 块(中心部分)被编码到音频的频谱中——需要用第 3 关学到的频谱分析技能提取。
生成过程:
- 用高容错(Error Correct H)生成 300×300 的二维码
- 切成 5 块(四角 + 中心),四角碎片带少量重叠确保定位点完整
- 将中心碎片作为灰度图编码进音频频谱(复用 Level 3 的逻辑)
- 生成拼图指引图标注各碎片位置
解题思路:
- 用 Audacity 打开
mystery.wav,切换频谱视图,截图得到第 5 块碎片 - 参考
puzzle_map.png的布局,用图片编辑器将 5 块碎片拼成完整二维码 - 扫描二维码得到最终密钥
- 二维码使用了高容错级别,即使拼接不够精确也能容忍约 30% 的误差
二、附加题(new/)#
Bonus 1:零宽字符隐写 ★★★★☆#
分发文件: bonus_message.txt(可选:bonus_message_clean.txt 作对比)
出题原理:
Unicode 中存在一类"零宽字符"——它们在屏幕上完全不可见,但确实存在于文本中。本题利用三种零宽字符构建一套二进制编码:
| 字符 | Unicode | 含义 |
|---|---|---|
| 零宽空格 | U+200B | 二进制 0 |
| 零宽非连接符 | U+200C | 二进制 1 |
| 零宽连接符 | U+200D | 字符分隔符 |
每个 ASCII 字符被编码为 8 个零宽字符(8 位二进制),字符之间用 U+200D 分隔。这些不可见字符被均匀嵌入到一段正常的英文文本中。
关键线索:
文件"看起来"只有一段普通的英文短文(约 200 字节),但实际文件大小超过 1000 字节——多出来的全是零宽字符(每个零宽字符占 3 字节 UTF-8)。
解题思路:
- 对比文件大小与可见文本长度,发现异常
- 用十六进制编辑器打开,发现大量
E2 80 8B/E2 80 8C/E2 80 8D字节序列 - 识别为零宽 Unicode 字符
- 提取所有零宽字符,按 U+200D 分割,将 U+200B 视为 0、U+200C 视为 1,每 8 位转一个 ASCII 字符
Bonus 2:敲击密码 ★★★☆☆#
分发文件: bonus2_prison_log.txt
出题原理:
Tap Code(敲击密码)是战俘和囚犯之间通过墙壁敲击进行秘密通信的经典方式。它基于 5×5 的 Polybius 方阵:
1 2 3 4 5
1 A B C/K D E
2 F G H I J
3 L M N O P
4 Q R S T U
5 V W X Y Z
每个字母用两组敲击表示:第一组 = 行号,第二组 = 列号。例如 "H" 在第 2 行第 3 列,编码为"敲 2 下,停顿,敲 3 下"。注意字母 K 与 C 共用位置(5×5 只能放 25 个字母)。
伪装形式:
谜题文件被包装成一份"监狱监控日志",记录了 Cell B-7 和 B-8 之间的墙壁敲击模式,带有时间戳和环境噪音记录(管道声、脚步声等)增加真实感。
解题思路:
- 阅读日志,注意到结构化的敲击模式:
●●● ●●●●或(... ....) - 搜索 "Tap Code" 或 "Prison Knock Code"
- 构建 5×5 方阵,将每组敲击的第一个数字作为行、第二个作为列
- 注意结果中的 C 可能实际是 K(需结合语义判断)
Bonus 3:DNA 碱基编码 ★★★★☆#
分发文件: bonus3_lab_report.txt、bonus3_sequence.fasta
出题原理:
DNA 有四种碱基(A、T、C、G),恰好可以用 2 位二进制表示:
| 碱基 | 二进制 |
|---|---|
| A (Adenine) | 00 |
| T (Thymine) | 01 |
| C (Cytosine) | 10 |
| G (Guanine) | 11 |
因此每 4 个碱基 = 8 位 = 1 个 ASCII 字符。例如字母 'H'(0x48 = 01001000)编码为 TACA。
伪装形式:
谜题被包装成一份 XenoTech BioLabs 的"机密基因序列分析报告",包含三段 FASTA 格式的 DNA 片段:Fragment Alpha 和 Gamma 是随机生成的干扰序列,Fragment Beta 是编码了密钥的目标序列,并被标注为"异常/非生物来源"。
关键线索:
- 报告明确指出 Fragment Beta "不匹配任何已知生物"
- 分析备注提到"序列长度恰好能被 4 整除"和"4-base periodicity"
- Beta 的碱基分布偏离自然序列(自然 DNA 四种碱基大致均匀,而编码后 ASCII 可打印字符集中在 0x41-0x7A 区间,导致 T 偏多)
解题思路:
- 锁定 Fragment Beta 为目标
- 意识到 4 种碱基 = 2 位二进制
- 每 4 个碱基一组,转为 8 位二进制,再转 ASCII
Bonus 4:盲文 Unicode 编码 ★★★★☆#
分发文件: bonus4_accessibility_report.txt、bonus4_braille_raw.txt
出题原理:
Unicode 盲文模式块(U+2800 ~ U+28FF)恰好包含 256 个字符,与一个字节的取值范围完全对应。每个盲文字符的码点偏移量(相对于 U+2800)就是 8 个点位的位图。
这意味着:任意一个字节都可以直接映射为一个盲文字符:
编码: 盲文字符 = chr(0x2800 + ASCII_value)
解码: ASCII_value = ord(盲文字符) - 0x2800
例如 'B'(0x42 = 66)→ chr(0x2842) = ⡂
伪装形式:
谜题被包装成一份"无障碍合规测试报告"。文档中包含标准英文盲文的 Grade 1 测试(干扰项,解码后是正常英语)和一段"异常序列"(目标,解码后不是标准盲文)。
关键线索:
- 报告直接列出了异常序列每个字符的 Unicode 码点
- 分析师备注:"256 = 2^8 = one byte. Coincidence?"
- 异常序列用标准盲文解码后是乱码,而正常测试段可以正确解码
解题思路:
- 尝试用标准盲文解码异常序列 → 失败(不是真正的盲文)
- 查看码点:全部在 U+2800~U+28FF 范围
- 意识到 256 个字符 = 一个字节
- 每个码点减去 0x2800 即得 ASCII 值
三、知识体系总结#
整个谜题集覆盖了 CTF(Capture The Flag)竞赛中 Misc 方向的核心知识领域:
信号处理类:
- Level 1 (SSTV):无线电图像传输协议
- Level 2 (Morse):经典电报编码
- Level 5 (DTMF):电话信令系统
隐写术(Steganography):
- Level 3 (Spectrogram):音频频谱隐写
- Level 4 (LSB):图片最低有效位隐写
- Bonus 1 (Zero-Width):Unicode 零宽字符隐写
编码与密码学:
- Level 6 (Multi-Cipher):多层编码(Hex/Base64/ROT13)
- Bonus 2 (Tap Code):Polybius 方阵替换密码
- Bonus 3 (DNA):自定义二进制编码方案
- Bonus 4 (Braille):Unicode 码点映射
综合应用:
- Level 7 (QR Fragments):融合频谱隐写 + 图像拼接 + 二维码扫描
难度梯度:
关卡按从易到难排列。Level 1–2 是入门级,只需找到正确的工具;Level 3–5 需要理解编码原理;Level 6 需要逐层分析;Level 7 和附加题需要综合运用多种技能。
后续还添加了sidequest线 那首乌托邦里面藏的是lsb隐写得到密文 图片的星点图是以红点X坐标排序 Y为ASCII码 解出后得到密钥 最后就是答案
最后恭喜解开谜题的参赛者#
我们明年有缘再见

再玩一次?https://101121.notion.site/trythispuzzlepizza
我们将在本服务器停止后公开谜题制作脚本&校验脚本
还没有已公开的评论。