Статья Реверс-инжиниринг UEFI-прошивки: от дампа SPI-flash до анализа DXE-драйверов в Ghidra

Руки на тёмной клавиатуре в зеленоватом свечении монитора с деревом томов UEFITool и дизассемблером Ghidra. Янтарно-зелёная атмосфера, глубокие тени.


На аппаратном пентесте серверной платформы я снял дамп SPI-flash и обнаружил в DXE-томе модуль, которого не было в исходной прошивке с сайта вендора. Два дня реверса через Ghidra - выяснилось: кастомный драйвер интегратора, не закладка. Но путь от подозрения до вердикта потребовал полного цикла анализа UEFI-прошивки - binwalk, UEFITool и Ghidra в связке. Цикл, от извлечения UEFI-образа до идентификации подозрительных модулей, и разберём - с конкретными командами и паттернами, которые экономят время.

Место UEFI-анализа в цепочке атаки​

Реверс-инжиниринг UEFI-прошивки - не так сложен, как может показаться. Firmware-level persistence входит в арсенал APT-групп, и пентестеру нужно понимать этот вектор с обеих сторон. В MITRE ATT&CK анализ прошивки затрагивает несколько техник:
  • System Firmware (T1542.001, Persistence / Defense Evasion) - модификация прошивки для закрепления. Имплант переживает переустановку ОС и замену диска, так как перезаписывает код BIOS или UEFI.
  • Bootkit (T1542.003, Persistence / Defense Evasion) - внедрение в цепочку загрузки. Перехват управления до старта ОС.
  • Component Firmware (T1542.002, Persistence / Defense Evasion) - изменение прошивок отдельных компонентов: сетевых карт, BMC-контроллеров, дисковых контроллеров.
  • Firmware Corruption (T1495, Impact) - деструктивное воздействие: «окирпичивание» платформы через порчу прошивки.
  • Firmware (T1592.003, Reconnaissance) - сбор данных о версиях прошивок цели перед атакой.
Исследование UEFI модулей нужно в трёх сценариях. Первый - аппаратный пентест с физическим доступом: снимаем дамп, ищем уязвимости в SMM-обработчиках, проверяем конфигурацию Secure Boot, оцениваем защиту SPI-flash от записи. Второй - supply chain security: заказчик получил партию серверов и хочет убедиться, что прошивка совпадает с эталоном вендора. Третий - incident response при подозрении на firmware-level persistence: сравниваем дамп с референсом и препарируем любые расхождения.

Модель доступа: white box (вендор дал эталонный образ и спецификацию платформы) или grey box (дамп снят с устройства, эталон скачан с сайта вендора). Целевые платформы - x86/x64 системы с UEFI: серверы, рабочие станции, ноутбуки. Прошивки на базе открытых проектов (EDK II/Tianocore) и проприетарные реализации (AMI Aptio, Insyde H2O, Phoenix SecureCore).

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

Прежде чем лезть в статический анализ прошивки BIOS - подготовьте рабочее место.

КомпонентМинимумРекомендуется
ОСLinux (Ubuntu 22.04+) или Windows 10Linux - удобнее для CLI-инструментов
RAM8 ГБ16 ГБ (Ghidra жрёт память при анализе крупных модулей)
Ghidra10.x11.x, активно поддерживается NSA, регулярные релизы
UEFIToolNE (New Engine)Обе версии: NE для навигации, старая для модификации
binwalk2.3+3.x (Rust-перепись от оригинального автора, активная разработка)
Python3.8+3.10+ для скриптов Ghidra и efiXplorer
Средство дампаflashrom или CHIPSECSPI-программатор (CH341A ~500 руб., Dediprog ~15 000 руб.)

Дополнительно: плагин efiXplorer для Ghidra (разработка Binarly, открытый исходный код, последний коммит - 2024, проект активный). Установка - через менеджер расширений Ghidra или ручное копирование в директорию Extensions.

Извлечение UEFI-образа: программный и аппаратный подход​

