샤오미 체중계를 샀습니다. 이 포스트에서는 이 체중계의 프로토콜을 역공학해보고자 합니다.

샤오미 체중계는 샤오미답게(?) 블루투스 LE 를 통해 체중을 전송하는 기능을 가지고 있습니다. 이 기능을 통해 Mi Fit 앱과 같은 앱이 체중계에서 데이터를 받아옵니다. 이 글에서는, 이 샤오미 체중계가 쓰는 BLE 프로토콜을 역공학한 과정을 설명하도록 하겠습니다.

먼저, 알려진 역공학된 문서가 존재하는지를 검색합니다. 이 과정애서 https://github.com/chaeplin/Xiaomi_scale_scan 를 발견하였고, 이를 힌트 삼아서, 추가 역공학을 진행합니다.

해당 파이썬 코드에서, 샤오미 체중계가 BLE advertise frame 에 데이터를 실어 보내고, 몇 가지 데이터들의 오프셋을 알 수 있습니다. 우선 이 코드를 가동시켜 봅시다.

xiaomi_scale_scan_wo_mod

해당 코드가 부분적으로는 동작하지만, 몇몇 부분에서는 잘못 동작하는 것을 확인할 수 있습니다. 이유를 확인하기 위해 print 를 추가합시다.

xiaomi_scale_scan_code_print

이 코드는 다음과 같은 출력을 냅니다.

xiaomi_scale_scan_w_print

빠진 리스폰스를 알려진 리스폰스와 비교합니다.

빠진 리스폰스: 0x82
알려진 리스폰스: 0x02, 0x22

이에 해당 단위 판단 부분은 다음괴 같은 포멧을 가질 것이라고 추측할 수 있습니다.

First 4 bit contains scale state (not stabilized, stabilized, locked, sleeping) and information about part of unit system. 
first bit (from LSB): true if config switch is on chinese Catty.
second bit (from LSB): stabilized bit?
third bit (from LSB): Unknown.
fourth bit (from LSB): Load removed?
Second 4 bit contains information about unit system. 
See BT Weight scale service doc.
first bit (from LSB): Imperial(true) or MKS(false).
second bit (from LSB): Time stamp present. (research needed) 
third bit (from LSB): UserID present (for multi-user scale) (research needed) 
fourth bit (from LSB): BMI and height present (research needed) 
    0011: imperial unit system (lbs).
    0010: MKS or chinese Catty. (example)
    Note: It seems it does not comply BT standard strictly.

더불어, 미상인 필드들을 찾기 위해 wireshark 를 켜고 블루투스 패킷을 캡쳐합니다. Wireshark 의 패킷 분석 기능을 활용해 BLE 패킷을 분석합니다.

xiaomi-scale-wireshark

Wireshark 의 도움으로 (BLE 문서를 읽는 수고를 덜고)추가 정보를 얻게 되었습니다. 이제 Wireshark 로부터 얻어낸 필드 정보와 처음 참조했던 파이썬 코드로부터 얻은 정보를 가지고 문서화를 진행하고, NodeJS 로 PoC 코드를 작성합니다.

https://wiki.gentoo.moe/wiki/Mi-scale

https://github.com/perillamint/node-xiaomi-scale

체중계 프로토콜을 역공학하는 데 참조한 파이썬 코드를 작성하신 chaeplin 님께 감사를 드립니다.