[Перевод] Подслушивает ли нас кофемашина? Купил её плату на eBay, получил root-доступ и запустил DOOM
Сервисное руководство Spengler PSL50: модуль экрана STUM_XXL с PIR-датчиком, микрофоном, ECO и динамиком
Автор оригинальной статьи: 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— проверяет наличиеautorun.shна USB-накопителе; -
/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. Иными словами, скрипт и хеш для его проверки размещаются на USB-накопителе. Вместо полноценной криптографической подписи кода механизм обновления использует самодельную проверку целостности с ключом. Секрет, записанный в файловой системе, объединяется с MD5-хешем autorun.sh, после чего результат снова хешируется и сравнивается со значением из hash.txt. Поскольку секрет хранится на устройстве в открытом виде, получив доступ к файловой системе, атакующий может повторить вычисление и подготовить действительный пакет обновления.
Но как получить доступ к USB-порту?
Видео: вскрытие замка автомата — https://www.youtube.com/watch?v=QJYCAjgUM0g

Как же мы распорядились полученными возможностями?

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

Видео: скрипт с USB-накопителя выполняет проверки — https://www.youtube.com/watch?v=XPitV76NglE
Так подслушивала кофемашина или нет?
Никаких признаков этого мы не обнаружили. В большинстве изученных конфигураций необходимого звукового оборудования не было вовсе. Более крупная версия дисплея и контроллера, по всей видимости, могла поддерживать звук — этим и объясняются упоминания микрофона в сервисной документации. Однако свидетельств того, что запись звука действительно использовалась, мы не нашли.
Но… пришло время ответить на вечный вопрос…

Совместимость программ прежде всего определяется архитектурой процессора, пользовательским 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
Coolpad Cool X Wide за 150 долларов: экран 6,38 дюйма, камера 50 Мп и 10 000 продаж за три дня
Коллекторов не рассекретят: банки России отвергли предложения МТС и «Мегафона» о маркировке звонков клиентам
Samsung подшутил над Apple, показав способ «убрать» чёрные полосы с экрана нового iPhone
Oppo выпустит смартфон с аккумулятором на 12 000 мА·ч уже в декабре
Nvidia передала независимому фонду технологию защиты автономных ИИ-агентов
Против Nvidia поданы первые иски на фоне расследования связей гендиректора с разведкой Китая
Google впервые за год выпустила четыре поколения чипов для ИИ, удвоив мощность без увеличения площади серверных стоек
33 мощнейших двигателя Raptor 3 вблизи: SpaceX показала ускоритель Super Heavy B22, который поймают «Мехазиллой»