SpiritualMachines/buds-audit
GitHub: SpiritualMachines/buds-audit
一款无需 dongle 和 root 权限的蓝牙耳机安全评估工具,专门检测 Airoha SDK 漏洞链(CVE-2025-20700/20701/20702)对无线耳机的影响。
Stars: 0 | Forks: 0
# buds-audit
**版本 0.5.0**
用于安全评估受以下漏洞影响的无线耳机的 Bluetooth 安全评估工具:
Airoha SDK 漏洞链(CVE-2025-20700 / CVE-2025-20701 /
CVE-2025-20702)。它会扫描附近的设备,对已知受影响的
基于 Airoha 的芯片组进行指纹识别,并探测未经身份验证的 GATT 访问和 RACE
协议可达性——完全通过 OS Bluetooth 协议栈 (BlueZ) 和
`bleak` 进行。不需要外部 Bluetooth dongle,也不需要 root 权限。
## 道德使用声明
此工具用于评估您拥有或获得明确授权进行测试的
设备。GATT 和 RACE 探测是主动操作:它们会连接并向
目标设备发送命令。请勿对不属于您或未获得测试许可的
设备运行 `--gatt`、`--race`、`--firmware`、
`--assess`、`--baseline` 或 `--check-drift`。`--scan` 是被动的,
它仅监听已经公开广播的广播包,因此
在信号覆盖范围内对任何设备运行都是安全的。
探测任意附近设备不仅仅是策略问题——它可能
产生实际的副作用。`--gatt` 会尝试对其发现的每个
特征值进行读取或通知订阅,而某些消费类设备会公开预配性质的
服务(例如 Google 的 Fast Pair 服务),这些服务会对此作出反应,在目标
设备上发起真实的配对握手,这与该
工具明确请求的任何操作无关。需要加密的特征值可能会
触发同样的情况,即使在您自己的设备上也是如此,因为 BlueZ 可以静默地
将该身份验证请求路由到您的桌面已注册的任何代理
(例如 KDE 的配对提示)——因此,每个主动命令还会注册
其自己的临时 BlueZ 代理,在探测
期间自动拒绝任何此类请求,这样就不会出现任何配对提示。每个主动
命令在通过无线电波执行任何操作之前,仍会提示您确认目标地址
属于您;一旦您确认这是您的设备,传递 `--yes` 即可跳过
提示以用于脚本化操作:
```
buds_audit.py --assess --target AA:BB:CC:DD:EE:FF --yes
```
`--watch` 是被动的,就像 `--scan` 一样——它仅监听
已经在广播的广播包,从不连接任何设备,因此它不会
提示确认。
## 安装
```
python3 -m venv venv
venv/bin/pip install -r requirements.txt
```
需要 Python 3.10+(基于 3.14 开发)以及运行
BlueZ 且 Bluetooth 适配器已开启的 Linux 系统。
## 平台支持
仅支持 Linux,且并非自动支持所有 Linux 系统:
- **不支持 Windows。** `bleak` 本身有一个 Windows 后端,但
此工具并不仅仅依赖于 bleak——Bluetooth Classic 发现
(`core/scanner.py`) 和绑定状态检查 (`core/gatt.py`) 都会直接
通过 shell 调用 `bluetoothctl`,这是一个 BlueZ 专属的 CLI 工具,在
Windows 上并不存在。这些代码路径会直接报错“command not found”。
- **需要 PATH 中包含带有 `bluetoothctl` 的 BlueZ**,而不仅仅是任何 Linux
内核。大多数桌面发行版都自带该工具;但若没有安装 `bluez` 包的最小化或
服务器镜像则默认没有该工具。已在 BlueZ 5.86 上验证
可免 root 运行——其他版本的工作方式应该相同,因为
bleak 针对的是 BlueZ 的标准 D-Bus API,但这并未经过
独立的重新验证。
- **WSL 取决于硬件,不能简单地说“行”。** WSL2 可以像
任何 Linux 一样运行 BlueZ,但要连接真实的 Bluetooth 无线电模块,需要
通过 `usbipd-win` 从 Windows 转发它,
而该工具只能转发 USB 接口的适配器。
大多数笔记本电脑内置的 Bluetooth 是通过非 USB
总线(SDIO/PCIe,与 Wi-Fi 共用)连接的,`usbipd-win` 通常无法
转发它们——因此这完全取决于具体的硬件。
## 关于设备电源状态的说明
许多 TWS 耳机在一段
时间不活动后会停止广播(并断开任何活动连接)以节省电量,而有些会完全自行关机。
如果扫描找不到一分钟前刚找到的设备,或者探测
在中途失败,这通常是因为耳机进入了空闲状态,而不是
出现 Bug——将它们从充电盒中取出或再次按下配对按钮,然后
重试。
这也会影响地址稳定性:本项目已确认的测试设备(
Sony WF-1000XM3)在测试过的每次电源循环中都保持了相同的 BLE 地址,
这对于专为配套应用重连而设计的耳机来说是符合预期的——它们
通常使用固定/公开的 BLE 地址,而不是轮换地址(不同于
手机,因为手机确实会轮换私有地址,并且由于该原因,它们不是此工具
的合适目标)。然而,这并不能保证适用于所有耳机型号
——一些厂商即使在
预配/重连模式下也会使用可解析的私有地址,这对于像此工具这样
未配对的扫描仪来说,会在每次电源循环后显示为不同的地址。
## 交互模式
```
buds_audit.py
```
在完全不使用任何标志运行该程序时,会启动一个带编号的菜单,而
不是要求您必须已经知道 BLE 地址或知道哪个标志
起什么作用:
```
1) Full analysis (scan, run the full CVE audit, and save a baseline)
2) Check current state against a saved baseline
3) Scan for spoofed/impersonating devices
4) Exit
```
选项 1 扫描附近的已知受影响设备并列出它们供您
按编号选择(而不是输入 MAC 地址),运行完整的 CVE 审计
(同 `--assess`),并保存基线(同 `--baseline`),以便未来的
运行可以检测到变化。选项 2 列出您已经记录过基线的
设备并重新检查您选择的设备是否有偏移(同 `--check-drift`)。选项
3 是 `--watch`。在通过无线电波进行任何操作之前,每个
选项仍然会像基于标志的界面一样进行相同的所属权
确认——向导只是完全相同底层检查的一个
更友好的前端,而不是一条独立的、不够严谨的
路径。
对于脚本化操作或任何已经知道自己想要
定位的地址的用户,下面基于标志的界面依然适用。
## 用法
所有命令均通过 `venv/bin/python buds_audit.py` 运行。
```
buds_audit.py --help
```
即使在没有任何 venv 且未安装任何
依赖项的情况下,仅运行纯粹的 `python3 buds_audit.py --help` 也能
工作——直到运行实际需要无线电模块的命令之前,它不会
导入 bleak。
### 发现
```
buds_audit.py --scan
buds_audit.py --scan --flags-only # only show devices matching the known-affected catalog
buds_audit.py --scan --target AA:BB:CC:DD:EE:FF
```
被动扫描附近的 BLE 和 Bluetooth Classic 设备,通过
制造商数据和地址前缀对 Airoha 芯片组进行指纹识别,并
与 `data/affected_devices.json` 进行交叉比对。
### 单项探测
这些选项中的每一个都需要 `--target ADDR`,并且都是针对
该单一设备的主动操作:
```
buds_audit.py --gatt --target AA:BB:CC:DD:EE:FF # CVE-2025-20700: unauthenticated GATT access
buds_audit.py --race --target AA:BB:CC:DD:EE:FF # CVE-2025-20702: RACE channel reachability
buds_audit.py --firmware --target AA:BB:CC:DD:EE:FF # CVE-2025-20701: passive firmware/pairing-bypass check
```
如果设备已经配对,这三个操作都会正常跳过
(无报错)——因为针对已绑定的设备得出的“未经身份验证的访问”
发现是毫无意义的。
### 全面评估
```
buds_audit.py --assess --target AA:BB:CC:DD:EE:FF
buds_audit.py --assess --target AA:BB:CC:DD:EE:FF --json result.json
```
针对一个目标运行上述所有三个探测,并得出一个单一的
结论:`PASS`、`PARTIAL`、`VULNERABLE` 或 `SUSPECTED_COMPROMISE`。`--json`
还会将完整结果(设备信息、结论、标志、证据、
修复建议)写入文件。
`--assess` 被特意设计为仅针对单一目标,这与
单项
探测相同——没有“评估范围内所有设备”的模式,因为这
意味着要主动探测可能不属于您的设备。
### 入侵评估(基线与偏移)
```
buds_audit.py --baseline --target AA:BB:CC:DD:EE:FF
buds_audit.py --check-drift --target AA:BB:CC:DD:EE:FF
```
`--baseline` 会在您首次
评估设备时捕获其受信任的快照——身份(名称和制造商数据)、GATT 表、RACE 固件
构建版本以及本地绑定状态(仅限已配对/受信任/已绑定的布尔值,绝不
包含密钥材料)——并将其存储在 `data/device_baselines.json` 中。它
绝对不会自动捕获;您必须明确请求该操作,并且
再次运行它会覆盖现有的基线。
`--check-drift` 会重新捕获相同的快照,并将其与
存储的基线进行比较,根据发现的任何偏移
得出结论:
`IDENTITY_DRIFT`、`GATT_TABLE_DRIFT`、`FIRMWARE_DOWNGRADE` 或
`BOND_STATE_DRIFT`。这回答的是“自上次我
信任此设备以来是否发生了某些变化”,而不是“此设备是否存在漏洞”——它是一种启发式
入侵信号,而非取证证明。任何带有偏移标志的设备都会被赋予
`SUSPECTED_COMPROMISE` 结论,该结论优先于其他所有结果。
### 模拟 / 中继监控
```
buds_audit.py --watch
```
在固定时间窗口内持续扫描(按 Ctrl+C 停止),并通过
名称和制造商数据关联
接收到的每一个广播包。如果两个不同的
地址广播了相同的身份,并且观察窗口存在重叠——
意味着两者在同一时间以该身份在无线电波中
出现——它就会标记 `POSSIBLE_IMPERSONATION`。单个物理设备随时间
轮换其 BLE 地址(按时间顺序被观测到,而非同时)
不会被标记;只有真正的
第二个发射源才会被标记。这映射到威胁模型的最后一步:
向受害者的手机模拟耳机。
## 已知受影响设备
`data/affected_devices.json` 是一个经过精心整理的目录,而非
详尽的列表。目前已确认的包括:
| 品牌 | 型号 | Airoha SoC | CVE | 已修复固件 |
|-------|-------|------------|------|-------------------|
| Sony | WF-1000XM3 | AB1562 | CVE-2025-20700, CVE-2025-20701, CVE-2025-20702 | 暂未发布 |
根据 ERNW 的披露,其他使用 Airoha AB1562/AB1565/AB1568 系列
SoC 的品牌(包括 Bose、Jabra、JBL、Marshall 以及补丁发布前的 Beats 型号)
也被报告受到影响,但尚未被纳入目录,因为在本
项目中尚未针对真实硬件确认它们确切的
地址前缀和芯片组详细信息。目录之外的设备仍然可以通过
`--gatt`/`--race`/`--firmware`/`--assess` 进行主动
探测——该目录仅影响
被动的 `--scan` 匹配和结论权重,而不影响
探测本身所测试的内容。
## 针对 CVE-2025-20701 主动测试的硬件要求
此工具仅通过 RACE 固件构建版本检查被动地
评估 CVE-2025-20701(缺少 Bluetooth Classic 配对
强制执行)。
主动测试是否可以完成静默配对握手需要通过
[Bumble](https://github.com/google/bumble) 获得原始 HCI 访问权限以及
一个专用的兼容 Bumble 的 USB Bluetooth dongle——这通过
BlueZ/bleak 是无法实现的,这也是此工具不尝试执行此操作的原因。有关涵盖所有三个 CVE 的
基于 dongle 的交互式
参考实现,请参阅 ERNW 的 [race-toolkit](https://github.com/auracast-research/race-toolkit)。
## 致谢
Airoha SDK 漏洞链(CVE-2025-20700 / CVE-2025-20701 /
CVE-2025-20702)是由 ERNW 的 Dennis Heinze 和 Frieder
Steinmetz 发现并披露的。他们的 [race-toolkit](https://github.com/auracast-research/race-toolkit)
是本项目旨在填补无 dongle 空白时所参考的实现,
并且这里使用的精确 RACE 协议 GATT UUID 和数据包组帧是
直接从其源码中读取的,而不是猜测的——具体情况请参阅 `core/race.py`。
race-toolkit 是无授权的(没有 `LICENSE` 文件,
已直接针对该代码库进行了检查)——除了
底层协议事实(UUID、结构体布局、命令代码)之外,此项目没有复用其源码中的任何内容,
这些事实描述的是 Airoha 自己的协议,并非
其作者需要授权的原创表达。
## 许可证
MIT - 参见 [LICENSE](LICENSE)。
## 开发
```
venv/bin/ruff check . --fix && venv/bin/ruff format .
venv/bin/python -m pytest tests/
```
标签:AES-256, bleak, Python, 插件系统, 无后门, 漏洞评估, 物联网安全, 蓝牙安全, 逆向工具