auracast-research/race-toolkit

GitHub: auracast-research/race-toolkit

一个用于与 Airoha 蓝牙设备通过 RACE 协议通信的安全研究工具,支持漏洞检测、内存转储和固件操作等功能。

Stars: 447 | Forks: 44

# RACE Toolkit RACE Toolkit 是与我们的 Airoha 研究一同发布的工具。你可以在我们的[博客文章](https://insinuator.net/2025/12/bluetooth-headphone-jacking-full-disclosure-of-airoha-race-vulnerabilities)中了解更多相关信息。 本仓库包含一个基于 Python 的命令行工具包,用于与通过各种传输层(BLE GATT、Bluetooth Classic RFCOMM、USB HID)暴露 **RACE protocol** 的设备进行交互。它主要用于对 Airoha 生态系统进行进一步的安全研究,以及供终端用户检查其设备是否受到相关漏洞的影响。 该工具支持 RAM/flash 转储、设备信息查询,并初步支持固件更新(FOTA)。特定功能是否适用于某个设备,很大程度上取决于该设备本身。例如,RAM 转储仅适用于(仍然)暴露了该命令的设备。目前的固件更新过程仅支持头戴式耳机,不支持 TWS(真无线立体声)耳机。 RACE toolkit 还提供了一个命令,用于检查给定设备是否受到 CVE-2025-20700、CVE-2025-20701 或 CVE-2025-20702 的影响。但是,由于设备之间的差异,我们无法保证该检查命令的可靠性。如果它返回 *FIXED*,设备仍有可能存在漏洞。例如,某些设备需要特定的条件才能绕过 Bluetooth Classic 配对。我们还发现过一个设备,在多次尝试和多次重启中,仅出现过一次容易受到 Classic 配对问题影响的情况。我们没有对所有这些设备和所有的边缘情况进行深入调查。尽管如此,`check` 命令仍是一个很好的起点,并且它不会产生误报。如果它认为设备存在漏洞,那么该设备就一定是脆弱的。 ## 功能 - 实现了一小部分 RACE 命令。主要是那些与进一步安全研究相关以及用于确认设备是否仍然存在漏洞的命令。 - 支持不同的 RACE 传输层: * BLE GATT(通过 Bumble 使用蓝牙适配器,或通过 Bleak 使用操作系统蓝牙协议栈) * Bluetooth Classic RFCOMM(通过 Bumble 使用蓝牙适配器) * USB HID - 针对 RACE 相关的 CVE(CVE-2025-20700、CVE-2025-20701 或 CVE-2025-20702)的半自动化漏洞检查 - 读写设备 RAM - 转储 flash 内存和分区 - 查询设备元数据(SDK 信息、构建版本、Bluetooth Classic 地址) - 固件(FOTA)更新(或降级) ## 安装说明 本项目支持两种安装方法。你可以根据自己偏好的工作流程选择其中之一: * 结合 `requirements.txt` 使用 `pip` * 结合 `pyproject.toml` 使用 `uv` 这两种方法都会安装相同的依赖项。由于 [Bumble Bluetooth 库](https://github.com/google/bumble)的要求,需要使用 Python 3.10。 ### 选项 1:使用 `pip` 安装 ``` python -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ### 选项 2:使用 `uv` 安装 本仓库包含一个可与 [`uv`](https://github.com/astral-sh/uv)配合使用的 `pyproject.toml`。 ``` uv sync ``` 此操作将会: * 创建虚拟环境 * 安装 `uv.lock` 中锁定的所有依赖项 要在该环境中运行命令: ``` uv run python race_toolkit.py --help ``` 要使用 `gatt` 或 `rfcomm` 传输层,Bumble 需要访问你内置的 Bluetooth 控制器或外接蓝牙适配器。在某些 Linux 发行版中,需要禁用蓝牙守护进程。如果你遇到任何与 HCI 或 libUSB 相关的问题,请尝试停用该服务(`systemctl stop bluetooth`)。在 macOS 上,由于操作系统不暴露 HCI 层,因此需要外接适配器。 通常,最好的方法是使用外接蓝牙适配器。这让你可以在不干扰操作系统蓝牙协议栈的情况下使用该工具包。请注意,并非所有的蓝牙适配器都能被 Bumble 支持。 ## 前置条件 - Python 3.10+ - 受 Bumble 支持的蓝牙适配器(例如 USB 或 UART)。请参阅 Bumble 的[传输层部分](https://google.github.io/bumble/transports/usb.html)。 - 某些 GATT 命令也可以在没有额外适配器的情况下,使用 [bleak 库](https://github.com/hbldh/bleak)来执行 ## 传输层 RACE 可以通过不同的传输层进行通信。在此工具包中,我们实现了其中的一个子集。每种传输层都有不同的功能、限制和要求。 ### GATT (Bumble) (`--transport gatt`) **默认传输层。** * 通过 Bumble 协议栈使用蓝牙低功耗 GATT * 支持通过设备名称或直接地址进行扫描 * 进行基于 BLE 的漏洞检查所必需 **注意事项:** * 需要兼容 Bumble 的 Bluetooth 控制器 * 可以选择使用 `--authenticate` 来尝试配对 ### GATT (Bleak) (`--transport bleak`) * 使用 Bleak 库进行 BLE GATT 访问 * 在 Bumble 不可用或不兼容时非常有用 **限制:** * 与基于 Bumble 的 GATT 相比,功能集有所减少 * 测试不全面。一旦我们切换到 Bumble,就不再关注 bleak 传输层了 * 并非所有的检查或命令都能正常工作 ### Bluetooth Classic RFCOMM (`--transport rfcomm`) * 通过 RFCOMM 使用 Bluetooth Classic **注意事项:** * 需要兼容 Bumble 的 Bluetooth 控制器 * 需要提供有效的 Bluetooth Classic 地址 ### USB HID (`--transport usb`) * 通过 USB HID 直接与设备通信 * 没有太多设备会通过 USB 暴露 RACE **注意事项:** * 设备以 `VID:PID` 格式指定 * 如果省略,工具可能会以交互方式枚举设备 ## 运行说明 ``` python race_toolkit.py [global options] [command options] ``` ## 全局选项 除非另有说明,否则这些选项适用于所有命令。 | 选项 | 描述 | | -------------------- | ------------------------------------------------------------------------------- | | `-t`, `--transport` | 传输方式。可选值为 `gatt`、`bleak`、`rfcomm`、`usb`(默认:`gatt`) | | `-c`, `--controller` | Bumble Bluetooth 控制器(默认:`usb:0`) | | `--target-address` | 目标设备的 Bluetooth Classic 地址 | | `--le-names` | 如果未提供地址,则扫描一个或多个 BLE 设备名称 | | `-d`, `--device` | USB HID 设备的 VID:PID(仅适用于 `usb` 传输层) | | `--outfile` | 将命令输出写入文件,而不是输出到标准输出 | | `--debug` | 启用调试日志 | | `--send-delay` | RACE 消息之间的延迟(秒)(可能适用于旧版固件?) | | `--authenticate` | 在连接期间尝试配对/认证 | ## 命令 ### `check` 检查设备是否存在 RACE 漏洞: - CVE-2025-20700 – 缺失 GATT 认证 - CVE-2025-20701 – 缺失 BR/EDR 认证 - CVE-2025-20702 – RACE protocol 暴露(BLE 和 Classic) ``` python race_toolkit.py check ``` 该命令将以交互方式引导你完成整个过程。它会执行以下操作: 1. 扫描 BLE 设备并询问哪个属于用户。 2. 连接到设备并枚举 GATT 服务。 3. 检查是否存在已知的 RACE UUID 之一。 4. 测试 flash 读取 RACE 命令。 5. 尝试通过相应的 RACE 命令获取 Bluetooth Classic 地址。 6. 并非所有设备都支持此命令。如果失败,它会交互式地提示用户输入 Bluetooth Classic 地址。 7. 通过 Bluetooth Classic 连接到设备。 8. 枚举 RFCOMM 服务。 9. 检查是否存在已知的 RACE RFCOMM 服务之一。 10. 连接并尝试通过 RFCOMM 使用 RACE 命令读取 flash。 如果你已经知道设备的 *Bluetooth Classic 地址*,可以通过 `--target-address` 参数提供。RACE toolkit 会尝试在 BLE 阶段获取该地址。如果失败,它将以交互方式询问地址。如果设备无法通过 BLE 访问,则自动获取 Classic 地址的操作将无法进行。 最后,会打印出汇总的漏洞状态。 ### `ram` 读取设备 RAM。 ``` python race_toolkit.py [global options] ram --address --size ``` **选项:** - `--address`(必填):目标 RAM 地址(十六进制) - `--size`(必填):要读取的字节数(十六进制)。必须是 4 的倍数,因为该命令仅支持读取 4 字节。 **行为:** - 除非指定了 `--outfile`,否则输出将以十六进制转储 ### `flash` 转储 flash 内存。 ``` python race_toolkit.py [global options] flash --address --size ``` **选项:** - `--address`(必填):Flash 起始地址(十六进制,`0x100` 的倍数) - `--size`(必填):要转储的字节数(十六进制,`0x100` 的倍数) ### `link-keys` 获取存储的 Bluetooth BR/EDR 链路密钥。 ``` python race_toolkit.py [global options] link-keys ``` 注意事项: - 此命令在许多设备上不起作用。输出仅包含部分链路密钥,而不包含其他设备的蓝牙地址。 - 这不是用于演示渗透(pivoting)的命令。NVDM 分区也包含这些密钥(参见 `dump-partition`)。 ### `bdaddr` 通过 RACE 查询 Bluetooth Classic 地址。 ``` python race_toolkit.py [global options] bdaddr ``` 注意事项: - 这非常有用,因为设备通常是不可被发现(undiscoverable)的。因此,为了通过 Bluetooth Classic 进行连接,此命令消除了嗅探设备地址的需要(例如使用 Ubertooth)。 ### `sdkInfo` 从设备获取 SDK 信息。 ``` python race_toolkit.py [global options] sdkinfo ``` 注意事项: - 响应 payload 被解释为 UTF-8 文本。 - 通常,这并没有太大帮助。对于某些设备,输出仅仅是版本 1。 ### `buildversion` 获取固件构建版本字符串。 ``` python race_toolkit.py [global options] buildversion ``` 注意事项: - 许多设备不再响应此命令。 - 如果它们响应,这对于指纹识别和确定版本会很有帮助。 ### `mediainfo` 转储有关当前播放媒体的元数据。 这是针对 Sony WH-CH720N 进行现场演示的概念验证命令。 ``` python race_toolkit.py [global options] mediainfo ``` 重要注意事项: * 这是一个概念验证功能 * 它依赖于硬编码的 RAM 偏移量 * 仅支持特定的固件版本和设备 ### `dump-partition` 交互式转储 flash 分区。 ``` python race_toolkit.py [global options] --outfile dump-partition ``` 工作流程: 1. 读取并解析分区表 2. 显示所有分区 3. 提示用户选择一个分区 4. 将所选分区转储到文件中 这通常用于转储 NVDM 分区(大多数情况下它是 6 号分区)。此分区包含配置数据。 注意事项: - 此处必须使用全局 `--outfile` 选项。此命令不会输出到标准输出。 ### `fota` **警告:**仅在你知道自己在做什么的情况下使用此命令! 此命令执行 FOTA 固件更新。我们根据在其中一台设备更新期间观察到的情况重新实现了 FOTA 过程。额外信息是通过逆向工程固件和移动应用程序获取的。最终,此过程被确认可以在 *Sony WH-CH720N* 和 *Sony WH-1000 XM6* 上正常工作。它很可能也适用于其他索尼头戴式耳机型号,但是我们尚未对此进行确认。这同样适用于其他厂商的耳机。此外,当前实现的 FOTA 过程无法用于真无线立体声(TWS)耳机。这需要一些我们(目前)尚未实现的额外步骤。 此实现允许你刷入有效的 FOTA 镜像。它也允许固件降级。但是,我们不建议降级你的日常生产设备。索尼固件可以在 [MDR Proxy Repository](https://github.com/lzghzr/MDR_Proxy)中找到。下载固件和运行 FOTA 命令时,请确保选择正确的设备。 再次重申,如果你不知道自己在做什么,请不要使用此功能。由于 FOTA 过程中会对固件进行完整性检查,因此*应该*是安全的。在我们的研究过程中,有两台设备在修改固件镜像并运行更新后变砖了。 ``` python race_toolkit.py [global options] fota --fota-file [options] ``` **选项:** - `--fota-file`(必填):FOTA 镜像的路径 - `--dont-reflash`:不擦除/重新刷入 FOTA 分区 - `--chunks-per-write`:每次刷入的块数(默认:3) 注意事项: - 除非设置了 `--dont-reflash`,否则必须提供 `--fota-file` - 更大的块大小可能并不适用于所有设备。通常 3(默认值)的效果最好。 ## 注意 此工具仅供**研究和教育目的**使用。 - 请勿对你不拥有或未经许可测试的设备使用! - 访问 Flash 和 RAM 可能会导致设备永久变砖! - 只有在你确切知道自己在做什么的情况下才使用 FOTA 命令!我们无法帮助你修复变砖的设备!
标签:Maven, Python, XXE攻击, 固件安全, 无后门, 漏洞验证, 物联网, 蓝牙, 逆向工具