qbsm/navee-k100-max-ble

GitHub: qbsm/navee-k100-max-ble

NAVEE Kids K100 Max 电动滑板车的逆向工程笔记,涵盖 BLE 协议、OTA API、固件分析及配套工具,供互操作性研究使用。

Stars: 0 | Forks: 0

# NAVEE Kids K100 Max — BLE 协议与固件说明 **NAVEE Kids K100 Max** 电动滑板车逆向工程笔记 (产品 2026,PID `25062`,SKU 系列 `T2506xx`)。涵盖完整的 BLE 控制 协议、设置布局、OTA API 以及固件分析。 **针对常见问题“如何在 EU 版本上解锁 20 km/h?”的 TL;DR:** 你无法通过 OTA 实现。固件中的速度表 *确实* 包含 20 km/h, 但区域(EU → 16 km/h 限制)源自序列号,每个型号只有一个 固件,并且 **OTA 镜像是 ECDSA 签名的**,因此修补过的 镜像会被 bootloader 拒绝。详情和证据如下。BLE 限速器命令允许你自由设置 8–16 km/h(绕过 App 的家长 限制),但不能超过区域上限。 🇷🇺 [阅读俄语版](README.ru.md) ## 硬件 | 部件 | 芯片 | 备注 | |------|------|-------| | 仪表盘 / BLE ("meter") | ARM MCU w/ mbedTLS | 运行面向 App 的 GATT + 签名 OTA | | Motor controller ("bldc") | **MM32SPIN0280** (MindMotion, Cortex-M0) | 执行速度限制 | | 蓝牙音箱 | Realtek | 独立设备,广播 `K100 Max BT Audio` | 区域编码在**序列号**的第 9-10 位字符中: `T2506xxM`**`EU`**`xxxxxxx`(第 9-10 位字符 = 区域)。App 将其映射为 SKU: `IT/DE/NE → ITA`,`US/CN/RU → USA`,其他所有 → `EUR`。 没有写入序列号的命令。 ## GATT 广播名称 `NAVEE`,广播中包含服务 `1812` (HID)。 | Service | Characteristic | Props | 角色 | |---------|----------------|-------|------| | `0000D0FF-3C17-D293-8E48-14FE2E4DA212` | `B002` | write / write-no-rsp | **命令 → 滑板车** | | `0000D0FF-…` | `B003` | notify | **回复 + 1 Hz 遥测** | | `0000D0FF-…` | `B001` | read | — | | `87290102-3C51-43B1-A1A9-11B9DC38478B` | `6AA50001…000A` | read | Realtek SoC 信息块 | 这些特征值解析为标准基础 UUID (`0000B002-0000-1000-8000-00805F9B34FB`),而不是厂商的 `D0FF` 基础 UUID。 **写入 `B002` 不需要配对/绑定。** ## 帧格式 ``` 55 AA 00 FE FD ``` * `55 AA` 开始,`FE FD` 结束 * `LEN` = payload 长度(在某些回复中为 2 字节) * `CHK` = 从 `55` 到最后一个 payload 字节的每一个字节的总和,**mod 256** 命令的 ACK:`55 AA 00 01 00 FE FD`(`00` = OK)。 App 构建的读取辅助命令: ``` read : 55 AA 00 FE FD write 1B : 55 AA 00 01 FE FD write NB : 55 AA 00 FE FD ``` ## 命令表 从 Android App(`com.uz.navee`,类 `BleHandler`)中解码得出: | 代码 | 含义 | 代码 | 含义 | |------|---------|------|---------| | `0x50` | 解绑 | `0x6C` | 声音 / 音量 | | `0x51` | 锁定 | `0x6D` | 灯光设置 | | `0x52` | 巡航控制 | `0x6E` | 设置速度 / 模式 *(在儿童固件上未实现)* | | `0x53` | 能量回收 | `0x6F` | 滑板车参数(子命令) | | `0x54` | 前大灯 | `0x70` | **读取设置(38 字节)** | | `0x55` | 单位(km/mi) | `0x71` | 读取骑行数据 | | `0x56` | 里程算法 | `0x72` | 读取电池 | | `0x57` | 光线传感器 | `0x73` | 读取固件版本 | | `0x5E` | 环境光 | `0x74` | 读取车辆序列号 | | `0x5F` | TCS | `0x75` | 读取电池序列号 | | `0x60` | 转向灯声音 | `0x76` | 读取骑行日志 | | `0x61` | 靠近解锁 | `0x80` | 天气 | | `0x6A` | 启动速度 | `0x82` | 超速主动控制 | | `0x6B` | **自定义限速器** | `0x90` / `0x92` | 遥测 (1 Hz) | `0x6F` 子命令:`[06, unixtime u32]` 时间同步,**`[08, country]`** 区域。 `0x6E` 子命令:`[01, kmh]` 最高速度,`[02, mode]` 驱动模式 —— **两者都会返回 ACK,但在 K100 Max 固件上会被忽略。** ## 设置块(`0x70`, 38 字节) 字段名称来自 App 自带的解析器: ``` 0 bindingStatus 1 drivingMode 2 lockStatus 3 ccsStatus 4 tailIsOn 5 ersStatus 6 mileageAlg 7 mileageUnit 8 autoSensor 9 tyreSwitch 10 ambientLight 11 tcsSwitch 12 turnSound 13 proximityKey 14 nightMode 15 mileageAlgMode 16 lightE 17 lightD 18 lightS 19 startSpeed 20 limitSpeed 21 volume 22 reportLang 23 logoLight 24 dayRunLight 25 maxSpeed 26 driveMode 27–30 startChargeTime 31 chargeLimit 32 lowPower 33 timedChargeOn 34 lockTime 35 breakSpeed 36 weather 37 slopeSup ``` ### 自定义限速器 (`0x6B`) Payload 字节 = `0x80 | kmh`(bit 7 = “启用限制”)。 已通过 App 的滑块验证: | 滑块 | 帧 | limitSpeed | |--------|-------|-----------| | min | `55 AA 00 6B 01 88 F3 FE FD` | 8 km/h | | mid | `55 AA 00 6B 01 8C F7 FE FD` | 12 km/h | | max | `55 AA 00 6B 01 90 FB FE FD` | 16 km/h | 写入 `0x94` (20) 会被*存储*并在重启后保留,但 ESC 仍然会将 车速限制在区域最大值 —— 限速器只能降低上限,绝不能提高上限。 使用 `0x70` 读取它(第 20 字节)。 现成的帧: ``` set 20 km/h 55 AA 00 6B 01 94 FF FE FD (stored, but not effective — see above) set 16 km/h 55 AA 00 6B 01 90 FB FE FD disable flag 55 AA 00 6B 01 00 6B FE FD read settings 55 AA 00 70 6F FE FD read serial 55 AA 00 74 73 FE FD read fw ver 55 AA 00 73 72 FE FD → "00140034" = meter 0.0.1.4 + bldc 0.0.3.4 ``` ## 遥测 * `0x90` (17 B): `[8][9]` 电池电压(小端 mV,约 22 V),`[1]` 状态位。 * `0x92` (19 B): `[10]` 当前速度(以 0.1 为单位的显示值),`[0]` 电池电量百分比 %。 * `0x76` 骑行日志:四组 u16 `(?, ?, avg, max)` 的速度记录(以 0.1 km/h 为单位)。 观察到的最高值达到 `0xBC` = 18.8 km/h 下坡 —— 该限制纯粹是固件层面的。 ## OTA API 基础地址 `https://lj.naveetech.com/tundra-api`。登录(`POST /login`, `{email,passwd}`)返回一个在 `Authorization` 头中使用的 Bearer JWT。 | Endpoint | Method | 用途 | |----------|--------|---------| | `/login` | POST | `{email,passwd}` → token(密码通过 TLS 明文传输) | | `/vehicle/model` | GET | 型号目录 | | `/vehicle/modelSoftware` | POST | `{vehicleModelId, meter, bldc, bms, screen, uwb}` → 固件列表 | **K100 Max 是 model id `5001`,PID `25062`** —— 一个单独的目录条目,**没有 EU/US 变体**。列表为每个组件返回 `fileUrl`。参见 [`tools/fw_pull.py`](tools/fw_pull.py)。 ### 直接固件链接(撰写本文时的最新版本) 未加密,无需验证即可下载: * meter(仪表盘)`0.0.1.4` — `https://myusnavee.s3.amazonaws.com/2026/06/01/09a6c871f71d4e2ca5e5f03c1d387ea0.bin` * bldc(Motor controller)`0.0.3.4` — `https://myusnavee.s3.amazonaws.com/2026/06/01/525529d5835c47da9968251407eea78f.bin` ## 固件分析 * **bldc.bin** — 头部 `MM32SPIN0280D6FFX`,位于 `0x08000000` 的普通 Cortex-M0 镜像,熵 6.98/8(未加密)。没有可读的字符串;速度 限制在代码中,而不是表中。 * **meter.bin** — 头部 `T2314…`,包含 mbedTLS。重要数据: * 位于 `0x20f95` 的速度阶梯:`04 08 0c 10 14 18 1c …` = 4/8/12/16/**20**/24… km/h * 位于 `0x21a10` 的区域表:`UK CN US AU EU RU` * **存在 ECDSA 验证**:`mbedtls_ecdsa_verify_restartable`, `[OTA] Upgrade verify ok, restarting...`,两个内置的 ECDSA 公钥。 ## 为什么无法通过 OTA 达到 20 km/h 1. **每个型号只有一个固件**,没有区域变体 —— 没有所谓的“US 固件” 可供刷入;区域来自序列号,而序列号是不可写的。 2. 固件速度阶梯中**存在 20 km/h 步进**;上限是一个 区域门控(`EU → 16`),而不是缺少该能力。 3. **OTA 是经过 ECDSA 签名的** —— 修补过的镜像无法通过 `[OTA] Upgrade verify` 并且 会被拒绝。通过 BLE 进行补丁和刷入的途径已被关闭。 剩下的唯一途径是物理层面的:使用 SWD 编程器直接连入 MM32SPIN0280,绕过签名的 bootloader(如果关闭了 flash 读取保护), 并对区域→上限逻辑进行反汇编。风险极高,且无法保证 —— 此处不作介绍。 ## 工具 | 文件 | 用途 | |------|------| | [`tools/navee_ctl.py`](tools/navee_ctl.py) | 读取设置 / 设置限速器 / 发送原始帧 (`bleak`) | | [`tools/pklg_parser.py`](tools/pklg_parser.py) | 将 iOS PacketLogger `.pklg` 抓包解析为 ATT 流量 | | [`tools/fw_pull.py`](tools/fw_pull.py) | 查询 OTA API 以获取固件下载链接 | ``` pip install bleak python tools/navee_ctl.py read python tools/navee_ctl.py limit 16 ``` ## 在 iOS 上抓取 BLE(无需越狱) 1. 安装 Apple 的 **Bluetooth Logging Profile for iOS/iPadOS** (developer.apple.com/bug-reporting/profiles-and-logs) 并 **重启**。 2. 驱动 App;然后触发 sysdiagnose:**同时按下音量键和侧边键**,持续约 1.5 秒。 3. 设置 → 隐私与安全性 → 分析与改进 → 分析数据 → `sysdiagnose_*.tar.gz`。 4. `logs/Bluetooth/bluetoothd-hci-latest.pklg` → `tools/pklg_parser.py`。 afterward(它会记录附近所有的 BLE 设备)。 ## 贡献 有 K100 / K100 Pro、US 区域设备,或控制器的 SWD 转储文件吗?欢迎提交 PR 和 issue —— 特别是关于 meter 固件中的区域→上限逻辑。 ## 许可证 [MIT](LICENSE)。按“原样”提供,用于研究和互操作性。改装 滑板车可能会使保修失效,并且在公共道路上骑行可能是违法的; 你对如何使用此信息自行负责。
标签:云资产清单, 固件分析, 智能硬件, 物联网, 蓝牙, 逆向工具, 逆向工程, 通信协议