Прошивка хранится в SPI NOR flash - микросхеме на материнской плате. Без дампа этой микросхемы анализ невозможен.

Программный дамп​

На работающей GNU/Linux-системе SPI flash дамп снимается одной командой: flashrom -p internal -r firmware_dump.bin. Альтернатива - Intel CHIPSEC: chipsec_util spi dump firmware_dump.bin делает то же самое, но дополнительно позволяет проверить статус защитных регистров SPI - BIOS Write Enable, BIOS Lock Enable, PRx-регионы (Protected Range Registers).

Ограничение программного метода: на современных платформах с Intel Boot Guard или активными SPI Protected Ranges дамп будет неполным. ME-регион и часть BIOS-региона окажутся заполнены нулями (0x00) или пустыми (0xFF). Для полного дампа нужен аппаратный подход.

Аппаратный дамп​

SPI-программатор подключается напрямую к микросхеме flash-памяти - через SOIC-8 клипсу (внутрисхемное чтение) или после выпаивания чипа. Команда flashrom -p ch341a_spi -r firmware_dump.bin снимает дамп через CH341A. Для надёжности - два дампа подряд с проверкой хешей: sha256sum dump1.bin dump2.bin. Хеши разъехались - проблема с контактом клипсы, нужно пережать или зачистить площадки.

Аппаратный метод обходит любые программные блокировки, но требует физического доступа к плате. На практике - открутить крышку, найти SPI flash (обычно SOIC-8 корпус рядом с южным мостом), подключить клипсу. Весь процесс - 10-15 минут, если знаешь расположение микросхемы на конкретной плате. (На незнакомой плате первый раз можно и полчаса провозиться, пока найдёшь нужный чип среди десятка похожих.)

Первичная разведка с binwalk: что покажет и что пропустит​

binwalk - первое, что запускаю на свежем дампе. Он сканирует файл на сигнатуры известных форматов, ищет сжатые потоки, определяет границы вложенных структур.
Код:
$ binwalk firmware_dump.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------
0             0x0             Intel Flash descriptor
4096          0x1000          Intel ME firmware region
2097152       0x200000        UEFI PI Firmware Volume, GUID: ...
3145728       0x300000        LZMA compressed data, properties: 0x5D
3276800       0x320000        UEFI PI Firmware Volume, GUID: ...
7340032       0x700000        UEFI PI Firmware Volume, GUID: ...
binwalk для UEFI полезен на этапе первичной разведки: определяет границы регионов (Intel Flash Descriptor, ME, BIOS), находит firmware volumes, обнаруживает сжатые секции. Полный анализ (binwalk -E firmware_dump.bin) выделяет участки с аномально высокой аномальностью - потенциально зашифрованные данные. Для UEFI высокая энтропия в LZMA-сжатых секциях - норма. А вот участок с энтропией ~1.0, не распознанный как известный формат сжатия, - повод копнуть глубже.

Извлечение компонентов: binwalk -e firmware_dump.bin вытаскивает распознанные файлы в отдельную директорию. Для UEFI результат потребует ручной сортировки - binwalk создаст набор firmware volumes и сжатых блоков без понимания их иерархии.

Чего binwalk UEFI-прошивке не даст:
  • Не парсит иерархию вложенных firmware volumes
  • Не понимает EFI_FFS_FILE_HEADER - не идентифицирует модули по GUID и типу (PEI/DXE/SMM)
  • Не показывает зависимости между модулями (протоколы, PPI, события)
  • Не отличает PEI-модуль формата TE от DXE-драйвера формата PE32+
По сути, binwalk - это быстрая валидация: убедиться, что дамп прочитался корректно, увидеть общую карту регионов, найти очевидные аномалии. Для структурного разбора UEFI нужен UEFITool.

UEFITool: навигация по томам и извлечение модулей​

UEFITool - специализированный инструмент для работы со структурой UEFI-прошивок, созданный CodeRush (LongSoft). Без него реверс-инжиниринг UEFI прошивки превращается в бессмысленное блуждание по hex-дампу.

