
oBike 프로토콜 통신(BLE 및 HTTP)의 리버스 엔지니어링
이 문서는 2018년 1월 기준 oBike 통신 프로토콜에 대한 분석을 제공합니다.
결과는 insomni'hack 보안 컨퍼런스 2019에서 발표되었습니다:
또한 AREA41 보안 컨퍼런스 2018에서도 발표되었습니다:
oBike 잠금장치는 BLE(Bluetooth Low Energy) 애플리케이션용 전력 최적화 SoC(System on a Chip)인 TI CC2541 마이크로컨트롤러로 구성됩니다. 잠금장치 자체에는 IP 연결 기능이 없으며, oBike 백엔드와 통신하기 위해 모바일 기기의 3G/4G 연결을 이용합니다. 잠금장치는 모바일 기기의 oBike 앱과 BLE를 통해 통신합니다. 프로토콜 메시지는 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비트로 잘린 값)와 (encKey에 해당하는) index를 보낸다. 이 시점에서 자전거가 잠금 해제된다.macKey와 index를 수신한다. 이는 잠금 해제가 성공했음을 알리는 확인 신호다.macKey 및 index)과 함께 lockMessage를 보낸다. 이 시점에서 oBike 백엔드는 라이딩을 등록하고 요금 부과를 시작한다.다음 섹션에서 설명하는 BLE 프로토콜 구성 요소는 파이썬 모듈 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`)로 시작합니다.
페이로드의 길이는 헤더/트레일러를 제외한 바이트 수입니다.
프로토콜은 바이트로 식별되는 다양한 메시지 유형을 지원합니다. 가장 중요한
두 비트가 메시지 방향을 정의합니다:```
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
명령 유형: `6`
이 메시지는 "잠금 레코드"를 관리하는 데 사용됩니다. 이 레코드는 칩에
유지되는 데이터 레코드로, 마지막 라이드의 정보(예: memberid, 타임스탬프,
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 Push Coords / Get Challenge
명령 유형: `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)
이 명령은 페이로드 없이도 사용할 수 있습니다:```
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...(|
The input chunk is empty. There is no content to translate.```
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)