
Двое реверс-инженеров пробуют разобраться, почему в старой стиральной машине Miele перестал работать отжим. Устранить неполадку им так и не удается — зато они умудряются отреверсить закрытый диагностический протокол и вытащить прошивку управляющей платы. А затем — написать утилиту, которая делает то же, что и проприетарный сервисный софт Miele, только без лицензий и посредников.
Детали этого эксперимента мы подробно разобрали в прошлой статье. Здесь история могла бы закончиться — но одной стиралки исследователям оказалось мало.
Дальше они вскрыли посудомойку BSH, подключились к шине обмена данными D-Bus и нашли механизм доступа к памяти, позволяющий выгружать прошивку с любых устройств BSH через эту шину. А к финалу исследования и вовсе ударились в откровенный инженерный троллинг, научив облачное приложение BSH управлять техникой бренда-конкурента.
Продолжаем разбор доклада Hacking Washing Machines с конференции 39C3 и смотрим, как попытка разобраться в логике одной капризной стиралки превращается в операцию по стыковке двух закрытых экосистем бытовой техники.
1. Исследование экосистемы BSH: шина D-Bus, облако и дампы прошивок
Знакомство с шиной D-Bus
BSH — один из крупнейших мировых производителей бытовой техники. Однако название компании в таком виде знакомо не всем: оно более узнаваемо по брендам Bosch, Siemens и ряду других.
При анализе техники BSH исследователи обратили внимание на часто упоминаемую в патентах внутреннюю шину D-Bus (или D-Bus 2), через которую взаимодействуют модули в устройствах. Поскольку шина проприетарная, открытой документации на нее нет. Исследователи задались вопросом: где проходит эта шина и как к ней подключиться?
На рисунке 1 показан силовой модуль, извлеченный из посудомоечной машины.

Поначалу в этом множестве разноцветных проводов и различных разъемов легко потеряться из-за полного отсутствия маркировки. После некоторых поисков исследователи установили, что почти все европейские производители бытовой техники используют так называемые разъемы RAST (от нем. Raster Anschluss Steck Technik). В устройствах BSH шина D-Bus часто выведена именно на такие 3- или 4-контактные разъемы (рис. 2).
Однако 3- или 4-контактный разъем RAST сам по себе еще не означает, что это D-Bus. Дополнительная подсказка — кодировка разъемов на плате. Если вы видите два или три разъема с одинаковой кодировкой, расположенных рядом, это верный признак того, что вы имеете дело с D-Bus (рис. 2). Для шины, как правило, не имеет значения, в какой именно из этих слотов вы подключаетесь.

Впрочем, это наблюдение нельзя считать строгим правилом, поэтому целесообразно перепроверить свою гипотезу. В частности, следует знать, что на силовых платах такой разъем имеет как минимум три провода: «земля», «данные» и «питание шины», именно в таком порядке. На подключенных датчиках и управляющих платах порядок обратный: «питание шины», «данные», «земля» (см. рис. 3).

Питающее напряжение шины составляет 9 вольт в стиральных машинах и 13,5 вольта в посудомойках и сушилках. По контакту данных передается сигнал напряжением 5 вольт. Зная эти параметры, можно достаточно надежно отличить D-Bus от другой проводки.
Для чего же D-Bus используется в бытовой технике? В стиральных машинах к этой шине подключены как минимум плата управления и пользовательский интерфейс. Судя по всему, именно с этих узлов в начале 2000-х годов BSH начала внедрение D-Bus. Со временем к шине стали подключать и другие компоненты: сначала датчик дисбаланса, в более новых моделях — контроллер двигателя, а в последних поколениях — модуль Wi-Fi.
В посудомоечных машинах картина схожая: к D-Bus подключены плата управления, пользовательский интерфейс, модуль TimeLight (проецирует на пол время до конца программы), и опять же модуль Wi-Fi.

Исследователи отмечают, что не все компоненты подключаются к D-Bus. Некоторые — датчик двери, нагревательные элементы, насосы и пр. — соединены с платой силового модуля напрямую, без участия шины.
Изучение логики работы D-Bus
Чтобы лучше понять, как происходит обмен данными по D-Bus, нужно рассмотреть пару примеров.
Пример 1. Взаимодействие с силовым модулем через пользовательский интерфейс
Рассмотрим стиральную машину и всего два ее компонента: панель пользовательского интерфейса и силовой модуль. Когда вы нажимаете кнопку выбора температуры, панель отправляет на силовой модуль кадр данных (data frame). Этот кадр содержит команду 1004, что означает «установить температуру», и аргумент 0x04, который в данном случае соответствует 60 градусам.
Силовой модуль обрабатывает этот кадр, пересчитывает, например, новое общее время выполнения программы, и отправляет обновленную информацию обратно на панель управления. Ответ приходит в виде пакета с командой 1600 и аргументом 0x60, что в пересчете из шестнадцатеричной системы означает 96 минут или 1 час 36 минут. Разумеется, можно отправлять такие команды в шину вручную, и дисплей их отобразит.