При открытии дампа UEFITool строит дерево:
  • Flash Image → Regions (BIOS, ME, GbE, PDR)
  • BIOS Region → Firmware Volumes (FV)
  • Firmware Volume → Files (каждый файл - отдельный модуль)
  • File → Sections (PE32 Image, TE Image, Compressed, UI Name, DependencyExpression)
Каждый файл имеет тип: EFI_FV_FILETYPE_PEIM (PEI-модуль), EFI_FV_FILETYPE_DRIVER (DXE-драйвер), EFI_FV_FILETYPE_SMM (SMM-модуль), EFI_FV_FILETYPE_FREEFORM (произвольные данные, часто картинки) и другие. По данным из анализа типовой прошивки (RU-3), распределение модулей примерно такое: 50-60 PEIM, 190-200 DXE-драйверов, 50-60 SMM-модулей и до сотни Freeform-файлов с ресурсами. Зоопарк приличный.

Ключевые операции с UEFITool​

Поиск по GUID. Каждый UEFI-модуль идентифицируется 128-битным GUID. В UEFITool NE - Action → Search → GUID. Принцип такой, если знаю GUID подозрительного модуля (из публичных исследований или списка известных имплантов) - ищу напрямую. Если нет - ищу по тексту в секциях UI Name.

Извлечение модулей для Ghidra. Правый клик на секции PE32 → Extract body. Результат - чистый PE32+ файл, который Ghidra распознаёт при импорте. Для PEI-модулей в формате TE - аналогично, у Ghidra есть встроенный TE-загрузчик.

Обнаружение аномалий. UEFITool сигнализирует о нарушениях спецификации UEFI PI. Пример из практики (описан CodeRush в разборе HP SecureUpdating): данные в свободном пространстве DXE-тома оказались контрольной суммой, спрятанной производителем вне рамок спецификации. Модуль SecureUpdating обращался к этим данным по фиксированному смещению для проверки целостности тома. Такие аномалии - точки входа в глубокий анализ.

Сравнение с референсом. Скачиваю эталонную прошивку с сайта вендора, открываю оба образа в двух экземплярах UEFITool. Побайтово сравниваю состав модулей: любое расхождение в количестве файлов, изменение GUID-ов, модифицированные секции PE32 - потенциальный индикатор компрометации. Добавленные DXE-драйверы, отсутствующие в референсе, - приоритет номер один.

На что обращать внимание при первичном осмотре: модули без секции UI Name (или с generic именем), DXE-драйверы вне основного DXE-тома, файлы типа RAW с нетипичным содержимым, секции DependencyExpression со ссылками на нестандартные протоколы.

Ghidra для анализа UEFI-прошивки: загрузка, плагины, идентификация сервисов​

1779784459902.webp

После извлечения интересующих модулей из UEFITool переходим к глубокому анализу в Ghidra. Ghidra - основной инструмент для статического анализа прошивки BIOS на уровне кода.

Загрузка PE/TE-модулей​

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

Ручная идентификация сервисных вызовов​

Точка входа DXE-драйвера получает два параметра: ImageHandle и указатель на EFI_SYSTEM_TABLE. Из SystemTable по смещению 0x60 (для 64-бит) достаётся указатель на EFI_BOOT_SERVICES, а дальше - конкретные сервисы по смещениям в этой таблице (смещения по UEFI Specification 2.x для 64-битной платформы).
Код:
MOV  RAX, [RDX+60h]       ; SystemTable->BootServices
MOV  RAX, [RAX+140h]      ; BootServices->LocateProtocol (UEFI 2.x, 64-bit)
LEA  R8,  [RSP+28h]       ; Interface (выходной указатель)
LEA  RDX, [rip+GUID_addr] ; указатель на GUID протокола
XOR  ECX, ECX             ; Registration = NULL
CALL RAX
Смещения в таблице - ключ к идентификации сервиса. Наиболее частые Boot Services (описание по SentinelOne): AllocatePool/FreePool (аналоги malloc/free), AllocatePages/FreePages (аналоги VirtualAlloc/VirtualFree), LocateProtocol (поиск протокола по GUID), InstallProtocolInterface (публикация нового протокола), CreateEvent/SignalEvent (событийная модель).

