Исследование

Динамический анализ компонентов прошивок IoT-устройств

Среди всех методов в наступательной безопасности (offensive security) можно выделить направленный поиск уязвимостей как наиболее актуальный при исследовании безопасности различных устройств из мира IoT/IIoT. Чаще всего такие устройства анализируются методом черного ящика, когда исследователю практически ничего не известно об объекте исследования. Как правило, это означает, что доступа к исходным кодам прошивки обычно нет, документация также отсутствует, и все, что в лучшем случае есть в распоряжении исследователя – руководство пользователя и несколько веток на каком-нибудь форуме с обсуждением работы устройства.

Поиск уязвимостей в устройствах IoT/IIoT основан на работе с прошивкой и включает в себя несколько этапов – подготовка прошивки (ее извлечение, распаковка), поиск интересных с точки зрения исследователя компонентов, запуск прошивки или ее частей с помощью эмулятора и, наконец, сам поиск уязвимостей. На последнем этапе применяются различные методы, включая статический и динамический анализ и фаззинг.

Пожалуй, чаще всего исследователи при изучении прошивок используют классическую связку из эмулятора QEMU и отладчика GNU Debugger. Мы решили рассказать про менее очевидные инструменты для работы с прошивками, каждый из которых имеет свои особенности, преимущества, и ограничения, которые делают их эффективными для решения тех или иных задач – в частности, о Renode и Qiling.

Renode – это инструмент, позволяющий эмулировать целевую систему полностью, включая эмуляцию микросхем памяти, сенсоров, дисплеев и другой периферии, а также взаимодействия между собой нескольких процессоров (на многопроцессорных устройствах), каждый из которых может иметь свою архитектуру и прошивку. Кроме того, Renode позволяет связать между собой эмулируемое оборудование и реальное «железо», реализованное в микросхеме ПЛИС.

Qiling – это продвинутый кроссплатформенный фреймворк для эмуляции исполняемых файлов, способный эмулировать множество ОС и окружений. С различной степенью зрелости в нем доступна эмуляция Windows, MacOS, Linux, QNX, BSD, UEFI, DOS, MBR и виртуальной машины Ethereum, поддержка архитектур x86, x86_64, ARM, ARM64, MIPS и 8086, поддержка различных форматов исполняемых файлов, а также эмуляция загрузки MBR.

В качестве объекта исследования мы выбрали реальное устройство – сетевой видеорегистратор одного из крупных производителей. Устройство построено на платформе компании HiSilicon, а в качестве операционной системы использует Linux.

Скачанная с сайта производителя прошивка состоит из единственного файла, в котором в результате анализа утилитой binwalk обнаруживается образ файловой системы CramFS. После его распаковки внутри находим комбинированный образ ядра Linux и initramfs — uImage, а также несколько зашифрованных скриптов и tar-архивов.

Рассмотрим, как работают Renode и Qiling на системном уровне.

О том, как использовать эти инструменты на прикладном уровне (на примере прошивки видеорегистратора) смотрите в полной версии статьи.

Эмуляция на системном уровне с помощью Renode

Renode – это инструмент полносистемной эмуляции, который, в  первую очередь, позиционируется разработчиками как инструмент, предназначенный для облегчения процесса разработки, отладки и автоматизированного тестирования встроенного ПО. Однако, его возможности позволяют использовать его и для целей динамического анализа поведения исследуемых систем при направленном поиске уязвимостей. С помощью Renode можно запускать как небольшие встраиваемые ОСРВ, так и полноценные операционные системы, такие как Linux и QNX. Большая часть эмулятора написана на языке C#, что позволяет относительно быстро адаптировать его функциональность под потребности исследователя.

Описание эмулируемой платформы

Как правило, периферийные устройства, входящие в состав однокристальных систем, доступны посредством Memory Mapped I/O (MMIO) – регионов физической памяти, на которые отражаются регистры соответствующих периферийных модулей. Renode предоставляет возможность собрать систему на кристалле как конструктор – из блоков, с помощью специального конфигурационного файла с расширением .repl (REnode PLatform), описывающего то, какие устройства следует разместить по каким адресам в памяти.

Информацию о доступных периферийных устройствах, а также карте распределения памяти в применяемой платформе можно почерпнуть из документации на SoC (при ее наличии в открытом доступе), а при ее отсутствии, например, проанализировав содержимое DTB (Device Tree Blob), – блока данных с описанием платформы для ядра Linux, который необходим для запуска Linux на встраиваемых устройствах.

В исследуемой прошивке блок DTB, по информации от того же binwalk, присоединен в конец файла uImage. Преобразовав DTB в читаемый формат (DTS) с помощью утилиты dtc, мы можем на его основе составить описание платформы для Renode.

Запуск эмуляции

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

Скрипт загружает uImage-файл в память платформы по адресу, который был получен из вывода binwalk, настраивает аргументы ядра и передает управление по адресу 0x40008040, так как первые 0x40 байт – это заголовок uImage.

Запустив эмуляцию, мы получаем полнофункциональный терминал, с которым можно взаимодействовать как обычно в любой Linux-системе:

