本文档提供了截至 2018 年 1 月 oBike 通信协议的分析。
相关成果已在 insomni'hack 安全大会 2019 上展示:
同时也在 AREA41 安全大会 2018 上展示:
oBike 车锁由 TI CC2541 微控制器构成,这是一款用于蓝牙低功耗(BLE)应用的功耗优化型片上系统(SoC)。车锁本身不具备 IP 连接能力;它借助移动设备的 3G/4G 连接与 oBike 后端进行通信。车锁通过 BLE 与移动设备上的 oBike 应用通信。协议消息随后通过 REST API 中继到 oBike 后端。
车锁本身没有 GPS 模块。因此,上报到后端的位置始终是移动设备的位置,而非 oBike 本身的位置。``` GPS | +---------+ +---------+ +----------+ | oBike | | Mobile | | oBike | | Lock | +--- BLE ---> | Device | +--- HTTPS ---> | Backend | +---------+ +---------+ +----------+
## 解锁序列```
oBike Lock (BLE) Mobile Device (HTTPS) oBike Backend
------------+------------------------+---------------------------+--------------
| | |
| [1] hello(lat, lng) | |
| <--------------------- | |
Generate | | |
32bit | [2] keySource | |
Challenge | ---------------------> | [3] unlockPass(keySource) |
| | ========================> | Compute
| | | Response
| [5] | [4] encKey, keys |
| sendKeys(encKey, keys) | <======================== |
!Unlock | <--------------------- | |
Bike! | | |
| | |
Generate | | |
Acknowledge | [6] macKey, index | [7] |
Message | ---------------------> | lockMessage(macKey,index) |
| | ========================> | Register
| | | Ride (start
| | | billing)
步骤:
hello消息,将坐标推送到锁。keySource,这是一个32位值,表示芯片上电以来的毫秒数(小端序)。unlockPass REST调用将keySource发送到oBike后端。encKey(密钥索引)和keys中的128位密钥值。encKey(截断为96位)和index(对应于encKey)。此时,自行车将解锁。macKey和index,表示解锁成功的确认。lockMessage,包含相应的值(macKey和index)。此时,oBike后端将登记行程并开始计费。以下章节描述的BLE协议组件已在Python模块obike.ble_client中实现。此外,用于检测obike BLE广播的扫描器已在obike.ble_scanner.py中实现。
6774 0D 86 59AEB6...3931 FD | | | | | | | | | +-- Check byte | | | +----------------- Payload | | +--------------------- Command type | +------------------------- Length of payload in bytes +------------------------------- Command Signature ('gt')
消息(无论是传入还是传出)始终以签名 `\x67\x74`(ASCII `gt`)开头。
载荷长度是不含头部/尾部(header/trailer)的字节数。
该协议支持由单个字节标识的不同消息类型。最高两位定义消息方向:```
0x86 1000 0101 mobile -> obike
0x46 0100 0101 obike -> mobile
校验字节是通过对命令类型和载荷字节进行异或运算计算得出的:``` check_byte = cmdtype ^ b[0] ^ b[1] ^ ... ^ b[N-1]
最大PDU大小为19字节(头 + 负载 + 尾)。超过此大小的消息将被分片。
### BLE getLockRecord/deleteLockRecord
命令类型:`6`
这些消息用于管理“锁记录”,即芯片持久化的一条数据记录,包含上次骑行信息,例如会员ID、时间戳、oBike标识符、坐标等。
在无负载的情况下调用该命令,用于检索已保存的锁记录:```
00000000 67 74 00 86 86 |gt...|
如果没有可用的锁记录,锁将以空载荷进行响应。``` 00000000 67 74 00 46 46 |gt.FF|
否则,锁的响应包含上次行程中的几个值,采用
以下格式:```
00000000 67 74 46 46 00 00 01 23 45 67 59 9d 72 2a 44 31 |gtFF...#d2Y.r*D1|
00000010 39 33 36 42 33 31 37 2a 72 9d 59 00 34 37 2e 33 |936B317*r.Y.47.3|
00000020 37 32 37 36 30 00 00 00 30 38 2e 35 33 30 38 34 |72760...08.53084|
00000030 32 32 00 00 87 76 f3 7a 8c be 90 f8 4b a4 fa 00 |22...v.z....K...|
00000040 2e ae e3 dc 91 00 00 00 a9 01 8b |...........|
0004 000001234567 member-id (explicitly coded in decimal, value is: 1234567)
000a 599d722a UNIX timestamp, 08/23/2017 @ 12:16pm
000e 443139333642333137 obike identifier (D1936B317) this corresponds to the MAC address without the first 3 hex digits, in this case: D4:3D:19:36:B3:17
0017 2a729d59 same UNIX timestamp, little endian
001b 00 transaction type
001c 34372e333732373630000000 latitude (47.372760)
0028 30382e353330383432320000 longitude (08.5308422)
0034 8776f37a8cbe90f84ba4fa002eaee3dc mackey (128 bits)
0044 91 key index
0045 000000 ? 0048 a901 battery voltag level (little endian) e.g. 4.25V
当与有效负载一起使用时,此命令会删除当前的锁记录:```
00000000 67 74 0d 86 59 d5 ff a4 36 33 39 38 37 37 31 33 |gt..Y...63987713|
00000010 43 14 |C.|
0004 59d5ffa4 timestamp (little endian) 000e 3633393837373133 "63987713C" obike identifier
### BLE 坐标推送 / 获取挑战
命令类型:`1`
这些消息由移动设备用于指示 obike 的当前位置,并将该位置存储起来。```
00000000 67 74 13 81 30 38 2e 35 33 30 38 34 32 32 34 37 |gt..08.530842247|
00000010 2e 33 37 32 37 36 30 b7 |.372760.|
0004 30382e35333038343232 longitude (08.5308422) 000e 34372e333732373630 latitude (47.372763)
该命令也可以在没有 payload 的情况下使用:```
00000000 67 74 00 81 81 |gt...|
作为响应,obike 会发送一个挑战,一个32位整数(小端序) 表示自通电以来经过的毫秒数:``` 00000000 67 74 0b 41 00 11 51 00 06 ef 5f 34 aa 01 00 28 |gt.A..Q..._4...(|
- [HaE](https://github.com/gh0stkey/HaE) - [BurpSuite](https://portswigger.net/burp) 的辅助工具,可以高度自定义地高亮标记有趣的 HTTP 请求/响应。```
Offset Value Description
-------------------------------------------------------------------------
0004 00115100 ? (constant, sometimes also 00115900)
0008 06ef5f34 challenge (aka keysource)
000c aa01 battery voltage level (little endian),
e.g 4.26V
000e 00 ? (constant)