Пример 2. Взаимодействие силового модуля и датчика дисбаланса
Рассмотрим, как взаимодействуют силовой модуль и крайне важный для стиральной машины датчик дисбаланса.
Чем он важен? Если к началу этапа отжима белье в барабане окажется распределено неравномерно, то на скорости в 1000 об./мин. машина начнет буквально «подпрыгивать». Это нехорошо. Поэтому, прежде чем раскрутить барабан, силовой модуль отправляет датчику дисбаланса кадр с командой 4002 («начать измерение») и аргументом 0x19, что задает длительность измерения в 25 секунд.
Получив этот кадр, датчик немедленно начинает анализировать поведение барабана. Результаты он отправляет обратно командой 4010, которая содержит три целых числа со знаком, описывающих направление и величину дисбаланса (см. рис. 6). Если дисбаланс оказывается слишком большим, скорость вращения барабана снижается, и машина перераспределяет белье с помощью специального алгоритма.

Вот некоторые команды, зафиксированные исследователями при обмене данными с блоком управления стиральной машины (рис. 7). Здесь присутствуют, например, команды установки температуры, программы стирки, скорости отжима, а также опций вроде «легкая глажка» или «предварительная стирка», которые кодируются отдельными битами — флагами функций. В ответ на них блок управления, в свою очередь, отправляет на дисплей данные об оставшемся времени стирки, состоянии дверцы, статусе программы и так далее. Также упомянуты команды взаимодействия с датчиком дисбаланса, рассмотренные выше.

Алгоритм передачи данных
Как же происходит передача данных по D-Bus? Известно, что D-Bus — это последовательная шина с несколькими ведущими устройствами (multi-master), работающая на скорости 9600 бод и использующая стандартный формат кадра UART.
Структура каждого кадра проста: он начинается с байта длины, за которым следует байт адреса. В старшей тетраде (верхнем ниббле) этого байта кодируется адрес целевого устройства, а в младшей — номер подсистемы в этом устройстве. Далее идет переменное число байтов данных и, наконец, двухбайтовая контрольная сумма.
Если изучить эти кадры внимательнее, можно заметить, что первые два байта данных имеют особое значение. Для удобства их можно назвать «командным словом», поскольку именно они определяют, какое действие должно выполнить целевое устройство.
Например, приведенный на рис. 8 кадр исследователи интерпретируют так: «обработать команду 4002 для подсистемы 7 на узле 4 с полезной нагрузкой 0x178019». Когда узел назначения успешно принимает кадр, он отправляет в ответ один байт подтверждения. Этот байт формируется из адреса назначения в старшей тетраде и константы 'A' в младшей. Вероятно, 'A' — это просто сокращение от Acknowledgement (подтверждение).

Интеграция D-Bus в «умный дом»
Зная всё это, появляется соблазн начать перехватывать данные с шины и направить их в систему домашней автоматизации, минуя облачные сервисы. Разумеется, для этого нужно специальное оборудование. Исследователи начали с простейшего устройства на базе чипа ESP и DC-DC преобразователя (рис. 9, слева), а потом добавили к нему преобразователь уровней с открытым стоком (TXSO102), чтобы корректно отправлять данные в шину (рис. 9, справа).
Конечно, даже после такого «глубокого апгрейда» конструкция может по-прежнему выглядеть неказисто, но исследователи честно просят публику простить им эти эстетические изъяны.

Теперь к программной части. Исследователи написали расширение для ESPHome: им легко пользоваться — главное, в конфигурационном YAML-файле определить набор датчиков (а также их адреса и команды), которые должны реагировать на сообщения. Ниже приведен пример фрагмента такого файла, где значение с оси X датчика дисбаланса прослушивается и передается в Home Assistant.
# Секция определения датчиков в ESPHome sensor: # Определяется датчик, использующий кастомную платформу для шины BSH - platform: bshdbus # Адрес целевого устройства на шине (шестнадцатеричный формат) dest: 0x17 # Код команды/типа сообщения, которое содержит нужные данные command: 0x4010 # Список конкретных датчиков, извлекаемых из этого сообщения sensors: # Первый (и в данном случае единственный) датчик в списке - id: bsh_wm_unbalance_x # Внутренни�� уникальный идентификатор датчика name: "Unbalance X" # Отображаемое имя в Home Assistant # Лямбда-функция для преобразования сырых данных: склеивает 2-й и 3-й байты в 16-битное целое со знаком lambda: return (int16_t) ((x[1] << 8) | x[2]);
В результате в системе домашней автоматизации отображается не только стандартная информация, но и диагностические данные, которые обычно скрыты от пользователя (рис. 10). Например, можно посмотреть показания датчика дисбаланса или сведения о том, какой именно программный модуль сейчас управляет стиркой. Более того, на новых моделях машин можно даже отслеживать точную скорость вращения барабана в реальном времени.

