Markthegamer108/RAVage

GitHub: Markthegamer108/RAVage

RAVage 是首个通过逆向工程 Ravensburger tiptoi 固件实现 RAV 音频格式双向转换的开源工具。

Stars: 0 | Forks: 0

# RAVage — tiptoi `.rav` 音频转换器 **English** · [Deutsch](README.de.md) 将**任何音频文件** (mp3, wav, m4a, flac, ogg, …) 转换为 **Ravensburger tiptoi pen (3203L)** 可播放的 `.rav` 文件 — 并支持反向转换。 3203L 使用的 RAV 加密是通过 Thumb-2 反汇编从固件更新文件 (`Update3203L.upd`) 中完全逆向工程得出的。这里的所有内容都是从零开始 实现的,并针对原始笔文件进行了字节级精确验证。据我们所知,这是第一个 可用的实现 — 十年前社区曾将其作为“高强度加密”存档 ([issue #115](https://github.com/entropia/tip-toi-reveng/issues/115))。 ![GUI](https://static.pigsec.cn/wp-content/uploads/repos/cas/84/84124e7b14d791180567a72e0becca97ae3bfeb22af66c7e3ea669ba3e58016c.png) ## 预编译二进制文件 无需 Python — 从 [releases 页面]( https://github.com/Markthegamer108/RAVage/releases) 获取适合你操作系统的版本(或最新 workflow 运行的 artifacts): | OS | 下载内容 | 备注 | |----|--------------|-------| | Windows | `ravage-windows.zip` — `ravage.exe` (GUI) + `ravage-cli.exe` | 双击 `ravage.exe` | | macOS | `ravage-macos.tar.gz` — `ravage.app` + `ravage-cli` | 未签名,因此首次启动:右键点击 → 打开 | | Linux | `ravage-linux.tar.gz` — `ravage` (GUI) + `ravage-cli` | 如有需要,请执行 `chmod +x` | 所有依赖都已打包 — ffmpeg、密钥表等一应俱全。二进制文件由 GitHub Actions 构建(参见 `.github/workflows/build.yml`)。 ### 已测试的硬件 已在真实硬件上验证:**tiptoi pen gen 2 (3203L)**。其他版本的笔 使用相同的 RAV 文件家族,但它们的固件有所不同 — 密钥表是从笔自身的固件更新中提取的(`data/keytable.bin` 来自 `Update3203L.upd`),因此在信任 gen 3 笔之前,需要根据其自带的原厂文件/固件进行验证。如果你有该设备并想进行 测试,解密器(`rav_cli.py decrypt`)会是你的好帮手。 ## 快速开始 ### GUI(最简单) ``` run_gui.bat ``` 或者 ``` python rav_gui.py ``` 选择一个音频文件,选择一个输出文件夹,点击 **Convert to .rav**,然后将 结果复制到笔的音乐文件夹中(例如 `E:\songs\My Song.rav`)。 ### CLI ``` python rav_cli.py convert "My Song.mp3" -o "My Song.rav" python rav_cli.py decrypt "Old MacDonald Had a Farm.rav" -o song.ogg # research ``` ## 工作原理 `.rav` 文件包含一个 0x20 字节的头部,随后是使用简单的带密钥字节转换加密的 **Ogg Vorbis** 音频 流(单声道,22050 Hz)。笔会忽略 Ogg 页面 CRC,因此密文不需要保留有效的 CRC。 ### 头部(20 字节) | 偏移量 | 大小 | 含义 | |-------:|-----:|---------| | 0x00 | 16 | magic `Ravensburgerv03\0` | | 0x10 | 2 | `value16` (little-endian) | | 0x12 | 1 | flag,始终为 `0xBE` | | 0x13 | 8 | key blob: `TABLE[value16 + 3 + i] ^ key8[i]` | | 0x1B | 5 | trailer,固定为 `4E 6C 31 F2 65` | ### 密钥派生 ``` key8 = "CommonI2" checksum = (sum(key8) + value16) & 0xFFFF # e.g. 0x78 → 0x035C keystream[i] = TABLE[(checksum + i) & 0xFFF] # 512 bytes ``` 4096 字节的 `TABLE` 是固件中固定的密钥表(文件偏移量 `0xDBADC`,内存 `0x008EDADC`),在此打包为 `data/keytable.bin`。 ### 主体加密算法 应用于从文件偏移量 `0x20` 开始的 payload: ``` kb = keystream[(pos - 0x20) & 0x1FF] op = pos & 3 op 0 XOR with pass-through: if c ∈ {0x00, 0xFF, kb} or (c ^ kb) == 0xFF → keep c unchanged, else out = c ^ kb op 1 out = (c - kb) & 0xFF op 2 out = (c + kb) & 0xFF op 3 out = c ^ kb (no pass-through rules) ``` 直通规则(在固件循环 `0x8DF3B4` 中验证过)的存在,使得与 keystream 的字节冲突永远不会产生可能 干扰解码器的值。编码器完全映射了它们(`op 0`:如果 明文是 `0x00`、`0xFF`、`kb` 或 `kb ^ 0xFF`,则原样输出),使加密 **无损** — 官方笔文件在这些位置是有损的,而我们的可以实现字节级精确往返。 ## 破解过程 这是为喜欢探索过程的人准备的简短说明。没有侧信道攻击,也没有泄露的 密钥 — 一切都隐藏在显眼处。 1. **兔子洞。** Wiki 和 issue #115(2015年关闭)宣称 RAV 文件使用了“高强度加密”加密,并流传着密钥可能存在于每支笔特定的芯片中的说法。约10年来无人能破解它。 2. **固件。** Ravensburger 在其网站上直接发布了笔的固件更新 (`Update3203L.upd`) — 这是一个普通的 Cortex-M (ARM Thumb-2) 镜像,没有任何实质意义上的混淆。 3. **寻找音频路径。** 在镜像中搜索 RAV magic `Ravensburgerv03` → 定位到 `0x8DFE84` 的音频打开函数, 该函数调用 key generator(`0x8DF380`)和解码循环 (`0x8DF3B4`)。 4. **“秘密”其实是公开的。** key generator 使用 `key8 = "CommonI2"`(固件中的硬编码字符串字面量)以及位于镜像 `0xDBADC` 处的 4096 字节表,构建出 512 字节的 keystream。每支笔出厂都内置了解密密钥 — 从来就没有什么单机密钥。这不是密码学,这只是带有查找表的高级 XOR。 5. **验证,失败,修复。** 最初的尝试在 PC 上实现了完美的往返,但笔拒绝播放我们的文件:keystream 索引是相对于 payload 的(`pos - 0x20`),而 op selector 是绝对值(`pos & 3`)。弄错相位会导致整个流静默偏移。 这个小细节花费了好几天的时间。 6. **怪癖。** 笔忽略了 Ogg 页面 CRC(解码器草率,对我们来说很幸运),并拒绝播放带有庞大 Vorbis 注释头的流 — 约 9 KB 的 YouTube 翻录头会失败,而约 3.6 KB 的原厂大小则可行。 7. **真实硬件。** Old MacDonald。Olchi。Drei Chinesen。全部解密为 `OggS`;自定义文件在笔上播放。大功告成。 ## 逆向工程笔记 - 固件:`Update3203L.upd` — Cortex-M (ARM Thumb-2) 镜像;文件偏移量 → 内存 `+ 0x00812000`。 - 音频打开函数:`0x8DFE84`;key generator:`0x8DF380` (`KEY[i] = TABLE[(checksum + i) & 0xFFF]`,注意掩码仅适用于 `checksum + i`);主体加密算法循环:`0x8DF3B4`。 - `0x8DF2FC` / `0x8DF340` 仅用于初始化/清理 — 与密钥派生无关。 - 原厂文件全部使用 `key8 = b"CommonI2"` 和 `value16 = 0x78` 解密了四个出厂文件;payload 全部为 Ogg Vorbis(单声道 22050 Hz)。 ### 重新生成 `data/keytable.bin` ``` from rav_tool import ravcrypto ravcrypto.extract_keytable(r"C:\path\to\Update3203L (1).upd", "data/keytable.bin") ``` ## 依赖项 - Python 3.8+ - PATH 中包含 `ffmpeg` **或者** `pip install imageio-ffmpeg`(捆绑的静态构建版本) - `numpy`(可选 — 包含纯 Python 回退方案,速度慢约 10 倍) ## 文件 ``` rav_gui.py / rav_gui.pyw GUI converter (double-click friendly) rav_cli.py command-line converter + decryptor rav_tool/ravcrypto.py the RAV cipher, header build/parse, key table rav_tool/convert.py ffmpeg wrapper (any format → Ogg Vorbis) data/keytable.bin key table extracted from firmware 3203L ``` ## 许可证 MIT — 可自由使用、学习和分享。 ## 社区 本项目建立在 [tip-toi-reveng](https://github.com/entropia/tip-toi-reveng) 社区及其 [wiki](https://github.com/entropia/tip-toi-reveng/wiki) 的基础工作之上。RAV 格式是 最后一个尚未解决的重大难题 — 加入 [tiptoi 邮件列表](https://lists.nomeata.de/mailman/listinfo/tiptoi) 并 打个招呼吧。
标签:GUI, Python, 云资产清单, 嵌入式固件, 文件格式, 无后门, 硬件黑客, 逆向工具, 逆向工程, 音频转换