Для PEI-модулей схема аналогична, но вместо EFI_SYSTEM_TABLE используется двойной указатель на EFI_PEI_SERVICES. Как отмечено в разборе HP SecureUpdating: «разыменование двойного указателя - не слишком популярная процедура в обычном коде, поэтому большую часть вызовов PEI-сервисов можно отследить глазами прямо в листинге». Характерный паттерн: MOV EAX, [EBP+PeiServices]MOV EAX, [EAX]CALL [EAX+offset] - двойное разыменование с последующим вызовом по смещению. Когда привыкнешь к этому паттерну - он буквально бросается в глаза в листинге.

Протоколы и зависимости между модулями​

Каждый протокол UEFI идентифицируется уникальным GUID. Когда модуль вызывает LocateProtocol с определённым GUID, он зависит от модуля, установившего этот протокол через InstallProtocolInterface. Восстановление этих зависимостей (Static Dependency Graph) для всех модулей прошивки - задача, описанная в RU-3 как «алгоритмически не разрешимая в общем случае», но на практике для конкретной прошивки - вполне подъёмная.

Для firmware security research приоритетны модули, устанавливающие или использующие протоколы, связанные с SMM (EFI_SMM_* GUID-ы), SPI-контроллером (SPI Flash Protocol), Secure Boot (Image Verification Protocol, переменные PK/KEK/db/dbx).

Паттерны UEFI-уязвимостей и имплантов: что искать в прошивке​

SMM Callout​

SMM (System Management Mode) - самый привилегированный режим x86-процессора. Код в SMRAM недоступен даже ядру ОС. SMM callout - класс уязвимостей, при которых SMI-обработчик использует данные или вызывает код из памяти, контролируемой непривилегированным кодом.

При анализе SMM-драйверов (тип EFI_FV_FILETYPE_SMM в UEFITool) ищу: обращения к CommBuffer (область обмена данных между ОС и SMM) без проверки, что указатели ведут внутрь SMRAM; вызовы функций по указателям из CommBuffer; использование SmmGetVariable для чтения UEFI-переменных без валидации размера буфера. Каждый из этих паттернов - потенциальный вектор эскалации из ring-0 в SMM.

Контекст применимости: внутренний пентест или аудит с физическим доступом. Эксплуатация SMM callout требует привилегий ядра ОС (ring-0) - это техника повышения привилегий, а не начального доступа.

UEFI Secure Boot обход​

1779784439774.webp

Secure Boot верифицирует подписи загружаемых модулей через цепочку доверия: PK → KEK → db/dbx. Обход возможен через уязвимости в парсере PE-заголовков (integer overflow при обработке размеров секций), манипуляции с NVRAM-переменными (если запись в PK/KEK/db не заблокирована), или загрузку подписанного, но уязвимого загрузчика (shim, GRUB), через который передаётся управление неподписанному коду.

В Ghidra ищу модули, обращающиеся к Secure Boot-переменным: строки SecureBootEnable, PK, KEK, db, dbx в секции данных. Модули, способные менять эти переменные или обходить проверку подписей в DXE-фазе, - приоритетные цели, если они не заблокированы.
В файле:
efivar -a -n PK -d pk.cer
Загружаем подписанный, но уязвимый загрузчик (shim, GRUB), через который передаётся управление неподписанному коду.
grub2-install --target=x86_64-efi --efi-directory=/boot/efi --boot-loader-id=GRUB
Используем уязвимость в парсере PE-заголовков для обхода проверки подписей.

Обнаружение UEFI rootkit и firmware-имплантов​

