Автор оригинала: Robin M.
Эта история начинается у кофейного автомата вроде этого…
Кто-то обронил, что в кофемашине есть микрофон, и мне стало интересно. Я скачал сервисное руководство той марки, перед автоматом которой стоял.

И вот он, на схеме: обозначение микрофона на плате! Я написал в сервисную компанию и спросил, зачем он нужен. Мне ответили, что это задел на будущее: датчик присутствия и движения для энергосбережения и доступности, который не реализован и не используется. Все просьбы разрешить изучить вопрос подробнее отклонили :-(
Но на помощь пришёл eBay! Там продавался такой модуль, и не слишком дорого, так что я решил рискнуть. Ник продавца, mrhankey91, стал забавным бонусом к этой истории.


Экран приехал в мою «лабораторию», посмотрим, что там внутри.


Разобрав руководство, надписи на плате и кое-что додумав, я пришёл к таким выводам:


RS485 — питание 24 В и модуль заваривания кофе;
MDB — модуль (бесконтактной) оплаты;
CUP — модуль подачи стаканчиков;
CAN — модуль энергосбережения;
RS232 и инфракрасный порт: EVA-DTS — стандартизованный Европейской ассоциацией вендинга интерфейс для считывания данных автомата через трёхконтактный джек или IrDA;
Escrow+door — датчик двери, обнаружение стаканчика, подсветка, приём денег и выдача сдачи;
AUX — датчик движения (PIR), динамик, микрофон;
Micro-HDMI — дополнительный экран;
Mini USB-B — Ethernet-гаджет для загрузчика через TFTP;
Ethernet — связь с базой: статистика и неисправности;
карта Micro SD — дополнительное хранилище или обновление ПО;
USB-A — порт для обновления ПО;
процессор i.MX 6: ARM Cortex A9;
старое ядро Linux 2013 года;
сборка Yocto;
ПО автомата и дисплея 2021 года;
ПО для учёта и передачи данных об использовании, ошибках, перерывах в обслуживании и т. п.;
есть микшер ALSA для обработки звука;
ПО для GSM-модема;
скрипты обновления через USB;
слот в стиле Mini PCIe / mSATA: под GSM-модуль (тоже для связи с базой: статистика и неисправности).
Проследив дорожки от нескольких конденсаторов, мы подали 24 В на нужные контакты, и плата с экраном включилась:

Через некоторое время появилось сообщение об ошибке: плата (что понятно) не может найти остальную часть автомата.
Немного покопавшись, мы нашли отладочный порт:

Щупами можно выяснить, на каких контактах во время загрузки появляется сигнал.


Проверка разъёма показала нечто похожее на сигнал UART 3,3 В во время загрузки:
RX — контакт 4, TX — контакт 5, GND — контакт 8;
скорость 115200, 8N1.
Чтобы получить консоль устройства, хватило подключить UART от Raspberry Pi с подходящими уровнями 3,3 В.

Видео загрузки: https://www.youtube.com/watch?v=w7k3NLBj1to
Консоль U-Boot во время загрузки не была защищена паролем и позволяла менять командную строку ядра. Ничто не мешало загрузиться с init=/bin/sh.
Достаточно в нужный момент нажать клавишу, чтобы прервать U-Boot. Через setenv можно попасть в оболочку сразу после загрузки ядра:

setenv bootargs console=ttymxc0,115200 root=ubi0:imx66 rootfstype=ubifs init=/bin/sh
После этого можно смонтировать файловую систему, сменить пароль root, перезагрузиться и войти под root…

[хакерским голосом] Я внутри…
Что я нашёл:
/etc/udev/rules.d/automount.rules— что делать, когда вставлен USB-накопитель;/etc/udev/scripts/mount.sh— проверяет, есть ли на USB-накопителеautorun.sh;/usr/setupscripts/validate_autorun.sh— проверяет, чтоautorun.sh— допустимый скрипт обновления:
#!bin/sh
AUTORUNPATH=$1
CONSOLE_OUTPUT=/dev/ttymxc0
ORG_MD5="$(md5sum $AUTORUNPATH/autorun.sh)"
set -- $ORG_MD5
NEW_MD5="$1"“[REDACTED_SECRET]"
RESULT="$(echo -n "$NEW_MD5" | md5sum )"
set -- $RESULT
#echo "calc hash: $1" > $CONSOLE_OUTPUT
CMP_MD5="$(cat $AUTORUNPATH/hash.txt | cut -b-32)"
#echo "read hash: $CMP_MD5" > $CONSOLE_OUTPUT
if [ "$1" = "$CMP_MD5" ]; then
echo "executing $AUTORUNPATH/autorun.sh" > $CONSOLE_OUTPUT
if [ ! -x $AUTORUNPATH/autorun.sh ]; then
chmod a+x $AUTORUNPATH/autorun.sh
fi
$AUTORUNPATH/autorun.sh
else
echo "authentication failed, ignored" > $CONSOLE_OUTPUT
fi
Обратите внимание на $AUTORUNPATH и на то, что hash.txt ожидается в той же папке, что и autorun.sh. Значит, и сам autorun.sh, и хеш для его проверки лежат на USB-накопителе! Вместо нормальной криптографической подписи кода механизм обновления использует самодельную проверку целостности с ключом. Секрет, зашитый в файловую систему, склеивается с MD5 от autorun.sh, результат хешируется ещё раз и сравнивается со значением из hash.txt. Поскольку секрет для проверки лежит на самом устройстве открытым текстом, доступ к файловой системе позволяет атакующему повторить вычисление и собрать валидный пакет обновления.
Но как добраться до USB-порта?

И что же мы сделали с этой новообретённой силой?

Проверим, не подслушивает ли нас автомат. Для этого напишем простой shell-скрипт на инструментах, которые уже есть на устройстве. Но нужно проследить, чтобы не сработал watchdog, обработать ошибки, как-то показывать ход работы и момент, когда скрипт закончил проверки, записал результаты на USB-накопитель и его можно вынимать. Скрипт должен:
приостановить штатную программу (иначе автомат может зависнуть или перезагрузиться);
выяснить, какое оборудование и ПО установлено (драйверы, номера версий и т. п.);
проверить, есть ли модем, Wi-Fi или другое сетевое подключение;
проверить, может ли устройство воспроизводить звук;
проверить, может ли оно записывать звук;
показывать ход работы набором картинок и сохранить все результаты на USB-накопитель;
возобновить штатную программу.

Так подслушивала кофемашина или нет?
Ничто на это не указывало. На оборудовании, которое мы изучили, в большинстве конфигураций нужного звукового железа не было вовсе. Более крупный вариант дисплея и контроллера, судя по всему, звук поддерживать мог, отсюда и упоминания микрофона в сервисной документации, но признаков того, что запись звука реально используется, мы не нашли.
Но… теперь пора ответить на извечный вопрос…

Совместимость программ зависит в первую очередь от архитектуры процессора, пользовательского ABI и библиотек, которые есть в системе. Здесь на плате процессор ARM Cortex-A9 и довольно старое пользовательское окружение с glibc 2.18. Старое ядро Linux 3.10.17 само по себе проблема меньшая: обычные пользовательские программы не нужно собирать под конкретную версию ядра, если они обращаются только к тем интерфейсам ядра, которые оно поддерживает.
Обычно для такого встраиваемого железа берут родной BSP (Board Support Package) или SDK с подходящим кросс-компилятором, библиотеками и заголовками. К сожалению, исходной среды разработки для этой заказной платы у нас нет. Пересобрать исходное окружение Yocto тоже оказалось непрактично: старые рецепты ссылаются на множество сторонних проектов и адресов с исходниками, часть которых по прежним адресам уже недоступна.

К счастью, DOOM портирован практически на всё. Есть порт fbDOOM, который рисует прямо в кадровый буфер Linux, а на этой плате рабочее устройство кадрового буфера есть. Зависимостей в пользовательском окружении у fbDOOM очень мало, так что для такой старой системы он хороший кандидат.
Остаётся libc. Бинарник, собранный в современной системе Linux, обычно ждёт glibc намного новее, чем версия 2.18 на кофемашине. Поэтому один вариант — кросс-компилировать fbDOOM в статически слинкованный бинарник с совместимой libc, чтобы он почти не зависел от библиотек, установленных на автомате. Другой — привезти с собой совместимое пользовательское окружение и явно вызвать его динамический загрузчик. В любом случае так можно собирать программу в современной системе и всё равно получить бинарник, который запустится в этом куда более старом окружении ARM.
И вот результат.
DOOM на тестовом экране в лаборатории: https://www.youtube.com/watch?v=G0dT6XedYFo
А ещё он запускается с подготовленного USB-накопителя. DOOM на кофейном автомате: https://www.youtube.com/watch?v=-mg8aKatJZE
![[Перевод] Слушает ли нас кофемашина? Купил её плату на eBay, получил root и запустил DOOM](https://habrastorage.org/extt/e0/3c/a9/e03ca9e8c85dd1d6c58e5af2af92d769.jpg)
Комментарии 0