发布于: -/最后更新: -/10 分钟/

PIZZA-CTF 赛后分析&复盘

摘要

PIZZA-CTF 赛后分析报告,涵盖了多个关卡和附加题。每个关卡都有其独特的出题原理和解题思路,涉及信号处理、隐写术、编码与密码学等领域。难度梯度从易到难,需要参赛者综合运用多种技能。最后,附加题中还包括了LSB隐写和星点图解码等挑战。

PIZZA-CTF 赛后分析&复盘

原帖子链接:https://www.nodeseek.com/post-625709-1

运用到的关卡(在对应level运用到的)

不排序

一、正式关卡(levels/)

Level 1:SSTV 慢扫描电视 ★☆☆☆☆

分发文件: level1_sstv.wav

出题原理:
SSTV(Slow Scan Television)是业余无线电爱好者用来通过音频信道传输静态图像的技术。本关使用 Robot36 格式——一种将彩色图像编码为音频信号的协议。图像的每一行被转换为一系列频率在 1500–2300Hz 之间变化的音调,其中频率的高低对应像素的亮度。

生成过程:

  1. 创建一张 320×256 的图片,上面写有密钥文字

  2. 将图片转为 YCrCb 色彩空间

  3. 按 Robot36 规范逐行扫描:先发送 VIS 码标识格式,然后每行由同步脉冲(1200Hz)+ 亮度扫描(88ms)+ 色度扫描(44ms)组成

  4. 使用连续相位正弦波生成,避免频率切换时的爆音

解题思路:

  • 直接用手机 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

出题原理:
将一张黑白文字图片"画"进音频的频谱图中。图片的每一列对应一个时间片段,每一行对应一个频率。像素越亮,该频率的振幅就越大。直接听只能听到噪音,但用频谱分析工具查看就能看到隐藏的文字。

生成过程:

  1. 创建一张 600×128 的黑白图片,白色文字写着密钥

  2. 遍历图片每个像素,对于亮像素,在对应的时间位置叠加对应频率(800–8000Hz)的正弦波

  3. 像素亮度控制振幅大小

  4. 最终归一化并保存为 WAV

解题思路:

  • 用 Audacity 打开 → 点击音轨名称 → 选择"频谱图"视图 → 密钥直接显示在频谱中

  • 也可使用 Spek 或 Sonic Visualiser


Level 4:LSB 图片隐写 ★★★☆☆

分发文件: level4_image.png

出题原理:
LSB(Least Significant Bit,最低有效位)隐写是最经典的图片隐写术。由于人眼无法分辨像素值相差 1 的颜色(例如 RGB(100,200,50) 与 RGB(101,200,51)),可以利用每个颜色通道的最低位来存储秘密信息。

生成过程:

  1. 创建一张 640×480 的渐变装饰图作为封面

  2. 将密钥转为二进制串,末尾加 NULL 终止符(8 个 0)

  3. 依次修改每个像素的 R、G、B 通道最低位为消息比特

  4. 必须保存为 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.pnglevel6_ciphertext.txt

出题原理:
三层套娃编码,玩家需要像剥洋葱一样逐层解开:

Plain Text
明文 → ROT13 → Base64 → Hex = 密文

玩家看到的是一串十六进制字符串,需要反向操作:

Plain Text
密文(Hex) → Hex解码 → Base64解码 → ROT13解码 = 明文

生成过程:

  1. 对密钥先做 ROT13(字母替换,A↔N、B↔O...)

  2. 结果做 Base64 编码

  3. 再将 Base64 字符串转为十六进制

  4. 同时生成一张"终端风格"的密文图片和纯文本文件

解题思路:

  • 观察密文全是十六进制字符 → 尝试 Hex 解码 → 得到看起来像 Base64 的字符串(有 = 填充)→ Base64 解码 → 结果仍然是乱码字母 → 尝试 ROT13 → 得到明文

  • CyberChef 一站式解决:拖入 From Hex + From Base64 + ROT13 三个操作


Level 7:二维码碎片 + 频谱隐写(终极关)★★★★★

分发文件: level7_piece1~4.pnglevel7_mystery.wavlevel7_puzzle_map.png