Имплант уровня UEFI - DXE-драйвер, внедрённый в прошивку для закрепления (T1542.001, Persistence). Публично известные примеры (LoJax, MosaicRegressor) работали по одной схеме: добавленный DXE-модуль при каждой загрузке сбрасывал на диск агент, переживающий переустановку ОС и замену жёсткого диска.

Признаки импланта:
  • DXE-модуль, отсутствующий в эталонной прошивке вендора
  • Модуль без UI Name секции или с нехарактерным именем
  • Обращения к файловой системе через EFI_SIMPLE_FILE_SYSTEM_PROTOCOL из DXE-фазы (нетипично для легитимных драйверов платформы)
  • Сетевые обращения через EFI_SIMPLE_NETWORK_PROTOCOL до загрузки ОС
  • Запись данных на диск через DiskIo/BlockIo протоколы в DXE-фазе
  • Обфускация кода (T1027, Defense Evasion) или деобфускация данных в runtime (T1140, Defense Evasion)
Основной метод обнаружения UEFI rootkit - сравнение дампа с эталоном. Дамп SPI flash с устройства побайтово сравнивается с прошивкой, скачанной с сайта вендора. Расхождения анализируются в UEFITool: какие модули добавлены, какие изменены, какие секции отличаются. Тупо, но работает - и ничего надёжнее пока не придумали.

Сравнение инструментов анализа firmware​

ИнструментЭтап workflowПреимуществаОграниченияКогда не подходит
binwalkПервичная разведкаБыстрый, универсальный, энтропийный анализНе понимает иерархию UEFI FVДетальный анализ модулей
UEFIToolНавигация, извлечениеПолный парсинг UEFI-структуры, поиск по GUIDНет дизассемблераАнализ логики кода
Ghidra + efiXplorerГлубокий анализ кодаБесплатный, расширяемый, автоматизация UEFI-типовТребует ручной доработки для нестандартных прошивокБыстрый обзор структуры
CHIPSECАудит конфигурацииПроверка SPI lock, SMM lock, Secure BootНе анализирует код, только конфигурациюРеверс конкретных модулей
QilingДинамический анализЭмуляция DXE-модулей, трассировка вызововНеполная эмуляция HW, не все протоколы реализованыPEI-фаза и HW-зависимый код

На практике workflow линейный: flashrom/CHIPSEC (дамп) → binwalk (разведка, SPI flash дамп анализ) → UEFITool (навигация, извлечение) → Ghidra (глубокий анализ). Инструменты не конкурируют - они покрывают разные этапы конвейера. Пытаться анализировать UEFI-прошивку только в Ghidra без UEFITool - всё равно что реверсить PE-файл без понимания структуры PE-заголовка: технически возможно, но вы просто утонете.

Firmware-уровень нередко выпадает из скоупа пентестерских команд. Стандартный аргумент: «у нас нет физического доступа» или «это слишком нишевая тема». Но реальность меняется - всё больше заказчиков включают firmware assessment в скоуп аппаратного пентеста, особенно в критической инфраструктуре и финтехе. И тут выясняется, что команда, уверенно работающая с AD и web, оказывается беспомощной перед дампом SPI-flash.

Барьер при этом не в инструментарии. Ghidra с efiXplorer опустил порог входа до уровня «умеешь реверсить PE на Windows - разберёшься с DXE-драйвером за день». Барьер - в понимании архитектуры: фазы загрузки (SEC → PEI → DXE → BDS), модель протоколов, граница SMM, специфика TE-формата. Эту базу реально освоить за неделю целенаправленной работы с дампом реальной прошивки, а не с документацией UEFI PI в вакууме. По моей оценке, BIOS reverse engineering будет всё активнее востребован в командах, работающих с аппаратной безопасностью, а firmware assessment войдёт в стандартные чеклисты пентеста критической инфраструктуры. Навык чтения дизассемблерного листинга, наработанный на UEFI-модулях, прямо переносится на reverse-задачи на HackerLab.pro - подход тот же, формат компактнее.
 
Последнее редактирование модератором:
  • Нравится
Реакции: Marylin
Мы в соцсетях:

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

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

HackerLab