При подключении своей бытовой техники к системе автоматизации важно учитывать, что у каждого типа устройств свой набор команд D-Bus. Это значит, что несмотря на то, что посудомоечные машины, микроволновые печи, холодильники, винные шкафы, кофемашины могут использовать D-Bus, их команды, аргументы и логика взаимодействия «запрос-ответ» будут совершенно разными.
Глядя на то, что происходит в шине, исследователи предположили, что у каждого подразделения BSH сложился собственный, особый подход к созданию команд для своих устройств. Если вам удастся собрать какую-то коллекцию параметров и команд по своим приборам, авторы исследования приглашают принять участие в проекте и поделиться ей на Github.
Итак, с домашней автоматизацией исследователи разобрались. Что дальше?
Дверь в кладовую прошивок: отладочный порт ST-Link
Следующим шагом стал дамп прошивки посудомоечной машины BSH. Внимание исследователей привлек шестиконтактный разъем на плате ее силового модуля. Оказалось, что это разъем ST-Link, к которому можно подключиться с помощью недорогого ST-Link программатора (рис. 11).
Микроконтроллер не имел активной защиты от чтения, поэтому через OpenOCD удалось без ограничений считать прошивку. По сути, устройство вело себя как обычная отладочная плата, а не как закрытая бытовая техника. Для реверса — идеальный сценарий.

Анализ прошивки показал наличие таблиц, полностью соответствующих командам, перехваченным в D-Bus. Следующие за ними байты по структуре совпадали с внутренними адресами функций в прошивке (рис. 12). Выяснилось, что эти списки — часть гораздо более крупной структуры, которая описывает подсистемы устройства, а также все входящие и исходящие команды.

Написав несложный скрипт, исследователи составили полный список всех подсистем устройства, включая все входящие и исходящие команды, длину их аргументов и соответствующих функций-обработчиков (рис. 13).

Наличие такого списка, в свою очередь, позволило с помощью дизассемблера сразу переходить к нужным участкам кода, минуя ручной поиск. Тоже немаловажное удобство с точки зрения реверс-инжиниринга.

При просмотре списка подсистем исследователи обратили внимание на некую «нулевую подсистему» — Subsystem 0x0. Она любопытна тем, что ведет себя не так, как остальные: ее команды обычно не появляются в трафике D-Bus. Выяснилось, что команды f0-00 и f0-01 используют одну и ту же функцию-обработчик; то же самое касается команд f2-00 и f2-01 (рис. 15).

