jtmuller5/samsung-galaxy-ring-client

GitHub: jtmuller5/samsung-galaxy-ring-client

绕过手机与 Samsung 应用,通过 BLE 直接与 Galaxy Ring 配对通信、读取健康历史数据并拦截手势事件的逆向工程工具包。

Stars: 0 | Forks: 0

# Samsung Galaxy Ring — 直连 BLE 客户端与协议工具包 一款 Electron 应用,可通过 **BLE 直接与 Samsung Galaxy Ring 通信——无需手机,无需 Samsung 应用**——与其配对,执行握手流程,并读取数据。该工具基于 Android 的 HCI-snoop 抓包对 Ring 的协议进行了逆向工程研发,秉承了 [open_oura](https://github.com/Th0rgal/open_oura) 的开源精神。 ## 当前状态 — 运行正常 ✅ - **在 Mac 上与 Ring 配对**,采用 **LE Secure Connections "Just Works"**(无需密码,也无需 Samsung 密钥),随后在 `1b1b` 通道(notify `797ae4e9…` / write `63e30bad…`)上执行完全解码的 **plaintext** 握手协议。 - **拉取 Ring 存储的健康历史数据**——包括心率记录和原始高速传感器数据流——并实时将其绘制成图表。 - **拦截双指捏合手势**,作为 Mac 端的实时触发器。 - 整个协议基于 **plaintext TLV——无任何加密**;唯一的门槛在于建立 BLE 配对。完整规范详见 [`docs/protocol.md`](docs/protocol.md)。 ## 已知限制 - **无法获取实时原始传感器数据流。** Ring 在设备端处理传感器数据,且仅输出**批量历史数据 + 处理后的事件**——此结论已在心率(HR)、手势和运动数据的抓包中验证。因此,实时原始加速度计数据(用于触发任意自定义动作)**并未对外暴露**;目前唯一可用的实时触发器是双指捏合事件。 ## 应用界面(5 个标签页) | 标签页 | 功能 | |-----|---------| | **Recon** | 扫描 / 连接 / 发现 GATT;读取 / 订阅 / 写入;实时通知显示为带时间戳的 HEX + ASCII;导出 TSV。自动标记可能的命令通道。 | | **Replay** | 向选定的 notify/write 通道发送解码后的初始化握手协议(带有用于实时时间的 `{EPOCH}` token);在响应前等待 Ring 发出 hello。 | | **Health** | 一键操作:握手 → `0a0a` token-echo 同步 → 将 `3f` 记录解码为 **HR + 原始数据流图表**。 | | **Gesture** | 启用手势模式(`161600`)并在每次**双指捏合**(`1616 02…`)时触发——作为实时触发器。 | | **Analyzer** | 导入 Android `btsnoop_hci.log`;解码 **ATT / SMP / classic-L2CAP / RFCOMM**;提供数据流解析、handle→UUID 映射以及 **双抓包差异对比**。 | ## 快速开始 ``` npm install # also rebuilds the native BLE module (noble) for Electron npm run dev # electron-vite dev --watch (the GUI toolkit) ``` ## `ring-pinchd` — 无头捏合守护进程(适用于宏自动化应用) 一个微型的常驻进程,用于**独占 Ring 的连接**(自动连接 + 自动重连 + 心跳保活),执行握手协议,启用手势模式,并在**每次双指捏合时发出信号**。无 GUI。复用本项目基于 Electron 构建的 noble 库。 ``` # 每次 pinch 时向 stdout 打印一行 JSON npm run pinchd # {"type":"pinch","count":1,"t":1782412345678} # 在每次 pinch 时运行 shell 命令(最简单的 macro 集成) RING_ON_PINCH='osascript -e "tell application \"System Events\" to keystroke space"' npm run pinchd # 或者 POST 到你的 macro 应用监听的本地 webhook npm run pinchd -- --webhook http://localhost:8910/pinch ``` 提供三种消费途径(任选其一):**stdout** 输出的 JSON lines · **`--on-pinch ""`**(或使用 `RING_ON_PINCH`)· **`--webhook `**(或使用 `RING_WEBHOOK`)。状态和日志会输出到 stderr,从而确保 stdout 始终输出纯净的事件流。可用的配置选项包括:使用 `--name ` / `--address ` 来指定设备,`--keepalive `(默认值为 25000)。 “是否已连接?未连接则发起连接”这一过程是完全自动化的——守护进程会自动扫描、连接,并在断线时静默重连,因此宏自动化应用只需关注捏合信号的消费即可。由于 Ring 采用单设备配对机制,请先在手机端解除配对,且切勿同时运行 GUI 应用与守护进程(因为同时只能维持一个 BLE 连接)。 在 macOS 上,必须授予**蓝牙**权限(系统设置 → 隐私与安全性 → 蓝牙),否则适配器状态会一直停留在 `unauthorized`。如果遇到原生模块的 ABI 错误,请运行 `npm run rebuild`。 ## 我们是如何抓取协议数据的 在与 Ring 配对的**手机端**进行 HCI 抓包(此操作可捕获已*解密*的 ATT 层;而在空中拦截抓包到的数据将是加密状态)。无需 root 权限: 1. 手机 → 开发者选项 → **Bluetooth HCI snoop log = Enabled**,随后关闭再打开蓝牙。 2. 打开 Galaxy Wearable / Samsung Health,使其重新连接并同步 Ring 数据。 3. 通过错误报告提取日志文件: adb bugreport ring-capture.zip unzip -j -o ring-capture.zip "FS/data/log/bt/btsnoop_hci.log" -d captures/ 4. 在应用的 **Analyzer** 标签页(或使用过滤条件为 `btatt` 的 Wireshark)中打开 `captures/btsnoop_hci.log`。 ## 解码后的握手协议(相对于连接建立后的时间) ``` t=0.00 APP→ WRITE 0x0004 = 0100 enable Service Changed indications t=0.07 APP→ WRITE 0x0024 = 0100 enable notifications on 0x0023 (CCCD) t=2.13 RING→ NOTIFY 0x0023 a70001010103... ring hello: "Samsung Electronics" / "Galaxy Ring" / SN_ t=2.13 APP→ WRITE 0x0026 a700010101012400...SAMSUNG identity ack t=2.14 APP→ WRITE 0x0026 01018301...0a "1782393760" TIME SYNC (unix time as ASCII digits) t=2.14 APP→ WRITE 0x0026 0101010402050010 / 0101020101 session config t=2.19 RING→ NOTIFY 0x0023 01014101...... TLV device info (FW, model SM-Q501, serial ) t=2.19 RING→ NOTIFY 0x0023 01014201 01 02 00 03 01... capability flags t=2.2+ APP→ WRITE 0x0026 0b0b02 / 1f1f31 / 161601 / 141400 / 2020…email enable data channels t=2.2+ RING→ NOTIFY 0x0023 (data starts streaming on those channel tags) ``` ## 数据帧封装 两个子协议共用 `0x0026`/`0x0023` 通道: - **控制协议** — header 格式为 `01 01 01 …`,payload 采用 TLV 编码。 - `0x83` = 设置时间,`0x41`/`0x42`/`0x43` = 设备信息 / 能力响应(bit7 = 命令,bit6 = 响应)。 - **通道协议** — 第一个字节是通道标签,采用双重叠加格式(`TT TT …`): - `0a0a` 健康 / 活动历史(payload 包含小端序时间戳 `e0xx27…` + 采样数据) - `0b0b` 状态 / 电量 - `1f1f` 设备状态 - `1414` 闹钟 - `1616` 设置 - `2020` 账户(抓包观察发现应用会将 Samsung 账户邮箱写入 Ring) ## 实测结果:确认存在配对/注册门槛 从一个**全新的、未配对的中心设备**(本应用在 Mac 上运行)发起连接并订阅通道的 notify 特征值时,Ring 仅回复了**一个固定的状态数据包,除此之外没有任何响应**——未发出 `a7` hello: ``` notify 79d34772-…-2b50a4a2b27 / 2fb6a5aa-…-f70613cd 03 10 00 00 00 11 01 00 00 00 00 01 00 01 00 00 00 00 00 00 01 (identical across connections) ``` 手机之所以能立即收到完整的 `a7` hello,是因为它已经**完成配对并注册了账户**(注意:应用在设置阶段会将 Samsung 账户邮箱写入设备)。 因此,协议的门槛在于 **链路层配对 + 应用层注册**,而不是带内加密认证。未受信任的中心设备只能收到静态的 `03 10…` 数据包。 **为了绕过这一限制**,我们需要抓取建立*信任*过程的数据——即在开启 HCI snoop 的状态下,在 Galaxy Wearable 中移除并重新添加 Ring——以此来观察 SMP 配对过程和注册写入指令。正是为了满足这种分析需求,Analyzer 现已支持解码 SMP(L2CAP CID 0x0006)。 客观来讲,这使我们陷入了与 open_oura 相同的处境:作为单配对且与账户绑定的设备,如果想要接入,可能需要:(a) 为新中心设备重新建立配对 + 重放注册流程(前提是 Ring 允许第二个配对,且注册流程未受密钥锁定),或者 (b) 从已 root 的手机中提取配对密钥 (LTK/IRK) 并将其导入宿主机 BLE 协议栈—— 而这在 **macOS/CoreBluetooth/noble 上是做不到的**;该方案需要 **Linux/BlueZ** 环境(在其中可以将 LTK 预加载到 `/var/lib/bluetooth` 目录下),这也是 open_oura 项目所采用的方法。 ## Ring 基于 BLE;障碍在于 BLE 配对/信任机制 早期对重新配对抓包数据的分析曾暗示该 Ring 使用了 Bluetooth *Classic*(RFCOMM/SAP)。**这是错误的**——因为该抓包数据中还包含了一块已配对的 **Galaxy Watch5**,那约 1.9 万条 RFCOMM 数据包其实是*手表*的 Samsung Accessory Protocol 通信数据,而非 Ring 的。通过过滤 ATT 协议可清晰发现 Ring 完全基于 **BLE**:它在 notify handle `0x23` / write handle `0x26` 上发出了相同的 `a7` hello(包含 "Samsung Electronics"、"Galaxy Ring (C085)"、型号 SM-Q501、序列号 RFAX81DZD…)。 因此,`@abandonware/noble` **完全可以**与 Ring 通信——传输层没有问题。唯一的障碍是 **BLE 信任机制**:手机端已完成配对/注册,而 Mac 并没有。因此,Ring 对我们的写入指令回复的是 `03 10…` nack,而不是 `a7` hello 及其后续数据。Analyzer 虽然也支持解码 classic L2CAP + RFCOMM + SAP(这对分析手表或未来的抓包数据很有用),但 Ring 本身并不涉及这些协议。 **通过最新获取的配对抓包已完全查明**(详见 `docs/protocol.md`): - 通道 UUIDs:notify 为 **`797ae4e9-…-b5c79599fb9b`** / write 为 **`63e30bad-…-e47cbf7a4b5d`**,隶属于 **`00001b1b`** 服务(必须选择*第二个*完全相同的实例;`1b1a` 是对应的错误孪生实例)。 - 配对模式为 **LE Secure Connections "Just Works"**(Ring 的 IO 属性为 NoInputNoOutput,无 MITM 防护,无 OOB)→ **任意中心设备均可配对,无需密码,无需 Samsung 密钥。** 信任门槛仅仅是 Mac 也能建立的标准 BLE 配对。配对流程与协议中均不存在加密/账户壁垒。 **✅ 已达成目标 (2026-06-25):** 在手机端解除配对后,Mac 成功通过 Just Works 配对与 Ring 建立连接,并在 `1b1b` 通道(notify `797ae4e9` / write `63e30bad`)上执行了解码后的握手协议。Ring 完整响应了全流程数据——包括 `0143` ack、`0141` 设备信息、`0142` 能力信息,以及 `0b0b`/`1f1f`/`1414`/`0a0a` 数据通道——在无手机且无 Samsung 应用的情况下直接将数据流传输到了 Mac。关键操作在于:通过 Just Works 配对,精准定位 `1b1b` 通道,发送**原汁原味的 167 字节 `a7` ack**,并且仅在收到 Ring 的 hello 之后再进行回复。 **下一步:实时传感器数据流。** 握手过程可获取设备/状态/配置数据;而如果要提取实时的 HR / SpO2 / 温度数据或传感器历史记录,则需要使用特定的 `0a0a` 请求指令——可以通过抓包分析官方应用发起测量时的操作来破解这些指令,随后进行重放。 ## 重放测试结论与注意事项 1. **显然只有时间戳是动态变化的。** 建议再抓取 1-2 次会话数据,并使用 Analyzer 的 **diff(差异对比)** 功能来确认每次连接时是否只有时间戳发生变化。如果变动的只有时间字段 → 说明这是纯粹的重放。 2. **配对状态可能是准入的关键。** Ring 会与手机建立配对(链路层 SMP),并且可能只允许**单设备配对**。当从新的中心设备(本应用)发起连接时,预计会触发配对提示;您可能需要先在手机端“忽略”该 Ring。请检查抓包数据中连接建立点附近的 `btsmp` 数据包。 ## 待解决问题 / 后续步骤 - [ ] 对比多次抓包数据,锁定确切的动态变化字段。 - [ ] 确认 Ring 是否允许第二台设备配对,还是仅限单设备配对。 - [ ] 将 `0a0a` 健康历史 TLV(时间戳 + 采样数据结构)解码为 HR / 体温 / 运动数据。 - [ ] 利用包含 GATT discovery 过程的抓包数据(本次未包含该过程),建立 ATT handles 到 UUIDs 的映射。 - [ ] 确定是哪个通道使能写入指令开启了**实时**传感器流,以及哪个指令是用于历史数据同步的。 ## 架构设计 - `src/main/ble.ts` — noble BLE 封装(单连接;类型化事件)。 - `src/main/btsnoop.ts` — btsnoop → HCI → L2CAP → ATT 解码器。 - `/main/index.ts` — 窗口管理与 IPC 通信。 - `src/preload/index.ts` — 类型化的 `window.ring` 桥接。 - `src/shared/types.ts` — 跨进程共享的 IPC 契约。 - `src/renderer/src/` — React UI 界面(`useRing` hook + Recon / Replay / Analyzer)。 ## 致谢 研究方法论灵感来源于 [Th0rgal/open_oura](https://github.com/Th0rgal/open_oura)。
标签:Electron桌面应用, MITM代理, 云资产清单, 数据可视化, 智能穿戴设备, 物联网(IoT), 自动化攻击, 蓝牙低功耗(BLE), 逆向工程