
Обратная разработка протокола связи oBike (BLE и HTTP)
В этом документе представлен анализ коммуникационных протоколов oBike по состоянию на январь 2018 года.
Результаты были представлены на конференции по безопасности insomni'hack 2019:
а также на конференции по безопасности AREA41 2018:
Замок oBike состоит из микроконтроллера TI CC2541 — энергооптимизированной системы на кристалле (SoC), используемой для приложений Bluetooth Low Energy (BLE). Сам замок не имеет IP-подключения; он использует 3G/4G-соединение мобильного устройства для связи с бэкендом oBike. Замок взаимодействует по BLE с приложением oBike на мобильном устройстве. Затем сообщения протокола передаются в бэкенд oBike через REST API.
Замок не имеет собственного 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)
Steps:
hello, передаёт координаты замку.keySource — 32-битное значение, представляющее количество миллисекунд с момента включения чипа (little endian).unlockPass.encKey (индекс ключа) и 128-битное значение ключа в keys.encKey (усечённый до 96 бит) и index (соответствует encKey). В этот момент велосипед разблокируется.macKey и index — подтверждение успешной разблокировки.lockMessage с соответствующими значениями (macKey и index). В этот момент бэкенд oBike зарегистрирует поездку и начнёт биллинг.Компоненты BLE-протокола, описанные в следующих разделах, реализованы в Python-модуле obike.ble_client. Кроме того, сканер для обнаружения рекламных BLE-пакетов obike реализован в 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`).
Длина полезной нагрузки — это количество байт без учёта заголовка/хвостовой части.
Протокол поддерживает различные типы сообщений, идентифицируемые байтом. Два старших
бита определяют направление сообщения:```
0x86 1000 0101 mobile -> obike
0x46 0100 0101 obike -> mobile
Контрольный байт вычисляется XOR-сложением типа команды и байтов полезной нагрузки:``` check_byte = cmdtype ^ b[0] ^ b[1] ^ ... ^ b[N-1]
Максимальный размер PDU составляет 19 байт (заголовок + полезная нагрузка + трейлер). Сообщения, превышающие этот размер, фрагментируются.
### BLE getLockRecord/deleteLockRecord
Command type: `6`
Эти сообщения используются для управления «lock record» — записью данных, сохраняемой чипом и содержащей информацию о последней поездке: memberid, timestamp, идентификатор 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