aaronsb/bosectl

GitHub: aaronsb/bosectl

在Linux上通过逆向Bose BMAP蓝牙协议实现对QC Ultra 2等耳机的本地控制,无需官方应用、云服务或账户。

Stars: 4 | Forks: 1

# bosectl [![MIT 许可证](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Python 3](https://img.shields.io/badge/Python-3-green.svg)](https://www.python.org) [![平台:Linux](https://img.shields.io/badge/Platform-Linux-orange.svg)](https://kernel.org) [![Bose BMAP](https://img.shields.io/badge/Bose-BMAP-black.svg)](https://www.bose.com) **在 Linux 上控制 Bose 耳机 — 无需应用、云服务或账户。** ![bosectl CLI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/01d95182eb171251.png) 一个对 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, 云资产清单, 协议破解, 无应用控制, 消费电子, 物联网, 硬件控制, 空间音频, 耳机控制, 蓝牙, 蓝牙协议, 设备控制, 逆向工程