Матричный принтер на антистатическом коврике печатает зелёный монопространственный текст с именами утилит и найденных уязвимостей. Янтарный свет выхватывает бумагу из абсолютной темноты.


На аудите IP-камеры с чипом Anyka и Tuya Cloud на борту binwalk выдал ноль распознанных сигнатур на весь 8-мегабайтный дамп SPI-флеша. График энтропии - ровная линия на уровне 7.98 из 8.0, классика шифрования. Два часа в Ghidra, XOR-декриптор в коде загрузчика U-Boot - и после расшифровки стандартный SquashFS с root-паролем в открытом тексте в /etc/shadow и CGI-скриптом, пробрасывающим HTTP-параметры прямо в system() без фильтрации. Три уязвимости класса Critical за одну сессию, ни одного запуска устройства. Ниже - полный workflow, который позволяет воспроизвести этот результат на произвольной прошивке.

Место анализа прошивки в цепочке атаки на IoT​

Реверс-инжиниринг прошивок - не отдельная дисциплина ради искусства. При пентесте IoT-устройства статический анализ firmware занимает конкретное место в kill chain и напрямую определяет, какие векторы эксплуатации откроются на следующих этапах.

В терминах MITRE ATT&CK работа с firmware затрагивает несколько тактик. Сбор информации о версиях прошивки - Firmware (T1592.003, Reconnaissance). Найденные захардкоженные учётные данные - одновременно Credentials In Files (T1552.001, Credential Access) и Default Accounts (T1078.001, Initial Access). Модификация образа для обхода проверок - Patch System Image (T1601.001, Defense Impairment). Закрепление через изменение firmware-компонентов - Component Firmware (T1542.002, Persistence). Деструктивное воздействие - Firmware Corruption (T1495, Impact).

Типичная последовательность при пентесте IoT-устройства:
  1. Получение firmware-блоба - скачивание с сайта вендора, дамп через SPI/JTAG, перехват OTA-обновления
  2. Статический анализ - извлечение файловой системы, поиск уязвимостей в бинарниках и конфигурациях
  3. Эксплуатация - подключение с найденными credentials, инъекция команд через веб-интерфейс
  4. Модификация firmware - патчинг образа для закрепления или обхода защит (если scope пентеста допускает)
Статический анализ - этап номер два. Без него пентест IoT превращается в слепой перебор портов и дефолтных паролей, а это малоэффективно для устройств с нестандартными сервисами.

Требования к окружению​

Прежде чем лезть внутрь прошивки - убедитесь, что рабочее место готово:

КомпонентМинимумРекомендуетсяПримечание
ОСUbuntu 22.04 LTSKali Linux 2024+macOS подходит для binwalk и Ghidra, но зависимости для нестандартных FS (sasquatch, jefferson) требуют GNU/Linux
RAM8 ГБ16 ГБGhidra на JVM жрёт 4-6 ГБ при анализе бинарников >10 МБ
Диск20 ГБ свободно50 ГБИзвлечённые FS могут занимать в 5-10 раз больше объёма блоба
binwalk2.3.x (ReFirmLabs/binwalk, GitHub)Сборка из masterЗависимости: p7zip-full, squashfs-tools, mtd-utils, jefferson, sasquatch
Ghidra11.x (NSA, Apache 2.0, активно поддерживается)11.3+Требует JDK 17+
radare26.1.x (текущая - 6.1.5, проект активен, LGPLv3)Последний masterДля скриптовой автоматизации, headless-анализ
Утилитыfile, strings, hexdump, dd+ flashrom для SPI-дамповСтандартные GNU-утилиты

Все инструменты работают offline. Интернет не нужен после установки.

Разведка: первичный анализ firmware-блоба​

file, strings и энтропия - выбор дальнейшей стратегии​

Анализ прошивки начинается не с дизассемблера, а с трёх базовых команд, которые за минуту определяют стратегию всего исследования.

file firmware.bin по magic bytes заголовкам определяет тип образа. Для GNU\Linux-based IoT типичный результат - u-boot legacy uImage с указанием архитектуры (ARM/MIPS), типа сжатия и точки входа. По данным Thyrasec, анализ firmware роутера Netgear R6950 через file сразу показывает: NAND Flash Image, Linux/MIPS, Load Address 0xA0200000 - этого достаточно для правильной загрузки в дизассемблер.

Дальше - strings -n 8 firmware.bin с минимальной длиной строки 8 символов, чтобы отсечь шум. Что конкретно искать в выводе:
  • Пути файловой системы (/etc/passwd, /etc/shadow, /var/run) - подтверждают GNU\Linux внутри
  • Форматные строки (%s, %d в контексте printf/sprintf) - потенциальные точки для format string атак
  • URL и IP-адреса - обращения к облачным API, захардкоженные адреса внутренних серверов
  • Ключевые слова (password, secret, key, token, admin) - прямые индикаторы захардкоженных credentials
  • Версии компонентов (U-Boot 1.1.3, BusyBox v1.19, OpenSSL 1.0.1) - для проверки на известные CVE в устаревших версиях, что соответствует A06:2021 Vulnerable and Outdated Components по OWASP Top 10
