aaronsb/bosectl
GitHub: aaronsb/bosectl
在Linux上通过逆向Bose BMAP蓝牙协议实现对QC Ultra 2等耳机的本地控制,无需官方应用、云服务或账户。
Stars: 4 | Forks: 1
# bosectl
[](LICENSE)
[](https://www.python.org)
[](https://kernel.org)
[](https://www.bose.com)
**在 Linux 上控制 Bose 耳机 — 无需应用、云服务或账户。**

一个对 Bose BMAP 协议进行逆向工程实现的工具,可让您完全控制
降噪、EQ、空间音频、设备设置等。所有功能都通过直接的蓝牙 RFCOMM 连接与耳机通信。
## 功能概述
```
$ ./bosectl status
Battery: 70%
Mode: quiet
CNC: 7/10
EQ: +3/+0/-2
Name: Fargo
FW: 8.2.20+g34cf029
Sidetone: medium
Multipoint: on
AutoPause: on
Prompts: off (US English)
$ ./bosectl cnc 8 # Set noise cancellation level (0-10)
$ ./bosectl eq 5 0 -3 # Set EQ: bass=+5, mid=0, treble=-3
$ ./bosectl spatial head # Spatial audio with head tracking
$ ./bosectl quiet # Switch to Quiet (full ANC) mode
$ ./bosectl name "My Cans" # Rename your headphones (any UTF-8 string)
```
### 完整命令列表
| 命令 | 描述 |
|---------|-------------|
| `quiet` `aware` `immersion` `cinema` `home` | 切换音频模式 |
| `cnc <0-10>` | 设置降噪级别 |
| `eq <低音> <中音> <高音>` | 设置 EQ(每个 -10 到 +10)|
| `eq flat` | 重置 EQ 为 0/0/0 |
| `spatial ` | 空间音频模式 |
| `name [文本]` | 获取/设置设备名称 |
| `sidetone ` | 侧音级别 |
| `multipoint ` | 切换多点连接 |
| `autopause ` | 摘下耳机时自动播放/暂停 |
| `autoanswer ` | 自动接听来电 |
| `prompts ` | 切换语音提示 |
| `pair` | 进入蓝牙配对模式 |
| `off` | 关闭耳机 |
| `status` | 显示所有当前设置 |
| `battery` | 电池百分比(仅数字)|
| `current` | 当前模式名称(仅单词)|
| `buttons` | 显示按钮映射 |
| `dump` | 转储所有 AudioModes 状态 |
| `raw <十六进制>` | 发送原始 BMAP 数据包 |
## 环境要求
- **Linux** 系统且已安装 BlueZ(几乎每个发行版都自带 — 这是标准的
Linux 蓝牙栈)
- **Python 3.6+**(仅使用标准库 — 无需 pip install)
- **蓝牙**适配器(内置或 USB dongle)
- **Bose 耳机**已与电脑配对(QC Ultra 2、QC35 及可能的其他型号)
无需:Bose 应用、Bose 账户、网络连接、手机。
## 快速开始
### 1. 配对耳机
如果您的耳机已经与 Linux 电脑配对(您可以通过它们听到音频),请跳到步骤 2。
否则,将耳机进入配对模式(向上滑动电源开关并保持,直到 LED 闪烁蓝色),然后:
```
bluetoothctl
> scan on
# 等待您的耳机出现,然后:
> pair XX:XX:XX:XX:XX:XX
> trust XX:XX:XX:XX:XX:XX
> connect XX:XX:XX:XX:XX:XX
> exit
```
将 `XX:XX:XX:XX:XX:XX` 替换为扫描输出中显示的 MAC 地址。
### 2. 下载并运行
```
git clone https://github.com/aaronsb/bosectl.git
cd bosectl
chmod +x bosectl
./bosectl status
```
`bosectl` 会使用 Bose 厂商 UUID 自动检测已配对设备列表中的 Bose 耳机 — 无需配置 MAC 地址,即使您已重命名耳机。
### 3. 试用一下
```
./bosectl status # See everything
./bosectl cnc 7 # Set noise cancellation to 7/10
./bosectl eq 3 0 -2 # Bass +3, mid flat, treble -2
./bosectl spatial head # Spatial audio with head tracking
./bosectl profile set Work cnc=8 spatial=off # Save a custom profile
./bosectl Work # Switch to it by name
./bosectl quiet # Back to full ANC
```
### 故障排除
- **"连接失败"** — 确保耳机已开机、已配对并通过蓝牙连接。一次只能有一个 RFCOMM 连接活动,因此请先关闭任何已连接手机上的 Bose 应用。
- **"未找到 Bose 设备"** — `bosectl` 通过厂商 UUID 检测 Bose 耳机,因此即使设备已重命名也能正常工作。如果自动检测失败,请设置 `BOSE_MAC=XX:XX:XX:XX:XX:XX` 作为环境变量。
- **"设备或资源忙"** — 等待一下再重试。耳机在蓝牙连接之间需要短暂的冷却时间。
无需安装 Bose 应用、Bose 账户或网络连接。
## 工作原理
Bose 耳机通过蓝牙 SPP/RFCOMM 通道 2 使用名为 **BMAP**(Bose 消息和协议)的协议进行通信。每个设置 — ANC 模式、EQ、设备名称、按钮映射 — 都通过 BMAP 数据包进行读取和写入。
### BMAP 数据包格式
```
[fblock_id, function_id, flags, payload_length, ...payload]
flags byte: (device_id << 6) | (port_num << 4) | (operator & 0x0F)
```
协议由**功能块**(相关特性的组)和**操作符**(您想要执行的操作)组成:
| 操作符 | ID | 描述 |
|----------|----|-------------|
| SET | 0 | 写入值(持久)|
| GET | 1 | 读取值 |
| SETGET | 2 | 写入并读回 |
| STATUS | 3 | 非请求状态通知 |
| ERROR | 4 | 错误响应 |
| START | 5 | 触发操作 |
| RESULT | 6 | 操作完成 |
### 认证缺口
Bose 将写操作保护在云端介导的 ECDH P-384 认证之后。当应用想要更改设置时,耳机发出挑战,应用将其转发到 Bose 的云服务器(`nadc.data.api.bose.io`),Bose 对其签名,应用再将响应中继回。只有这样耳机才会接受 SET 命令。
**但 Bose 并没有对每个操作符都进行认证。** 通过协议分析,我们发现了认证策略中的三个缺口:
1. **AudioModes(块 31)上的 START 未认证。** 这是应用用于实时模式切换的操作符。它可以让我们在 Quiet、Aware、Immersion、Cinema 和自定义模式之间即时切换。
2. **AudioModes 上的 SETGET 未认证。** 虽然 SET 需要认证,但 SETGET(写入并读回)不需要。自定义模式槽(索引 5-10)接受完整配置:CNC 级别、空间音频、风噪屏蔽、ANC 切换和模式名称。预设模式(0-3)无论认证与否都由固件锁定。
3. **Settings(块 1)上的 SETGET 未认证。** 整个 Settings 块 — EQ、设备名称、侧音、多点、自动播放/暂停、按钮映射 — 都接受 SETGET 而无需认证。只有 Settings 块上的 CNC 级别 [1.5] 需要认证(但我们通过 AudioModes 绕过这一点)。
最终结果是:Bose 应用能做的,我们都能做到,无需应用。
## 我们是如何发现的
### 蓝牙探索
我们通过 RFCOMM 连接到耳机并探测所有通道(1-30)。通道 2 返回 BMAP 协议数据。我们通过发送 GET 请求并观察哪些返回 STATUS vs ERROR 响应来枚举所有功能块和函数。
### 流量拦截
为了理解您在切换设置时应用发送的内容,我们通过 Android 的 HCI snoop 日志和 `btsnoop` 捕获蓝牙流量。我们编写了 `bmap-capture.py` 来自动化设置更改前后的快照 — 它读取每个已知的函数,等待您在应用中更改设置,再次读取,然后对比差异。`captures/` 目录包含这些会话的原始数据。
### 云 API 分析
我们拦截了应用的 HTTPS 流量以了解认证流程。应用使用 QUIC/HTTP3(回退到 HTTPS)与 `nadc.data.api.bose.io` 通信,并执行由 Bose 服务器签名的 ECDH 密钥交换。没有这个云签名,耳机不会接受 SET 命令。
当我们注意到即使云 API 被 DNS 劫持,应用仍然可以切换 ANC 模式时,突破了这一点。对比切换前后的所有 BMAP 流量发现,应用使用的是块 31(AudioModes)上的 START,而不是块 1(Settings)上的 SET。START 操作符没有认证检查。
### 系统性操作符测试
一旦我们理解了 START 上的认证缺口,我们就系统性地测试了每个功能上的每个操作符。这发现 SETGET 在 AudioModes 和 Settings 块上也都未认证 — 这是一个比 START 大得多的漏洞。
## 协议参考
完整协议文档在 [NOTES.md](NOTES.md) 中,包括:
- 完整功能块映射(块 0-31)
- 所有 Settings 函数及其有效载荷格式
- ModeConfig SETGET 有效载荷结构(40 字节)
- 按钮重映射协议(ID、事件、操作模式)
- 语音提示语言代码
- 认证系统详情(ECDH P-384、云端点)
- BMAP 错误代码
## 兼容性
已测试:
- **Bose QC Ultra 2**(代号 "wolverine",QCC-384)— 固件 8.2.20
- **Bose QC35**(代号 "baywolf",CSR8670)— 固件 4.8.
BMAP 协议在 Bose 的蓝牙产品线中通用。其他型号(QC 45、QC Ultra Earbuds、NC 700 等)可能使用类似的功能块 — 添加新设备只是一个带有正确地址的配置字典。
## 包含的工具
| 文件 | 描述 |
|------|-------------|
| `bosectl` | 用于控制耳机的 CLI 工具 |
| `bmap-capture.py` | 交互式捕获工具 — 在设置更改前后拍摄所有 BMAP 状态的快照 |
| `captures/` | 设置切换实验的原始捕获数据 |
| `NOTES.md` | 完整协议文档和逆向工程笔记 |
## 许可证
MIT
标签:ANC降噪, BMAP协议, Bose, EQ调节, Python3, QC Ultra 2, RFCOMM, 云资产清单, 协议破解, 无应用控制, 消费电子, 物联网, 硬件控制, 空间音频, 耳机控制, 蓝牙, 蓝牙协议, 设备控制, 逆向工程