От взлома протокола в старом «железе» до разработки программ

dinadh_lzwxu6j6p2_yxgyt6ske.jpeg

Как-то раз получил задачу — «взломать» протокол передачи данных внутри торгового автомата. Торговый автомат по продаже охлаждённых газированных напитков, включает несколько цифровых плат, объединенных сетью RS-485 — судя по наличию чипов MAX485 на платах.

Заказчик хотел заменить старую плату индикации режима работы на Raspberry Pi, при этом протокола передачи данных у него не было и схем тоже. Сам заказчик и его громоздкое оборудование находилось очень далеко от нас, и чтобы не тратить лишнее время и деньги, предложили сфотографировать цифровые платы и купить дешевый китайский логический анализатор.

mih1s44sqgpr0kdn9dizieoncrc.jpeg

Cовместимый с программой Saleae Logic — очень удобная программа для такого взлома. На фото плат, сделанных заказчиком, нарисовали, куда подключиться на индикаторной плате, а именно на вход передатчика и выход приемника чипа MAX485 — чтобы видеть, что приходит на плату индикации и что она отправляет в ответ — если вообще отправляет.

3f0704938536dca223424d6d29be6250.jpg

Затем вместе удаленно, через Teamviewer, сделали записи потоков данных в различных режимах. Внимание! Teamviewer уже бесполезен, события давно происходили.

Примеры режимов в терминах платы индикации — всё исправно, идёт охлаждение сиропа, сироп закончился, общая неисправность, требуется обслуживание, и т.п. Всё это для двух независимых контейнеров с разным сиропом. На плате индикации все возможные состояния отображались 6-ю светодиодами.

В итоге получили более 16 файлов в формате Saleae Logic 1.x с записями во всех режимах, которые смог обеспечить заказчик на своем оборудовании. В программе сразу было видно, что скорость примерно 38925 бод (ближайшая стандарная 38400). Все остальные параметры передачи байта — 8 бит, 1 стоповый бит, без бита четности и т.п.

Программа Logic 1.x может показывать сразу расшифрованные байты, если задать параметры протокола передачи байта. По паузам получилось выделить отдельные сообщения. В итоге, после просмотра записи, получили представление о том, когда и какие байты передаются в различных ситуациях. Например, каждое сообщение начинается с байта 0xC0 и заканчивается байтом 0xC1:

Пауза 3с после включения
Байты принимаемые платой индикации: 0xC0, 0x01, 0x7D, 0xE0, 0x01, 0x40, 0xF7, 0xFA, 0xC1

Пауза 0.25мс
Байты принимаемые платой индикации: 0xC0, 0x01, 0x40, 0x01, 0x7D, 0xE0, 0xF6, 0x0A, 0x03, 0x01, 0x55, 0xC1

Пауза ~95 мс
Байты, принимаемые платой индикации: 0xC0, 0x02, 0x00, 0x01, 0x40, 0xF7, 0x8D, 0xC1,
0xC0, 0x01, 0x40, 0x02, 0x00, 0xF6, 0x28, 0x03, 0x00, 0xAB, 0xC1,

Пауза ~95 мс
Байты, принимаемые платой индикации: 0xC0, 0x02, 0x00, 0x01, 0x40, 0x13, 0x02, 0x83, 0xC1,   0xC0, 0x01, 0x40, 0x02, 0x00, 0x12, 0x02, 0x02, 0x02, 0x01, 0x01, 0x27, 0xC1,

Пауза 94 мс
Байты, принимаемые платой индикации: 0xC0, 0x01, 0x80, 0x01, 0x40, 0xF7, 0x1A, 0xC1,
0xC0, 0x01, 0x40, 0x01, 0x80, 0xF6, 0x20, 0x03, 0x04, 0x7D, 0x5D, 0xC1,

Пауза 95 мс
Байты, принимаемые платой индикации: 0xC0, 0x01, 0x80, 0x01, 0x40, 0x17, 0x02, 0x01, 0x00, 0x28, 0x60, 0x32, 0x00, 0x28, 0x60, 0x32, 0x00, 0x1D, 0x4C, 0x32, 0x00, 0x1D, 0x4C, 0x32, 0xF6 0xC1,
0xC0, 0x01, 0x40, 0x01, 0x80, 0x16, 0x20, 0xC1,

