at0m-b0mb/Hermes-FlipperZero

GitHub: at0m-b0mb/Hermes-FlipperZero

Flipper Zero 上的 UART 自动波特率检测与串口控制台工具,通过信号边沿测量和硬件校验自动识别未知串口的波特率与帧格式。

Stars: 4 | Forks: 0

Hermes — UART baud detector and console tap for the Flipper Zero # Hermes **每根线都在说话。Hermes 告诉你它们在说什么。** 夹接到未知的串行线上。Hermes 使用 CPU 的周期计数器测量位时间,将结果与真实的 UART 进行校验,然后将控制台交给你。 [![Flipper Zero](https://img.shields.io/badge/Flipper%20Zero-FAP-FF6900?style=flat-square&logo=flipper&logoColor=white)](https://flipperzero.one/) [![Build FAP](https://img.shields.io/github/actions/workflow/status/at0m-b0mb/Hermes-FlipperZero/build.yml?style=flat-square&label=build)](https://github.com/at0m-b0mb/Hermes-FlipperZero/actions) [![Category](https://img.shields.io/badge/category-GPIO-FFB02E?style=flat-square)](#) [![Firmware API](https://img.shields.io/badge/API-87.1%20(fw%207)-2EDC82?style=flat-square)](#) [![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE) [![Made by at0m-b0mb](https://img.shields.io/badge/made%20by-at0m--b0mb-black?style=flat-square)](https://github.com/at0m-b0mb)
## 问题所在 你已经撬开了路由器的外壳。SoC 旁边有四个焊盘,其中几乎肯定有一个是带有 root shell 的串行控制台。但它的波特率是多少?是 8N1,还是更奇怪的组合? 通常的答案是盲猜:在 115200 下打开一个终端,眯着眼睛看一堆乱码,再试试 57600,继续眯着眼看。Hermes 替你完成了这些测量。
Hermes screens: the live edge scope while listening, the detected result with confidence, and the console attached to a U-Boot prompt
Listen → measure → tap. The scope shows the target's real bits. The verdict shows what it is, how sure Hermes is, and why. Then you're on the console.
## 实际工作原理 大多数自动波特率工具会做两件事中的一件。Hermes 两件都做,因为它们能互相弥补盲区。 ### 阶段 1 — 测量位时间 RX 引脚被接管为一个普通的中断输入。每个信号边沿都通过 `DWT->CYCCNT`(即 ARM 周期计数器)记录时间戳,它以 64 MHz 的频率运行——大约每个 tick **15 纳秒**。 这给出了一份*片段*列表:电平在两次边沿之间保持高或低的时间。每一个片段都是位时间的整数倍,因为 UART 就是这样工作的。 ``` idle start d0 d1 d2 d3 d4 d5 d6 d7 stop idle ─────┐ ┌─────┐ ┌────┐ ┌─────┐ ┌────── └──────┘ └─────┘ └─────┘ └──────┘ │ 1 │ 2 │ 1 │ 1 │ 1 │ 2 │ 1 │ └──────────── every run is k × the bit time ────┘ ``` 所以“波特率是多少?”这个问题就变成了“**什么样的位时间能把这些测量值全变成近似整数?**” Hermes 通过直接测试每个标准速率并计算它能解释多少个片段来回答这个问题。有两个细节让这不仅仅是听起来聪明,而是真正起作用: **谐波。**真实位时间的一半*同样*也能把每个测量值变成整数——只是变成大一倍的整数而已。四分之一位时间也是如此。逃脱这个陷阱的关键在于,一个 UART 数据帧中连续相同的位数是有限的(受起始位和停止位限制,低电平连续长度最多为 9)。在谐波倍率下,较长的电平段需要的位数超过了数据帧的物理容纳上限,因此无法对齐。**在得分相近的速率中,最慢的那个才是真实的速率**——其余的只是它的回声。 **容差。**一个片段的计时误差来自于其两个边沿的中断延迟,而且这个误差*不会*随着中间位数的增加而累积变大。因此,容差只是**一个**位时间的一部分,绝不是整个片段的一部分。如果让容差随片段长度缩放,那么一个极其离谱的快速率会把任何信号都吞没,直接把每个脉冲都当作它自己的 9 个位——这正是让我栽过跟头的 bug,[由测试套件捕获](test/)。 一旦速率确定,Hermes 就会以此为基准进行微调,读取线路*实际*的位时间——这正是你用来区分标准的 115200 和晶振偏差了 3% 的电路板的方法。 ### 阶段 2 — 通过硬件进行校验 时间上的契合仍然只是一种推断。因此,Hermes 会把同一个引脚重新作为**真正的 UART** 打开,并在每个候选速率下监听 150 毫秒,从两个维度对返回的数据进行评分: | 信号 | 含义 | |---|---| | **Framing errors** | 线路与猜测速率不一致。这是最强有力的证据,也是唯一能在二进制协议下存活的证据。 | | **可打印字符比例** | 读取的数据中有多少是文本。用于打破平局,并奖励真实的控制台。 | | *Overruns* | **特意不计入评分。** Overrun 意味着 Hermes 处理速度太慢,而不是速率错误——将其计入评分会暗中惩罚那些最快、最正确的候选者。 | 这也是它检测**帧格式**的方式:速率正确但校验位错误,会表现为一条充斥着 frame errors 的相对干净的字节流,因此第二遍会锁定速率,并让 8N1 / 8E1 / 8O1 / 7E1 进行竞争。这就是为什么 Hermes 报告的是 `115200 8N1` 而不仅仅是一个数字。 ### 为什么需要这两个阶段 它们失败的方向正好相反,这正是关键所在: - **边沿计时** 仅基于一次短暂的突发数据即可工作——一条启动消息就足够了——但中断无法捕捉大约超过 **230400** 的边沿。 - **UART 扫描** 没有速度限制,在 921600 下依然能保持硬件级的精确度,但它需要在其监听窗口内有数据通信。 因此,当时间契合的结果落空时——这正是在极高速线路上发生的情况——Hermes 会转而在 UART 上扫描整个速率表。而当线路在两个阶段之间陷入沉默时,它会在结果屏幕上显示 **"timing only"**,而不是把一个猜测伪装成测量结果。 ## 阅读结果
The result screen: 115200 8N1 at 97% confidence, verified, with a candidate ladder
- **数字和帧格式** — 打开控制台时所使用的配置。 - **`verified` / `timing only`** — 是有真实的字节数据作为支撑,还是仅仅依靠了边沿计时。 - **条形图** — 置信度:该速率能解释多少捕获的数据,并根据微调后的测量值的接近程度进行缩放。 - **数据来源行** — `128 B 94% text`,或者 `412 edges - 96% fit`。绝不仅仅是一个数字;总会告诉你它的来源。 - **筹码** — 次优选项,每个筹码的高度代表其置信度。紧随其后的第二名是*可见的*,而不是被隐藏在按键背后。按 **Left / Right** 选择一个,按 **OK** 打开它。 ## 控制台
The console attached to a U-Boot prompt at 115200 8N1
这是一个真正的终端,而不是字节转储。启动日志中充满了 ANSI 颜色代码,因此 Hermes 会在数据流上运行一个小型 VT 解析器——否则屏幕上会布满 `[0;32m` 而不是文本。 | 按键 | 功能 | |---|---| | **Up / Down** | 向上滚动。在你阅读时,新的输出绝不会把你拉走。 | | **Right** | ASCII ⇄ hex(hex 侧边带有 ASCII 边栏,因此熟悉的字符串依然能一眼看到) | | **Left** | Ctrl 键盘 — **Ctrl+C**, Ctrl+D, Ctrl+Z, Esc, Tab | | **OK** | 输入一行并发送 | | **OK (长按)** | 单独发送 Enter | | **Back** | 断开链接 | RX 在 DMA 上运行,因此即使是 921600 下的完整启动日志,也能在传输过程中不丢失任何字节地到达。 ## 接线
The wiring guide: Flipper pin 14 to target TX, pin 13 to target RX, GND to GND The rules screen: 3.3V logic only, RS-232 kills the Flipper, ground first
**RX 和 TX 总是交叉连接的。** 你的 TX 连接他们的 RX。 | Flipper | | 目标设备 | |---|---|---| | **Pin 14** (RX) | ← | **TX** | | **Pin 13** (TX) | → | **RX** | | **Pin 8/11/18** (GND) | ↔ | **GND** | 想用其他引脚?**Settings → Port** 会切换到 **15/16** 上的 LPUART,并且接线指南会自动重新标记以匹配。 ## 安装 ### 预编译的 `.fap` (最快) 1. 从 [**Releases**](https://github.com/at0m-b0mb/Hermes-FlipperZero/releases) 下载 `hermes.fap`,或者从 [**Actions**](https://github.com/at0m-b0mb/Hermes-FlipperZero/actions) 下最新一次成功运行(绿色)的 *Artifacts* 中获取。 2. 打开 [qFlipper](https://flipperzero.one/update),连接你的 Flipper。 3. 将其复制到 **`SD Card / apps / GPIO /`**。 4. 在 Flipper 上:**Apps → GPIO → Hermes**。 ### 自行构建 ``` python3 -m pip install --upgrade ufbt git clone https://github.com/at0m-b0mb/Hermes-FlipperZero.git cd Hermes-FlipperZero ufbt # -> dist/hermes.fap ufbt launch # build, install and run on a connected Flipper ``` 基于官方固件 **fw 7 / API 87.1** 构建,并且 CI 也会基于 **dev** SDK (API 88.0) 进行构建。它仅使用公开的 `furi_hal_serial` 和 `furi_hal_gpio`,因此可以同时跟踪两个发布通道。 与 **Momentum** / **Unleashed** / **RogueMaster** 使用的应用目录布局即插即用兼容——只需将文件夹放入 `applications_user/hermes` 即可。 ## 测试 检测器是整个产品的核心,也是截图无法证明其有效性的唯一部分。因此它经过了测试: ``` make -C test ``` 这会为主机环境编译带有 stubbed HAL 的 **真实** `autobaud.c`,合成已知速率的 8N1 波形,并逐个边沿地驱动**真实的中断处理程序**——然后询问真实的拟合算法它看到了什么。21 项检查,在 ASan 和 UBSan 下运行,每次推送时都会在 CI 中执行: ``` clean signal 1200 · 9600 · 19200 · 38400 · 57600 · 74880 · 115200 interrupt jitter up to ±200 cycles at 115200 idle gaps 200 bit times of silence between frames harmonic traps 57600 must not answer 115200; 19200 not 38400 binary payload random bytes, not text degenerate non-standard rate must not be named confidently · silent line ``` 抖动和谐波案例并不是摆设——它们在开发过程中都曾抓出过真实的 bug。 ## 目录结构 ``` Hermes-FlipperZero/ ├─ application.fam # manifest (appid, GPIO category, icon) ├─ hermes.c / hermes_i.h # lifecycle, views, notifications ├─ helpers/ │ ├─ autobaud.[ch] # the star: edge capture + the bit-time fit │ ├─ verifier.[ch] # the second opinion: real UART, real framing errors │ ├─ uart_tap.[ch] # the live link (DMA rx, gated tx) │ ├─ term.[ch] # terminal model + the ANSI parser │ └─ baud_table.[ch] # standard rates, framings, pin profiles ├─ views/ │ ├─ detect_view.[ch] # the live square-wave scope │ ├─ result_view.[ch] # verdict card + candidate ladder │ ├─ console_view.[ch] # the terminal │ └─ wiring_view.[ch] # animated wiring + the safety rules ├─ scenes/ # start · detect · result · console · ctrl · │ # keyboard · manual · wiring · settings · about ├─ test/ # host test for the fit (stubbed HAL) └─ tools_gen_*.py # Pillow asset generators ``` ## 常见问题 **它显示 "no edges yet"。** 接地问题,或者交叉接错了。Flipper **RX (14)** 必须接目标设备的 **TX**——而不是 TX 接 TX。如果你确定这两点都没错,那么焊盘可能只是处于空闲状态;许多开发板只在启动时发送数据,所以可以在 Hermes 监听时给目标设备重新上电。 **它找到了速率,但文本是乱码。** 帧格式可能不是 8N1。*如果在验证期间有数据通信*,Hermes 会自动尝试 8E1/8O1/7E1——如果开发板归于沉寂,请在 **Manual Console** 中自行选择帧格式。 **它能检测 921600 吗?** 检测速率是可行的——通过硬件精确的 UART 扫描。但*边沿计时*在大约 230400 左右就会放弃,因为中断的进入速度跟不上相隔 4 µs 的边沿。Hermes 会自动回退;你会看到它进行扫描。 **我的设备运行在非标准速率上。** Hermes 只能从它的速率表中命名。类似 100000 波特率的设备返回的置信度会很低,而不是给出一个充满自信的错误答案——这是刻意为之的。如果你已经知道了速率,请使用 **Manual Console**。 **它会向我的开发板写入数据吗?** 在检测期间不会——TX 引脚会被主动释放。在控制台中,它只传输你输入的内容。**Settings → Transmit: OFF** 可以使整个会话变为只读。 **为什么我的 80 列日志会换行?** 128 像素对应 21 个字符。换行是诚实的表现;截断反而会隐藏信息。 ## 伦理 Hermes 适用于**你自己的开发板,以及你被授权测试的设备**。串行控制台通常是一个无需身份验证的 root shell——这正是为什么在你自己的硬件上找到它是有价值的,而在不属于你的硬件上寻找它是别人应该跨越的界限,而不是你的。 默认情况下它只进行监听,只有在你下达命令时才会发送数据。剩下的取决于你。不要做个混蛋。 ## 致谢 由 **[at0m-b0mb](https://github.com/at0m-b0mb)** 构建。Flipper Zero 工具家族的一部分: - 🗿 **[Rosetta](https://github.com/at0m-b0mb/Rosetta-FlipperZero)** — 协议解释器:观察 Mifare、OOK/PSK 和 1-Wire 的交互过程 - 🛡️ **[Warden](https://github.com/at0m-b0mb/Warden-FlipperZero)** — NFC 门禁卡安全评级器 - 🔱 **[Trident](https://github.com/at0m-b0mb/Trident-FlipperZero)** — 三合一 ESP32 + NRF24 + CC1101 多无线电设备 - 👻 **[Specter](https://github.com/at0m-b0mb/Specter-FlipperZero)** — 被动式 NFC 读取器/_skimmer_ 窃取器防窃听扫描 - 📡 **[Cerberus](https://github.com/at0m-b0mb/flipper-cerberus)** — Sub-GHz 射频看门狗 - 🏷️ **[GhostTag](https://github.com/at0m-b0mb/GhostTag-FlipperZero)** — 防追踪 BLE 追踪器猎手
MIT © 2026 at0m-b0mb — Flipper Zero 和海豚标志是 Flipper Devices 的商标。Hermes 是一个独立的项目。
标签:Flipper Zero, 串口通信, 客户端加密, 嵌入式硬件, 控制台调试, 波特率检测, 硬件调试, 逆向工具