При реверс-инжиниринге ПО контроллера гирлянды разработчику помог Хабр, но автор всё равно смог окирпичить устройство
Разработчик и любитель умного дома Уилл Кук подробно и с примерами кода рассказал, как он смог в процессе реверс-инжиниринга светодиодных контроллеров LEDnetWF, работающих по беспроводной технологии Bluetooth LE , окирпичить рождественскую гирлянду, выйдя за пределы допустимого производителем светоцикла устройства. Но перед этим разработчик использовал подсказки от коллег и даже обнаружил полезную информацию в этой публикации на Хабре.
Кук пояснил, что давно занимается реверс-инжинирингом светодиодных контроллеров. «Если устройство обменивается данными через Bluetooth LE и имеет приложение, оно заслуживает интеграции в мою систему умного дома после надлежащих доработок в коде», — уточнил Кук.
«Я потратил значительное количество времени на реверс-инжиниринг различных недорогих светодиодных лент, чтобы автоматизировать работу с ними. Процесс, как правило, повторяющийся, но мне он нравится. Недавно я успешно подключил самый дешёвый светильник, который мне когда-либо попадался — неадресную полоску длиной 5 м с Bluetooth LE к Home Assistant всего за несколько часов. Вы можете купить её аналог здесь, а мой код проекта для её автоматизации размещён на GitHub», — добавил Кук.
Но после нескольких удачных проектов Кук столкнулся с адресной гирляндой на базе контроллера LEDnetWF, для которого он тоже решил выполнить процесс реверс-инжиниринга для добавления в свой умный дом, а также для расширения штатных доступных опций от производителя.
Украшая свой офис к Рождеству, Кук решил потратить некоторое время на подключение этих новых гирлянд к Home Assistant, используя свой код BJ_LED в качестве шаблона. «Это должно было быть просто, верно? Ну да, но и нет», — заинтриговал разработчик.
Новые гирлянды состоят из цепочки адресных светодиодов длиной 10 м, управляемой приложением iDeal LED. Приложение многофункциональное, оно сделано достаточно просто и удобно. Светодиоды, скорее всего, WS2812 или аналогичные. «Меня очень порадовали эти недорогие гирлянды, которые можно найти на AliExpress», — пояснил предысторию Кук в рамках рассказа о дальнейших событиях.
«Теперь позвольте мне поделиться предостерегающей историей. Хотя для краткости я опускаю некоторые детали, здесь нет никаких секретов, а дополнительные инструкции легко найти в сети в открытом доступе. Я понимаю, что это может быть похоже на рисование остальной части совы (отсылка к мему), но предоставленные ниже ссылки должны послужить отправной точкой для всех, кто заинтересован в реверс-инжиниринге своих купленных недорогих гирлянд», — добавил Кук.
Шаг 1. Байты по проводам
Чтобы управлять подобными устройствами-гирляндами с помощью собственного программного обеспечения, первым делом необходимо проверить байты, отправленные через Bluetooth на устройство из приложения. Обычно в гирляндах используют простой протокол с заголовком, байтами команд (для таких действий, как включение/выключение, изменение цвета) и футером (footer), который может представлять собой контрольную сумму.
На Android этот процесс значительно упрощён. Включите режим разработчика на своем устройстве Android, установите приложение для своей гирлянды и включите отслеживание Bluetooth HCI в настройках разработчика. При этом байты Bluetooth сохраняются в файле, доступном для чтения в анализаторе Wireshark. Выполняйте действия в приложении, например включайте и выключайте свет, а также используйте adb для копирования журналов на свой компьютер. Пример: adb pull sdcard/btsnoop_hci.log.
После этого откройте логи в Wireshark, чтобы увидеть именно те байты, отправленные на устройство. Ищите закономерности в значениях, и вы, скорее всего, обнаружите последовательность байтов для каждого действия, где один байт чередуется между двумя значениями (например, 1 и 0 для включения и выключения). Вот полезный фильтр Wireshark: bluetooth.dst == ff:ff:ff:ff:ff:ff && btatt.opcode.method==0x12.
Потом измените MAC-адрес на MAC-адрес ваших гирлянд. btatt.opcode.method==0x12 — пример отправки команды для записи с устройства Android на гирлянду. Поздравляем, вы теперь реверс-инженер!
Небольшой совет от Кука: можно немного ускорить процесс, используя tshark вместо Wireshark. Что действительно нужно получить, так это значения, записываемые в контроллер гирлянды. tshark -r <имя файла> -T поля -e btatt.value выгрузит дамп прямо в для облегчения анализа данных.
Иногда ваши байты будут выглядеть так (Вкл, выкл, вкл, выкл, вкл, выкл, вкл, выкл.):
69 96 02 01 01
69 96 02 01 00
69 96 02 01 01
69 96 02 01 00
69 96 02 01 01
69 96 02 01 00
69 96 02 01 01
69 96 02 01 00
Иногда ваши байты будут выглядеть так:
84 dd 50 42 37 41 50 89 7a c8 2f 39 11 09 68 a8
79 d1 db a4 09 19 c2 46 a8 58 0a e7 d1 1b 78 84
84 dd 50 42 37 41 50 89 7a c8 2f 39 11 09 68 a8
79 d1 db a4 09 19 c2 46 a8 58 0a e7 d1 1b 78 84
84 dd 50 42 37 41 50 89 7a c8 2f 39 11 09 68 a8
79 d1 db a4 09 19 c2 46 a8 58 0a e7 d1 1b 78 84
84 dd 50 42 37 41 50 89 7a c8 2f 39 11 09 68 a8
Здесь до сих пор наблюдается повторяющаяся закономерность. Есть два разных набора байтов: один для включения, другой для выключения, но… что? Почему так непонятно и неочевидно? Кто разрабатывает такой протокол? Ответ: тот, кто пытается что-то скрыть.
Шаг 2. Повторяйте атаки
Если ваша цель — просто включать и выключать свет, то наблюдаемой вами повторяющейся последовательности байтов может быть достаточно для управления питанием. Проверьте это с помощью gatttool, который позволяет подключаться к устройству BLE и отправлять байты. Вам нужно будет знать дескриптор для отправки байтов, который вы можете найти с помощью Wireshark.
Для большей возможности перехвата контроля управления гирляндой важно понимать все эти байты. Обратимся к первоисточнику…
Шаг 3. Декомпилируйте приложение Android
Скачайте APK приложения и откройте его в jadx. Станьте свидетелем секретов внутри! В данном случае с этой гирляндой можно заметить в исходнике упоминание AES, указывающее на потенциально зашифрованный протокол. Если данные зашифрованы, можно сделать некоторые предположения:
• зашифрованные данные не меняются каждый раз, что предполагает наличие постоянного ключа;
• данные требуют быстрой расшифровки на маломощном микроконтроллере, отдавая предпочтение более коротким ключам;
• ключ, вероятно, не уникален для каждого устройства, что делает возможным использование фиксированного ключа.
Исходный код приложения гирлянды содержал скомпилированную AES-библиотеку libAES.so, с которой jadx мне не помог.
Кук пояснил, что тут он застрял. Примерно 5 минут.
Я попросил своих коллег под никами popey и sil поделиться некоторыми идеями. Разработчик sil погуглил часть декомпилированного кода приложения и нашёл эту публикацию на Хабре! При ближайшем рассмотрении код выглядит идентично. Оказывается, разработчик @equuskk использовал ida free для декомпиляции библиотеки AES и нашёл встроенный в неё ключ. Кук решил попробовать этот ключ в своем проекте.
Когда он попытался расшифровать пакеты с байтами включения и выключения, то получил:
05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00
05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00
05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00
05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00
05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00
05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00
«Успех! Это гораздо понятнее. Тут есть фиксированный заголовок, байт 05, видно переключение между 1 и 0 для включения и выключения, а также куча нулей. Теперь мы можем расшифровать все пакеты, отправляемые на устройство, и зашифровать наши собственные байты, чтобы дублировать элементы управления из приложения Android в нашем собственном коде. На данный момент это практически выполненная миссия», — обрадовался Кук.
Шаг 4. Доступ ко всем опциям
Теперь нужно проработать каждую функцию приложения, записывая отправленные байты. Запишите каждое действие, повторите его несколько раз и используйте разделители, например, включение и выключение света. Это помогает выявить закономерности и сопоставить заметки с захваченными байтами.
Например, ваш процесс может быть следующим:
turn off, turn on - [start of function]
set to red
set to green
set to blue
set to red
set to green
set to blue
set to red
set to green
set to blue
turn off, turn on - [end of colour changing]
set brightness to 100%
set brightness to 50%
set brightness to 10%
set brightness to 50%
set brightness to 100%
turn off, turn on - [end of brightness]
Этот процесс помогает обнаружить закономерности в данных и увидеть, какие байты изменяются в зависимости от того, что отправляется на устройство.
Шаг 5. Автоматизированный генератор электронных отходов
Изучая изменения цвета гирлянды, в коде Кук заметил, что приложение никогда не отправляло значение выше 0x1F (5 бит) для красного, зелёного или синего. Ему стало любопытно. Он попробовал отправить 8-битные значения, и это сработало на удивление хорошо — цвета стали ярче! Большой успех!
Воодушевлённый своим открытием, Кук начал задаваться вопросом, какие ещё секреты скрывал этот контроллер гирлянды. Интересно, есть ли какие-нибудь дополнительные эффекты помимо 10, которые использует приложение? Хорошим способом попробовать это будет простой цикл.
Кук запустил этот цикл и проверил его работу от 1 до 10. Пока все хорошо. Но потом дошло до 11 и АХ-ХА! Я нашёл секретный режим! Потом дошло до 12 и… темнота.
«Ну ладно, я думаю, эффектов всего 11, это нормально. Я перезапущу его и допишу остальной код. И на этом моё веселье закончилось. Свет так и не вернулся. Контроллер больше не работает по Bluetooth, к гирлянде нельзя подключиться. Я пробовал удерживать кнопку при включении. Я оставил их отключёнными от сети на ночь, чтобы посмотреть, поможет ли это, но нет. Они мертвы. Наверное, я переполнил какой-то буфер и повредил прошивку», — сообщил Кук.
«Однако не все потеряно. Сами светодиоды являются стандартными адресуемыми светодиодами, поэтому я могу, по крайней мере, подключить шнур к другому микроконтроллеру и использовать их. Несмотря на неудачу, я задокументировал большую часть протокола и создал проект на Github с пользовательским компонентом Home Assistant. Это работает, но действуйте на свой страх и риск», — подытожил Кук.
Написать комментарий