出题原理:
综合前面所学的技能。一张完整的二维码被切成 5 块:4 块直接给玩家作为图片碎片,第 5 块(中心部分)被编码到音频的频谱中——需要用第 3 关学到的频谱分析技能提取。

生成过程:

  1. 用高容错(Error Correct H)生成 300×300 的二维码

  2. 切成 5 块(四角 + 中心),四角碎片带少量重叠确保定位点完整

  3. 将中心碎片作为灰度图编码进音频频谱(复用 Level 3 的逻辑)

  4. 生成拼图指引图标注各碎片位置

解题思路:

  1. 用 Audacity 打开 mystery.wav,切换频谱视图,截图得到第 5 块碎片

  2. 参考 puzzle_map.png 的布局,用图片编辑器将 5 块碎片拼成完整二维码

  3. 扫描二维码得到最终密钥

  4. 二维码使用了高容错级别,即使拼接不够精确也能容忍约 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)。

解题思路:

  1. 对比文件大小与可见文本长度,发现异常

  2. 用十六进制编辑器打开,发现大量 E2 80 8B / E2 80 8C / E2 80 8D 字节序列

  3. 识别为零宽 Unicode 字符

  4. 提取所有零宽字符,按 U+200D 分割,将 U+200B 视为 0、U+200C 视为 1,每 8 位转一个 ASCII 字符


Bonus 2:敲击密码 ★★★☆☆

分发文件: bonus2_prison_log.txt

出题原理:
Tap Code(敲击密码)是战俘和囚犯之间通过墙壁敲击进行秘密通信的经典方式。它基于 5×5 的 Polybius 方阵:

Plain Text
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 之间的墙壁敲击模式,带有时间戳和环境噪音记录(管道声、脚步声等)增加真实感。

解题思路:

  1. 阅读日志,注意到结构化的敲击模式:●●● ●●●●(... ....)

  2. 搜索 "Tap Code" 或 "Prison Knock Code"

  3. 构建 5×5 方阵,将每组敲击的第一个数字作为行、第二个作为列

  4. 注意结果中的 C 可能实际是 K(需结合语义判断)


Bonus 3:DNA 碱基编码 ★★★★☆

分发文件: bonus3_lab_report.txtbonus3_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 偏多)

解题思路:

  1. 锁定 Fragment Beta 为目标

  2. 意识到 4 种碱基 = 2 位二进制

  3. 每 4 个碱基一组,转为 8 位二进制,再转 ASCII


Bonus 4:盲文 Unicode 编码 ★★★★☆

分发文件: bonus4_accessibility_report.txtbonus4_braille_raw.txt

出题原理:
Unicode 盲文模式块(U+2800 ~ U+28FF)恰好包含 256 个字符,与一个字节的取值范围完全对应。每个盲文字符的码点偏移量(相对于 U+2800)就是 8 个点位的位图。

这意味着:任意一个字节都可以直接映射为一个盲文字符

Plain Text
编码: 盲文字符 = chr(0x2800 + ASCII_value)
解码: ASCII_value = ord(盲文字符) - 0x2800

例如 'B'(0x42 = 66)→ chr(0x2842) = ⡂

伪装形式:
谜题被包装成一份"无障碍合规测试报告"。文档中包含标准英文盲文的 Grade 1 测试(干扰项,解码后是正常英语)和一段"异常序列"(目标,解码后不是标准盲文)。

关键线索:

  • 报告直接列出了异常序列每个字符的 Unicode 码点

  • 分析师备注:"256 = 2^8 = one byte. Coincidence?"

  • 异常序列用标准盲文解码后是乱码,而正常测试段可以正确解码

解题思路:

  1. 尝试用标准盲文解码异常序列 → 失败(不是真正的盲文)

  2. 查看码点:全部在 U+2800~U+28FF 范围

  3. 意识到 256 个字符 = 一个字节

  4. 每个码点减去 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码 解出后得到密钥 最后就是答案

最后恭喜解开谜题的参赛者

我们明年有缘再见

sealwhichilike.jpeg
点击查看大图
sealwhichilike.jpeg

再玩一次?https://101121.notion.site/trythispuzzlepizza

我们将在本服务器停止后公开谜题制作脚本&校验脚本

正文结束