Исследователи начали анализ именно с этих команд и перешли к изучению соответствующих обработчиков в декомпилированной прошивке. Ниже приведен фрагмент функции, обрабатывающей команды f0-00 и f0-01:
int FUN_cmdin_00_F000_08005fe0(int len, char *buf) { // ... предыдущий код ... short sVar4 = *(short *)(buf - 2); // D-Bus команда if (sVar4 == 0xF000) { *(short *)(puVar6 + 8) = 0; // Обнуляем слово по смещению 8 puVar6[7] = buf[2]; // Копируем байт из buf[2] в puVar6[7] puVar6[6] = buf[3]; // Копируем байт из buf[3] в puVar6[6] } else if (sVar4 == 0xF001) { puVar6[9] = buf[2]; // Копируем байт из buf[2] в puVar6[9] puVar6[8] = buf[3]; // Копируем байт из buf[3] в puVar6[8] puVar6[7] = buf[4]; // Копируем байт из buf[4] в puVar6[7] puVar6[6] = buf[5]; // Копируем байт из buf[5] в puVar6[6] } // ... последующий код ... }
По декомпилированному коду видно, что первая функция принимает 16-битный адрес во втором и третьем байтах аргумента, а вторая — 32-битный адрес в байтах со второго по пятый. В остальном логика обеих функций практически идентична (рис. 16).

Декомпилировав оставшуюся часть кода, исследователи обнаружили важную особенность: эти команды позволяют читать и записывать любые ячейки памяти модуля напрямую через D-Bus, невзирая на защиту микроконтроллера от чтения. Но что еще важнее — «нулевая подсистема» обнаруживалась во всех исследованных ими устройствах. По сути, они получили простой инструмент, позволяющий делать дампы прошивок со всех компонентов техники BSH, к которым можно подключиться по D-Bus.
Сказано — сделано. Исследователи попробовали считать прошивку модуля Timelight — небольшого проектора в посудомойке, который отображает на полу оставшееся время программы (рис. 17).

Первый шаг — базовый визуальный осмотр кода. Для этого исследователи воспользовались инструментом Binxelview. Если загрузить бинарник с шириной в 8 пикселей, можно сразу увидеть шрифт (рис. 19, справа от центра), которым на пол проецируется оставшееся время.

Если увеличить ширину еще немного, появится сначала логотип Siemens, а затем и Gaggenau (рис. 20), а далее и другие графические элементы.

Эти рисунки навели исследователей на мысль, что работа в BSH более творческая, чем может показаться на первый взгляд. А вот найти команду в D-Bus, которая выводит эту графику на пол, им так и не удалось.
2. Эксперимент по гибридизации: создание «продвинутого уровня совместимости Miele и BSH»
Облачная интеграция: реверс-инжиниринг модуля Home Connect
Итак, есть локальная интеграция в «умный дом» и есть дамп прошивки. Следующий шаг — облачная часть. У BSH для этого используется сервис Home Connect.
Связь с облаком в технике BSH обеспечивает отдельный коммуникационный модуль внутри машины. Этот модуль — небольшая черная коробка, которая служит мостом между двумя мирами: с одной стороны она подключена к D-Bus, а с другой — к сети Wi-Fi (рис. 21).

Для Home Connect существует официальный developer API. Однако исследователей интересовал другой вопрос: можно ли взаимодействовать с коммуникационным модулем напрямую, минуя официальные механизмы?
Исследователи установили, что этот коммуникационный модуль использует на D-Bus адрес 0xB и взаимодействует с модулем управления по адресу 0xA. Примечательно, что модуль управления обычно имеет адрес 0x1, но здесь для связи с коммуникационным модулем ему дополнительно выделен адрес 0xA.
Чтобы не опрашивать по шине устройство, модуль управления хранит у себя список всех возможных параметров и значений состояний (рис. 22). Он просто запрашивает у модуля управления по адресу 0xA таблицу параметров и таким образом получает текущее состояние устройства.

Для этого опроса предусмотрен отдельный набор команд: они позволяют модулю управления экспортировать табличную структуру со значениями в коммуникационный модуль (рис. 23). Кроме того, существует множество других команд, позволяющих коммуникационному модулю читать и изменять отдельные параметры устройства через облако.

Эти наблюдения позволили исследователю написать и опубликовать собственный стек для D-Bus под названием Open-D-Bus. Он выполняет хендшейк с коммуникационным модулем, после которого модуль ведет себя так, словно общается с посудомоечной машиной, а не с ESP32, и успешно подключается к облаку. На рис. 24 показан полный процесс установления соединения, завершающийся успешной инициализацией коммуникационного модуля.

Объединение двух миров: Miele и BSH
Итак, домашняя автоматизация реализована, дампы прошивок получены, коммуникационный модуль и стек open-dbus для BSH подключены. Такую же работу исследователи ранее проделали с устройствами Miele (об этом мы рассказывали в первой части обзора). Оставалось сделать очевидное для инженера и неочевидное для продакт-менеджера: заставить две конкурирующие экосистемы работать вместе.
Сказано — сделано. Исследователи взяли стиральную машину Miele, добавили библиотеку FreeMDU, затем реализовали AMBCL — «продвинутый слой совместимости техники Miele и BSH», полностью сгенерированный ИИ (нужно же где-то прикрутить вайб-кодинг). Сверху — стек Open-D-Bus, коммуникационный модуль и, наконец, приложение BSH Home Connect.

Таким образом исследователи соединили два мира. Если открыть приложение BSH, в нем корректно отображается устройство Miele, и его даже можно запустить (рис. 26).

Исследователи признаются, что реализация пока еще сыровата (рис. 27). Приложение, например, не реагирует, если в коммуникационный модуль отправить строку с названием производителя Miele. Изменить номер модели тоже нельзя. Кроме того, у Miele отсутствует понятие FD-номера, поэтому в соответствующее поле пришлось подставить значение по умолчанию.

Авторы исследования с иронией выражают надежду, что Miele и BSH как-то все-таки между собой договорятся и выпустят совместное обновление, которое устранит данные ограничения. На этом эксперимент можно считать завершенным: стиралку Miele теперь можно запустить с дивана через облачное приложение бренда-конкурента — пусть и с оговорками.

PURP — Telegram-канал, где кибербезопасность раскрывается с обеих сторон баррикад
t.me/purp_sec — инсайды и инсайты из мира этичного хакинга и бизнес-ориентированной защиты от специалистов Бастиона