Пауза 1186 мс
Байты, принимаемые платой индикации: 0xC0, 0x01, 0x80, 0x01, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xC1,
		 0xC0, 0x01, 0x40, 0x01, 0x80, 0x14, 0x00, 0x35, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xC1

Пауза 49 мс
Байты, принимаемые платой индикации: 0xC0, 0x02, 0x00, 0x01, 0x40, 0x11, 0xB9, 0xC1

Пауза 9.3 мс
Байты, принимаемые платой индикации: 0xC0, 0x01, 0x40, 0x02, 0x00, 0x10, 0x00, 0xFA, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xC1-

Пауза 33.3 мс
Байты, принимаемые платой индикации: 0xC0, 0x01, 0x7D, 0xE0, 0x01, 0x40, 0x23, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xC1 
#-------- в этом сообщении есть байты, меняющиеся в зависимости от состояния устройства

Пауза 0.23 мс
Байты, передаваемые платой индикации:  0xC0, 0x01, 0x40, 0x01, 0x7D, 0xE0, 0x22, 0x64, 0xC1  

После изучения всех 16-ти записей стало ясно, что данные о состоянии устройства есть в сообщении, начинающимся с байтов 0xC0, 0×01, 0×7D, и после этого сообщения сразу следует сообщение от платы индикации.
Информации стало достаточно, чтобы заменить плату индикации на одноплатный миникомпьютер Raspberry Pi с адаптером RS-485.

rg0coneqkhxvifge00xz0eklwbk.jpegchxgytdd31i4d6jwrwtl9uzfvcg.jpeg

На своей стороне собрали имитатор передаваемых сообщений с выходом RS-485, добавили в него записанные сообщения. Подключили к своей Raspberry Pi через адаптер, написали и отладили простую программу на Python с выводом в консоль принимемых сообщений.

c_aaq7tadzvcans4eigclywd9y4.jpegrhrck-ywuinw9vonthfed3hqarc.jpeg

Заказчик закупил всё необходимое, отключил плату индикации и подключил Raspberry Pi через адаптер RS-485, согласно нашей схеме подключения. Предоставил нам удалённый доступ по SSH к подключенному Raspberry Pi. После подачи питания на устройство раздался возмущённый писк из торгового автомата, по документации — сигнализация о поломке.

Не обращая на писк внимания, запустили нашу программу. Писк исчез. Как выяснилось позднее, отсутствие быстрого ответа в виде сообщения от платы индикации воспринимается основной платой как поломка.

Данные о состоянии оборудования принимались правильно и стабильно.

Писк оказался проблемой. После включения питания торговый автомат немного пищал, пока запускалась программа на Raspberry. Иногда неожиданно автомат мог пискнуть, правда, это происходило крайне редко и не каждый день. Как выяснилось, время ожидания ответа менее 300 мкс. Сначала переписали программу приема данных на Си и запустили её отдельным процессом, потом разработали свою плату адаптера RS-485 Raspberry Pi с микроконтроллером, единственной задачей микроконтроллера было разпознавать запрос и оперативно на него отвечать. После этого писк после подачи питания исчез, так как микроконтроллер запускается почти мгновенно по сравнению со временем загрузки ОС в Raspberry Pi.

Симулятор с макетом нового адаптераСимулятор с макетом нового адаптера

Первая версия серийного адаптера с микроконтроллером:

p_10dh5oasfgebjwzvvgv9yufze.jpeg

Следующим этапом стало добавление функций в программу на Raspberry Pi, а именно запуск большого рекламного видео на мониторе, отображение
аварийных состояний иконками справа и слева, отправка телеметрии на web сервер.

Торговый автомат после всех доработок, с монитором и Raspberry Pi внутри. Работает моя программа. Желтые иконки внизу показывают, что сироп закончился:

afexe_qo08m7dkve8qkgv6i6auc.jpeg

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

© Habrahabr.ru