Если strings возвращает осмысленные результаты - прошивка не зашифрована, переходим к binwalk. Если на выходе только случайный мусор - анализируем энтропию.

binwalk -E firmware.bin строит график энтропии по блокам файла. Энтропия измеряется в битах на байт, максимум 8.0. Интерпретация:
  • 0-4 бита - незашифрованные данные, текст, таблицы, NOP-слайды
  • 5-7 бит - скомпилированный код или стандартное сжатие (gzip, LZMA). Binwalk справится
  • 7.5-7.9 - сильное сжатие. Нормально для отдельных сегментов (ядро в LZMA/XZ)
  • 7.9-8.0 ровной линией по всему файлу - шифрование. Сигнатуры binwalk бессильны
И вот тут критический нюанс, который почему-то упускают: энтропия 7.9 для одного сегмента прошивки (ядра) - норма. Ровная линия 7.9+ от начала до конца файла - признак полного шифрования образа. В таком случае декриптор ищем в незашифрованном загрузчике (первые 64-256 КБ).

Именно анализ энтропии определяет, пойдёт ли работа по автоматизированному пути или придётся руками разбирать шифрование. Пропустить этот шаг - потерять час на попытки распаковать зашифрованный блоб.

Извлечение файловой системы через binwalk​

1780217510262.webp

Для незашифрованных прошивок стандартный вызов binwalk -e firmware.bin распаковывает содержимое в директорию _firmware.bin.extracted/. Binwalk сканирует блоб по базе сигнатур, находит заголовки файловых систем и автоматически вызывает соответствующий распаковщик.

Типичный вывод для GNU\Linux-based IoT прошивки:
Код:
DECIMAL       HEXADECIMAL   DESCRIPTION
0              0x0           uImage header, Linux/MIPS, Standalone Program
170624        0x29A80       U-Boot version string, "U-Boot 1.1.3"
2097152       0x200000      uImage header, Linux Kernel Image, LZMA
5451776       0x534000      Squashfs filesystem, little endian, v4.0
Четыре компонента: загрузчик U-Boot, ядро Linux с LZMA-сжатием и файловая система SquashFS - наша основная цель. Именно там лежат конфигурации, веб-интерфейс, init-скрипты и пользовательские бинарники.

После извлечения в squashfs-root/ появляется стандартная GNU\Linux-иерархия. Первое действие - grep -rn "password\|passwd\|secret\|key" etc/ и проверка /etc/shadow на хеши паролей.

Нюанс по файловым системам: многие OEM используют модифицированные версии SquashFS с нестандартными заголовками. Стандартный unsquashfs их не поймёт - нужен sasquatch, форк с поддержкой нестандартных сигнатур Broadcom, Realtek, Qualcomm. Без него извлечение прошивок TP-Link, D-Link, Netgear часто падает с ошибкой. Для JFFS2 (NOR-флеш) - jefferson, для UBI/UBIFS (NAND-флеш) - ubireader.

Когда binwalk молчит - decision tree подхода​

УсловиеЭнтропияПодход
binwalk находит сигнатуры<7.9Стандартное binwalk -e
binwalk находит ядро, но не FS7.5-7.9 (сегменты)Установить sasquatch/jefferson/ubireader, повторить
binwalk не находит ничего<7.5Кастомный формат - ручной поиск magic bytes в hex-редакторе
binwalk не находит ничего>7.9 (весь файл)Шифрование - искать декриптор в загрузчике через Ghidra
binwalk находит загрузчик, остальное - шумПеременнаяВендор изменил заголовки - искать hsqs/sqsh через grep -boa

Реальный пример из исследования Westside Electronics: прошивка камеры MOWE на чипе Anyka содержала U-Boot с заголовком 95 00 00 EA вместо стандартного 27 05 19 56. Binwalk его не распознал, но в hex-дампе обнаружились повторяющиеся последовательности E0-EF - характерная сигнатура ARM-кода в little-endian. Исследователь загрузил сегмент в Ghidra, нашёл строку password err, проследил XREF до функции проверки пароля U-Boot и патчнул инструкцию beq на bne - инвертировал проверку и получил доступ к консоли загрузчика. Это прямая иллюстрация техники Patch System Image (T1601.001) из MITRE ATT&CK!!!

Для вырезания вручную найденной FS: dd if=firmware.bin of=fs.squashfs bs=1 skip=<смещение>, после чего unsquashfs fs.squashfs или sasquatch fs.squashfs.