Предоставляемых эмулятором Renode возможностей достаточно для быстрого начала работы с исследуемой прошивкой в динамике. В качестве наглядного примера нам удалось частично запустить прошивку сетевого видеорегистратора без самого регистратора. Далее с помощью имеющихся на эмулируемой файловой системе утилит можно расшифровать зашифрованные файлы прошивки, извлечь и проанализировать логику работы модулей ядра, обеспечивающих функциональность регистратора, и т. д.

Благодаря достаточно обширной поддержке эмулятором Renode периферии, часто используемой в системах на кристалле на базе архитектуры ARM, для того чтобы увидеть полнофункциональный терминал Linux часто даже не требуется писать какой-либо дополнительный код. В то же время, в случае возникновения такой необходимости, модульная архитектура самого эмулятора и предоставляемые им возможности написания скриптов и плагинов позволяют с относительно низкими трудозатратами реализовать поддержку отсутствующей функциональности на достаточном для проведения исследования уровне.

Из особенностей данного инструмента стоит отметить его низкоуровневость – эмуляция происходит на системном уровне, поэтому с его использованием сложно провести, например, фаззинг или отладку какого-либо user-space приложения, работающего в эмулируемой операционной системе.

К минусам же можно отнести отсутствие подробной документации – в имеющейся документации описаны лишь самые базовые сценарии работы с инструментом, а в процессе создания чего-то более сложного, как, например, нового периферийного устройства, а также для того, чтобы понять, как работает та или иная встроенная команда, придется неоднократно обращаться к GitHub-репозиторию проекта и изучать исходный код как самого эмулятора, так и имеющихся реализаций периферийных устройств.

Фаззинг с помощью Qiling Framework

Qiling Framework написан на языке Python, что позволяет достаточно легко адаптировать его функциональность под свои нужды. Qiling Framework использует под капотом движок Unicorn для эмуляции. Однако Unicorn – это просто эмулятор машинных инструкций, в то время как Qiling — это надстройка, предоставляющая большое количество высокоуровневых функций, таких как поддержка чтения файлов с файловой системы, загрузка динамических библиотек, и т. д.

В сравнении с QEMU Qiling Framework позволяет эмулировать большее количество платформ, предоставляет возможность гибкой настройки процесса эмуляции, включая, например, изменение выполняющегося кода на лету, и также является кроссплатформенным, то есть позволяет эмулировать, например, исполняемые файлы Windows или QNX на Linux и наоборот.

В рамках демонстрации попробуем запустить с помощью Qiling фаззинг имеющейся в прошивке утилиты hrsaverify с помощью AFL++. Данная утилита предназначена для проверки корректности зашифрованных файлов и принимает в качестве аргумента путь к файлу для проверки. В репозитории Qiling Framework уже имеется несколько примеров запуска фаззера AFL++ в директории examples/fuzzing. Для запуска утилиты hrsaverify мы адаптируем один из них, а именно linux_x8664. Перепишем скрипт запуска фаззера следующим образом:

Первое, на что следует обратить внимание, – это базовый адрес исполняемого файла (в нашем случае 0x10000), адрес функции main. Иногда бывает необходимо дополнительно установить перехватчики на другие адреса, факт перехода на которые фаззеру следует рассматривать как падение. Например, в примере запуска AFL в среде QNX (в директории qnx_arm) устанавливается такой дополнительный обработчик на адрес функции SignalKill в libc. В случае с hrsaverify можно обойтись без дополнительных обработчиков. Также следует обратить внимание, что все файлы, которые должны быть доступны для выполняемого приложения, следует помещать в sysroot и передавать пути к ним относительно него (в данном примере это ../../rootfs/hikroot/).

Непосредственно запуск AFL++ выполняется следующей командой:

В результате будет запущен фаззер AFL, и через некоторое время мы увидим результат его работы:

Qiling – перспективный инструмент, основными плюсами которого является высокая гибкость, легкая расширяемость, поддержка большого количества архитектур и окружений. Фреймворк может заменить QEMU в случаях, когда использование последнего не представляется возможным (неподдерживаемая целевая ОС или отсутствие необходимых дополнительных возможностей, таких как установка произвольных обработчиков на любые адреса памяти, особая обработка прерываний и т. д.). Платой за высокую гибкость и низкий порог вхождения за счет использования языка высокого уровня Python является относительно низкая скорость эмуляции и фаззинга.

Полная версия статьи опубликована на сайте Kaspersky ICS CERT.

Динамический анализ компонентов прошивок IoT-устройств

Ваш e-mail не будет опубликован. Обязательные поля помечены *

 

Отчеты

CloudSorcerer: новая APT-угроза, нацеленная на российские государственные организации

«Лаборатория Касперского» обнаружила новую APT-угрозу CloudSorcerer, нацеленную на российские государственные организации и использующую облачные службы в качестве командных серверов аналогично APT CloudWizard.

StripedFly: двуликий и незаметный

Разбираем фреймворк StripedFly для целевых атак, использовавший собственную версию эксплойта EternalBlue и успешно прикрывавшийся майнером.

Подпишитесь на еженедельную рассылку

Самая актуальная аналитика – в вашем почтовом ящике