Взламываем фитнес-браслет Xiaomi Mi Band 2
LOCKNET![](/file/4b48d553b469100be8633.png)
![](/file/1675e6054438ecdefccc1.png)
Приветствую тебя, мой дорогой юзернейм! В этой статье будет приведено пошаговое руководство взлома фитнес-трекера Xiaomi Mi Band 2. Я хочу получать данные с сенсоров в режиме реального времени и поэкспериментировать с полученной информацией. Мне хочется создать советника по физическим упражнениям. В итоге было решено хакнуть фитнес-трекер. Приятного изучения.
Я никого ни к чему не призываю, скрипты используются в ознакомительных целях!
Приступаем.
У меня не было никакого опыта работы с BLE-девайсами (Bluetooth Low Energy), и я решил начать с изучения этой технологии. Выяснилось, что никаких особых сложностей нет:
- У каждого BLE-устройства есть несколько служб.
- У каждой службы есть некоторые характеристики.
- У некоторых характеристик есть дескрипторы (если у характеристики больше чем один параметр или тип соответствует чтению или уведомлению).
- У некоторых характеристик есть доступ только на чтение/запись (например, текущее время, статус батареи или информация о последней ревизии).
- Некоторые характеристики более сложны и работают, используя запросы/цикл уведомлений (например, монитор частоты сердцебиения в режиме реального времени или авторизация).
Также вам понадобятся два приложения для отладки BLE-устройства:
Анализаторпротоколов Wireshark и BLE отладчик. Кроме того, нужно активировать опции разработчика в устройстве на базе Android (для любителей iOS придется поискать эквивалент в этой платформе).
Посмотрим, какие службы и характеристики есть у нашего устройства. Открываем отладчик для BLE и запускаем сканирование.
Должно появиться примерно следующее:
![](https://www.securitylab.ru/_Article_Images/2019/28/image002.jpg)
MAC адрес устройства нам понадобится позже, поэтому лучше эту информацию где-то сохранить или записать.
Подключаемся и смотрим перечень служб и характеристик:
![](https://www.securitylab.ru/_Article_Images/2019/28/image003.jpg)
Выполнив две простые операции, мы уже получили полезную информацию о нашем устройстве. Схожая функция доступна через командную строку при помощи утилит hcitool и gatttool.
Запуск сканирования из командной строки:
sudo hcitool lescan
Подключение к BLE устройство через Mac адрес и получение списка служб и дескрипторов:
sudo gatttool -b YOUR_MAC -I -t random > connect > primary > char-desc
В некоторых случаях могут возникнуть проблемы. В том случае можно перезагрузить устройство или запустить следующую команду:
sudo hciconfig hci0 reset
Подготовка к сниффингу данных.
Для сниффинга данных во время коммуникации телефона и BLE-устройства нужно включить Bluetooth-логи в настройках разработчика. Вначале необходимо включить настройки на Android-устройстве. Следуйте по шагам, описанным далее.
До Android 4.1 опции разработчика доступны по умолчанию. Начиная с версии 4.2, нужно сделать следующее:
- Откройте раздел Settings на Android-устройстве.
- Выберите раздел System (только на устройствах с Android 8.0 и выше).
- Прокрутите вниз и выберите About phone.
- Прокрутите вниз и тапните 7 раз на Build number.
- Возвратитесь к предыдущему разделу. Почти в самом низу должен появиться раздел Developer options.
- Откройте настройки разработчика и включите опцию «Enable Bleutooth HCI snoop log».
Теперь все коммуникации между телефоном и любым внешним Bluetooth-устройством должны отражаться в файле btsnoop_hci.log. (на моем телефоне с Android 7.0 логи находятся в /mtklog/btlog/btsnoop_hci.log).
Аутентификация.
Теперь нужно выполнить следующие шаги для получения информации о том, как работает аутентификация (сопряжение):
- Включите Bluetooth и HCI логи.
- Выполните сопряжение устройства с приложением Xiaomi Android App.
- Отключите Bluetooth.
- Загрузите btsnoop_hci.log на компьютер.
- Откройте файл в Wireshark.
- Найдите первый запрос, имеющий отношение к протоколу ATT, с параметром Handle: 0x0055 (который связан с компанией Anhui Huami Information Technology Co, выпускающей переносные устройства и владеющей брендом Xiaomi).
Должно получиться примерно следующее:
![](https://www.securitylab.ru/_Article_Images/2019/28/image004.jpg)
Выделенный запрос – первый этап аутентификации.
Как видно из рисунка выше, обрабатываются следующие значения UUID:
- Pairing device
- Main service UUID
- 0000fee1-0000–1000–8000–00805f9b34fb
- Auth Characteristic (Char) UUID
- 00000009–0000–3512–2118–0009af100700
- Notification descriptor (Des) handle
0x2902 - (всегда неизменный)
Аутентификация состоит из следующих шагов:
- Настройка auth-уведомлений (для получения ответа) посредством отправки двухбайтового запроса \x01\x00 в Des.
- Отправка 16-байтового ключа шифрования в Char с командой и добавление двух байт \x01\x00 + KEY.
- Запрос случайного ключа с устройства с командой посредством отправки двух байт \x02\x00 в Char.
- Получение случайного ключа от устройства (последние 16 байт).
- Шифрование этого случайного номера при помощи 16-байтового ключа, используя алгоритм шифрования AES/ECB/NoPadding (из Crypto.Cipher import AES) и обратная отправка в Char (\x03\x00 + закодированная информация).
Данные в режиме реального времени
Процесс аутентификации Auth оказался чуть сложнее, и появились некоторые проблемы. Мониторинг частоты сердцебиений отключался через 15 секунд. Ниже показан перечень полученных значений UUID:
- Hardware service (HRDW) UUID
- 0000fee0–0000–1000–8000–00805f9b34fb
- Heart Monitor Service (HMS) UUID
- 0000180d-0000–1000–8000–00805f9b34fb
- Heart Rate Measure Characteristic (HRM) UUID
- 00002a37–0000–1000–8000–00805f9b34fb
- Heart Monitor Control Characteristic (HMC) UUID
- 00002a39–0000–1000–8000–00805f9b34fb
- Sensor Characteristic (SENS) UUID
- 00000001–0000–3512–2118–0009af100700
- Notification descriptor (DES) handle
- 0x2902 (всегда неизменный)
Выполняются несколько стандартных операций:
- Отключение текущего мониторинга сердцебиений. Отправка запроса \x15\x02\x00 к HMC для одноразовых измерений. Отправка запроса \x15\x01\x00 к HMC для непрерывных измерений.2.
- Разрешение сырых данных от гироскопа и измерителя сердцебиений посредством отправки команды \x01\x03\x19 к SENS
- Включение уведомлений для HRM посредством отправки запроса \x01\x00 к DES
- Начало непрерывных измерений сердцебиения посредством отправки запроса \x15\x01\x01 к HMC
- Отправка команды \x02 к SENS (не очень понятно, зачем нужна эта команда)
- Затем в процессе получения уведомлений каждый 12 секунд нам нужно отсылать пинг со значением \x16 к HCM
Парсинг данных.
Далее нужно было разобраться, как распаковать информацию, приходящую с устройства, для последующего парсинга.
Некоторую часть данных можно распарсить из логов, некоторую - нельзя.
![](https://www.securitylab.ru/_Article_Images/2019/28/image005.jpg)
Поиск правильных пакетов и изучение системы кодирования может отнять некоторое время. В моем случае я попытался найти похожие байты в пакетах рядом с друг с другом. Некоторые байты повторяются внутри пакета.
Raw heart: 02102d8c348c448c458c3d8c428c488c 16 Raw heart: 0218468c418c3d8c468c3f8c398c418c 16 Realtime heart: 93 Raw heart: 0220408c448c3f8c428c498c3c8c3d8c 16 Raw heart: 02283d8c398c488c3e8c468c488c328c 16 Realtime heart: 99 Raw heart: 0230438c408c378c3a8c318c458c388c 16 Realtime heart: 102 Raw heart: 02404f8c408c458c428c4d8c558c4d8c 16 Raw heart: 02483e8c3b8c3f8c348c398c318c428c 16 Realtime heart: 98 Raw heart: 02504c8c428c5e8c4f8c588c498c558c 16 Raw heart: 0258478c458c3c8c4e8c3f8c468c4d8c 16 Realtime heart: 100 Raw heart: 0260518c4d8c4f8c4b8c4f8c528c458c 16 Raw heart: 0268408c3f8c538c4d8c408c548c598c 16 Realtime heart: 102 Raw heart: 0278418c508c4e8c548c588c468c498c 16 Raw heart: 0280368c328c2e8c3c8c338c308c3f8c 16 Realtime heart: 101
Здесь можно заметить четкий повторяющийся шаблон 368c 328c 2e8c 3c8c 338c 308c 3f8c в пакете размером 16 байт. Если мы распакуем с учетом, что каждое измерение представляет собой беззнаковый короткий тип размером 2 байта, то получим 7 непосредственных измерений от сенсора сердца.
Также видно, что второй байт просто увеличивается и связан, как я думаю, с временной разницей между измерениями (ответами).
Raw gyro: 01de49ffd9ff3c004cffd8ff3b004dffdcff4400 Raw gyro: 01df4cffd6ff44004dffd8ff40004cffd1ff4700 Raw gyro: 02e1103231323d3274328e329632af32c732cf32 Raw gyro: 01e34fffd7ff56004bffc7ff590049ffccff4c00 Raw gyro: 01e443ffccff43004effcdff40005bffd4ff4c00 Raw gyro: 01e558ffc9ff5f005effbfff66005fffb0ff5900 Raw gyro: 01e64cffacff60005cffa7ff410066ffc9ff4600 Raw gyro: 01e760ffdcff4b0051ffe4ff4f0034ffdeff5300 Raw gyro: 02e903365c36813663361036543688374139fe3a Raw gyro: 01eb4bffc3ff50004fffc1ff430047ffbbff4100 Raw gyro: 01ec3effb2ff3c0050ffbfff560047ffccff7300 Raw gyro: 01ed4fffe0ff78005cffebff8e0056fff6ff8300 Raw gyro: 01ee7efffbffa1008bff0f00bc00b1ff1900b800 Raw gyro: 01ef9bff0c00d10095fff3ffd600b7ff0800df00 Raw gyro: 02f12445314600479e473348aa481c499749244a Raw gyro: 01f3c3ff1600fe00beff1800f200a6ff0800e700 Raw gyro: 01f4a9fff8ffd300a7fff3ffd700a9fff1ffdf00 Raw gyro: 01f3c3ff1600fe00beff1800f200a6ff0800e700 Raw gyro: 01f4a9fff8ffd300a7fff3ffd700a9fff1ffdf00 Raw gyro: 01f5b1fff8ffe800b4fff1fff700acfffcffef00 Raw gyro: 01f67ffff7ffc0006bfff4ffb00078ffe9ffb600 Raw gyro: 01f786ffecffc0006ffff0ffbc0060fff1ffc000 Raw gyro: 02f9ca4cbb4c784c964ca84c784c854c444c1b4c Raw gyro: 01fb7cff0f00bb007eff2700ae0083ff30009800 Raw gyro: 01fc79ff1800b00076ff0f00bc0068ff0900d900 Raw gyro: 01fd78ff07000c01f6fffbff19011c000b00f600 Raw gyro: 01fe4b001100d30054000700c3004300efffeb00 Raw gyro: 01ff1f00d0ff1701fbffe8ff1b01e3ffffff1101 Raw gyro: 0201214b014bec4ad04aba4acb4abe4aba4abd4a Raw gyro: 0103efffecfffc00e3fff3fff300defff3fffc00 Raw gyro: 0104e3fff0fff400e6ffefff0301dbffe9ff0c01 Raw gyro: 0105e3fff0ff0301e6ffe6fffc00dcffecfffc00 Raw gyro: 0106dffff0fff700dbffeefff600d6fff0fff400 Raw gyro: 0107dfffecffff00e1fff0ff0301defff3fffc00
В случае с гироскопом ситуация оказалась чуть сложнее. Но я думаю, что упаковка должна выполняться схожим образом, как и для данных о частоте сердцебиения. Однако здесь у нас 3 измерения знакового типа для каждой оси гироскопа, а сам пакет размером 20 байт. Таким образом, данные от всех сенсоров укладываются не в 12, а в 3 измерения по осям x, y, z. Первые 2 байта играют ту же роль, что и в предыдущем случае.
В итоге моя гипотеза оказалась верной.
Код.
Код, как обычно, можно найти на Github с примером использования. Ничего сложного нет, и я решил подробно не рассматривать этот момент в статье.
![](/file/94615533c883b3d0c50f6.png)
Инкогнито - не забываем подписываться на наш второй канал!
DARK PLACE - место, где ты заработаешь 100.000₽ уже через месяц!
BLACK - самые топовые сливы схем заработка и обучений.
Предыдущие статьи:
Как нести доход в дом с Твиттера?
Поднимаем 50к рублей в месяц на самоделках
Пассивный заработок от 500 рублей в день на VTOPE
Заработок на курьерах и их счетах
Другие статьи на нашем с вами любимом канале LOCKNET! Подписывайся, делись ссылкой на статью с друзьями!