Статический анализ бинарных файлов прошивки в Ghidra

1780217729300.webp

Загрузка и настройка проекта для ARM/MIPS​

После извлечения файловой системы основная работа переключается
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме

Паттерны уязвимостей в прошивках IoT

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

Захардкоженные учётные данные (CWE-798). Credentials In Files (T1552.001) и Default Accounts (T1078.001) в терминах ATT&CK. Проявления: известный хеш в /etc/shadow, пароль admin-панели в конфигурационном файле веб-сервера, строковая константа в бинарнике, которая передаётся в strcmp() при аутентификации. По данным исследования Kouser et al. (Saudi Journal of Engineering and Technology), при анализе контролируемого firmware-образа на базе SquashFS с помощью Ghidra и binwalk были успешно обнаружены все намеренно внедрённые захардкоженные credentials - что подтверждает достаточность инструментального подхода для этого класса уязвимостей.

Инъекции команд ОС (CWE-78). Самый опасный паттерн в IoT. Использование system() или popen() для вызова утилит (ping, traceroute, nslookup, iwconfig) с пользовательским вводом из HTTP-интерфейса. Фильтрация символов ;, |, &, обратных кавычек - либо отсутствует, либо реализована через неполный чёрный список, который обходится через $() или переводы строк. Для обнаружения достаточно найти XREF на system() в Ghidra и проследить аргумент до точки ввода.

Переполнение буфера (CWE-120). Бинарники IoT часто компилируются без stack canaries, ASLR и PIE - ресурсы микроконтроллера ограничены. Проверка: readelf -s binary | grep __stack_chk_fail (отсутствие = нет canary), readelf -h binary (тип ET_EXEC = PIE выключен). Вызовы strcpy(), sprintf(), gets() при отсутствии всех защитных механизмов - прямой путь к memory corruption и RCE.

Менее распространённые, но не менее критичные паттерны: криптографические ошибки (A02:2021 Cryptographic Failures по OWASP) - использование устаревших алгоритмов (DES, MD5 для хеширования паролей), хранение симметричных ключей в открытом виде в файловой системе; а также race condition при обработке конкурентных запросов к CGI.

Инструменты firmware-анализа - trade-off таблица​

КритерийbinwalkGhidraIDA Proradare2
ЗадачаИзвлечение компонентов из блобаДизассемблирование, декомпиляцияДизассемблирование, декомпиляцияДизассемблирование, скрипты
СтоимостьБесплатно (MIT)Бесплатно (Apache 2.0)Коммерческий ($1000+)Бесплатно (LGPLv3)
ДекомпиляторНетВстроенныйHex-Rays (отдельно)Плагин r2ghidra
GUIНет (CLI)ДаДаЧерез Cutter
Порог входаНизкийСреднийСреднийВысокий
ПреимуществаБаза сигнатур, автоматизацияБесплатный декомпилятор, сообществоSVD Loader для MCU, FLIRT-сигнатурыМалый footprint, headless
ОграниченияНе анализирует кодJVM медленнее на крупных бинарникахЛицензияКривая обучения, фрагментированная документация
Когда использоватьВсегда - первый шагОсновной инструмент декомпиляции firmwareMCU (STM32, PIC, Renesas) с SVDАвтоматизация: 50 прошивок за ночь
Когда не использоватьНужен анализ кода - не задача binwalk.NET/Java бинарникиНет бюджетаНужен GUI для навигации

Связка binwalk + Ghidra закрывает подавляющее большинство задач анализа прошивок IoT. IDA Pro оправдан при работе с голыми микроконтроллерами, где SVD-файлы и FLIRT-сигнатуры значительно ускоряют идентификацию периферии и библиотечных функций. radare2 (v6.1.5, проект активно развивается) - выбор для ситуаций, когда нужна headless-обработка большого числа образов через r2pipe. Я предпочитаю Ghidra для ручного анализа и r2 для скриптов - каждому своё.

Ограничения статического анализа firmware​

Понимание границ техники для пентестера важнее перечисления возможностей. Вот где статика перестаёт иметь смысл:

Обфускация и виртуализация кода. Коммерческие обфускаторы (VMProtect, Themida) превращают декомпилированный код в нечитаемый набор виртуальных инструкций. В массовом IoT встречается редко - обфускация увеличивает размер кода и потребление ресурсов MIPS/ARM-чипа. Но в automotive и телеком-оборудовании - всё чаще.

Шифрование с аппаратным ключом. Если ключ дешифрования хранится в OTP-памяти чипа или в Secure Element - статический анализ бессилен. Нужен физический доступ: fault injection, side-channel analysis, или дамп через JTAG до момента верификации ключа. Это уже hardware security research, а не binary analysis.

Stripped-бинарники. Большинство IoT-бинарников собраны без отладочных символов. Ghidra восстанавливает структуру функций по эвристикам, но имена придётся присваивать вручную. Для стандартных библиотек (uClibc, musl, newlib) частично помогает механизм Function ID - но «частично» тут ключевое слово.

Динамическое поведение. Статический анализ не покажет подгрузку кода из сети, расшифровку в runtime через dlopen()/mmap(), или поведение, зависящее от состояния железа. Для полного покрытия статику дополняют эмуляцией через QEMU или динамическим анализом на живом устройстве.

Кастомные бинарные протоколы. Статический анализ покажет структуру парсера проприетарного протокола, но не реальные пакеты. Для полной картины нужен перехват трафика через логический анализатор на UART/SPI/I2C.

Минилаб: первый анализ прошивки за 30 минут​

Для отработки навыка не нужна физическая железка. Большинство производителей роутеров (TP-Link, D-Link, Netgear, ASUS) публикуют firmware-образы на страницах поддержки в открытом доступе.

Требования: Ubuntu 22.04, 8 ГБ RAM, установленные binwalk с зависимостями и Ghidra.

Последовательность:
  1. Скачать .bin с сайта вендора для любой модели роутера
  2. file firmware.bin - определить архитектуру
  3. binwalk -E firmware.bin - оценить энтропию
  4. binwalk -e firmware.bin - извлечь содержимое
  5. grep -rn "password\|admin\|secret" squashfs-root/etc/ - искать credentials
  6. Найти httpd или lighttpd в squashfs-root/usr/sbin/, загрузить в Ghidra
  7. В Symbol Tree -> Imports найти system(), проследить XREF до аргумента
  8. Зафиксировать найденные уязвимости с CWE-идентификаторами
Весь цикл для незашифрованной прошивки укладывается в 30 минут. После двух-трёх таких итераций паттерны начинаешь узнавать на автомате - глаз цепляется за system() в импортах ещё до запуска автоанализа.

Чеклист аудита безопасности прошивки​

Список пригоден для включения в отчёт по пентесту IoT-устройства:
  1. Получить firmware (OTA, сайт вендора, дамп SPI через flashrom, перехват обновления)
  2. Определить архитектуру: file firmware.bin
  3. Оценить энтропию: binwalk -E firmware.bin - если >7.9 на всём файле, искать декриптор
  4. Извлечь FS: binwalk -e firmware.bin (при ошибках - sasquatch, jefferson, ubireader)
  5. Проверить /etc/shadow, /etc/passwd - дефолтные пароли, пустые хеши
  6. Выполнить grep -rn по всей FS: password, secret, key, token, api_key, private
  7. Определить версии BusyBox, OpenSSL, dropbear, lighttpd - проверить на известные CVE
  8. Загрузить управляющие бинарники в Ghidra (httpd, демоны, CGI)
  9. Найти все system(), popen(), execve() - трассировать аргументы до точек ввода
  10. Найти все strcpy(), sprintf(), gets() - проверить размеры буферов
  11. Проверить stack canaries: readelf -s binary | grep __stack_chk_fail
  12. Проверить PIE: readelf -h binary - тип ET_DYN = PIE включён, ET_EXEC = нет
  13. Проверить открытые отладочные интерфейсы: строки UART, JTAG, debug в конфигурации
  14. Проверить механизм обновления - подписана ли прошивка, есть ли проверка целостности
  15. Задокументировать находки с CWE-идентификаторами и CVSS-оценкой
Позиция индустрии IoT в вопросах firmware security за последние пять лет не сдвинулась. Те же system() с пользовательским вводом, те же root-пароли admin в /etc/shadow, те же BusyBox образца 2012 года с набором известных n-day уязвимостей. Инструменты стали доступнее - Ghidra сделал декомпиляцию бесплатной, binwalk автоматизирует рутину извлечения. Но проблема давно не в инструментах. OEM-производители собирают SDK от чипмейкера, меняют логотип на веб-интерфейсе и отгружают устройство без единого security review.

Два вектора, которые реально сдвинут ситуацию в ближайшие год-два: давление регуляторов (EU Cyber Resilience Act и аналоги начнут штрафовать за отсутствие базовых мер) и автоматизация firmware-аудита, снижающая порог входа до запуска одной команды. Для исследователя это означает одно: ценность ручного firmware RE только растёт. Автоматизация найдёт strcpy() без проверки размера - она не найдёт логическую ошибку в state machine кастомного протокола, позволяющую обойти аутентификацию без единого переполнения. Навык чтения декомпилированного кода Ghidra, поиск нетривиальных уязвимостей в бинарниках, умение разобраться в проприетарном загрузчике - на https://hackerlab.pro в категории reverse эти вещи отрабатываются на компактных задачах, прежде чем переходить к firmware-блобам на десятки мегабайт.
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab