Что именно исследовано
Объект этого досье — локальная директория BlackIris-main с кодом, подписанным AitorFirmware в LICENSE. Название само по себе не устанавливает связь с известной кампанией, коммерческим продуктом или другим bootkit. В частности, BlackIris нельзя отождествлять с BlackLotus: последний описан в отдельном исследовании ESET с собственной цепочкой и CVE. S28
В этом снимке главное расхождение проходит между широтой README и полнотой достижимой реализации. Вход ведёт в InitializeBootkit; эта функция сохраняет таблицы UEFI и вызывает установку перехвата ExitBootServices. Она не связывает все каталоги в единую доказанную цепочку. Некоторые подсистемы содержат явные заглушки. E19 E25
Статический разбор позволяет уверенно обсуждать эти расхождения. Он не заменяет сборку, а отсутствие динамического испытания не следует скрывать категорическим «никогда не работает». Точнее говорить: конкретная заявленная возможность не подтверждается просмотренным путём и требует недостающих свидетельств.
MmMapIoSpace: знакомое имя, другая реализация
В Boot/MemTools.c определена локальная функция MmMapIoSpace. Она вызывает UEFI AllocatePages с AllocateAddress и возвращает адрес выделенной области. Это не одноимённая Windows DDI. Выделить страницы по желаемому адресу и отобразить произвольный уже существующий физический диапазон — разные операции с разными предусловиями. E22
Параметр Write также не создаёт убедительной модели доступа: ветвь для его отрицательного значения пуста. Из имени функции нельзя вывести корректные атрибуты отображения, возможность доступа к защищённой памяти или жизнеспособность адреса после смены таблиц страниц. В качественном анализе символ всегда нужно доводить до его определения, а не до страницы документации похожего API.
Копирование функции не является загрузчиком
Перехват ExitBootServices копирует фиксированный объём байтов от KernelMain в выбранную область и вызывает её как функцию без параметров. Но KernelMain объявлена с аргументом EFI_SYSTEM_TABLE*. Уже на уровне сигнатур видна несогласованность. Дополнительно фиксированный размер копирования не доказывает перенос всех зависимых данных, относительных ссылок и вызываемых функций. E20 E21
Это архитектурная проблема доказательства: чтобы утверждать перенос исполняемой программы, нужно показать её формат, релокации, зависимости, ABI и время жизни. Название KernelRegion не переводит процессор в Windows kernel context. В момент вызова перед оригинальным ExitBootServices всё ещё действует загрузочный контекст UEFI.
Официальный контракт UEFI различает службы до и после завершения загрузочной фазы. Он не обещает, что произвольная функция, скопированная в runtime data, сможет продолжать пользоваться console input и boot services под запущенной ОС. S24
RemoteControl и Keylogger: какой канал существует на самом деле
InitRemoteControl выводит сообщение и возвращает TRUE. RemotePoll читает строку из локального буфера по условному физическому адресу, сравнивает её с предыдущей и передаёт обработчику. В этом участке нет сетевого соединения, аутентификации удалённой стороны или приёма TCP-сообщения. Наличие другого серверного каталога в проекте не доказывает транспорт между ним и этой функцией. E23
Клавиатурная часть использует EFI_SIMPLE_TEXT_INPUT_PROTOCOL и ReadKeyStroke. Подтверждённая семантика — чтение консольного ввода UEFI, пока соответствующий протокол доступен. Это не фильтр Windows keyboard stack и не основание заявлять сбор ввода из любых приложений после загрузки. E24
Red: обязательный вопрос к демонстрации — в каком контексте получен вывод. Строка из EFI-консоли не подтверждает работу на рабочем столе Windows, а локальный shared buffer не подтверждает удалённое управление.
Blue: опирайтесь на реально присутствующий артефакт и путь исполнения. Не стоит строить сетевой детектор несуществующего в просмотренной ветви протокола лишь потому, что README использует слово remote.
SMM: название обработчика не пересекает аппаратную границу
InstallSMIHandler в Shared/SyscallBridge.c прямо сообщает placeholder и возвращает TRUE. Отдельный PatchSMI.c сканирует память в поисках условной сигнатуры, а затем пытается изменить найденный участок. Этот код не показывает преодоление блокировок SMRAM и не доказывает, что найденная последовательность является настоящим SMI handler. E25 E27
Для вывода о SMM-импланте потребовались бы свидетельства выполнения в SMM, идентификации защищённого региона и условий доступа к нему. Здесь их заменяет предположение о доступности адресов. Методологически это тот же разрыв, что и с MmMapIoSpace: лексика проекта выглядит как низкоуровневая архитектура, но названия не дают привилегий.
В том же SyscallBridge виден небольшой локальный массив патча, после которого записывается указатель большего размера. Это конкретный повод сомневаться в корректности функции. Однако разбор не превращает эту находку в инструкцию по исправлению цепочки: для классификации достаточно установить, что успешный лог не является надёжным свидетельством выполненной операции. E25
Криптографическое обещание тоже проверяется в определении
В CryptoDefs.h комментарий прямо говорит, что SimpleAES не реализует полноценный AES. Тело выполняет собственные преобразования с таблицей подстановок и битовыми операциями. Поэтому называть этот компонент реализацией AES-256 на основании имён AESCore и AES_CONTEXT некорректно. E26
Здесь важен более общий вывод для ревью: наличие знакомого примитива в названии не подтверждает ни стандарт, ни режим, ни аутентификацию данных, ни обратимость преобразования. Для криптографического утверждения нужны спецификация, тестовые векторы и проверенная реализация. В этом досье такие проверки не выполнялись; утверждение ограничено несоответствием заявленного стандарта видимому коду и собственному комментарию автора.
Таблица заявлений и свидетельств
| Заявление | Наблюдение по снимку | Допустимый вывод |
|---|---|---|
| Работа в Windows KernelMode | EFI-типы и console input в KernelMain | Название каталога не устанавливает контекст |
| Runtime persistence | Hook до оригинального ExitBootServices | Нужно отдельно доказать жизнь после перехода |
| Remote control | Polling локальной памяти | Сеть в этом пути не подтверждена |
| SMI handler | Явная заглушка | Регистрация обработчика не реализована здесь |
| AES-256 | Собственное преобразование, авторский комментарий | Стандартный AES не подтверждается |
| Secure Boot bypass | Вход предполагает уже исполняемый EFI | Первичный обход доверия не показан этим входом |
Чем полезен такой образец
BlackIris полезен как проверка дисциплины анализа. Его нельзя оценивать только по списку функций, но и просто отбросить как «несерьёзный» недостаточно: конкретные опасные операции с памятью всё равно есть. Нужно разделять намерение автора, доступность функции, корректность её контракта и доказанный эффект на реальной платформе.
Именно эта дисциплина предотвращает две ошибки одновременно: преувеличение угрозы неработающей цепочки и недооценку отдельного действительно опасного компонента. Вывод относится к зафиксированным файлам и их хешам, а не к любой будущей версии проекта с тем же названием.
Источники и исходники
Ссылки E ведут к свидетельствам по локальному коду; S — к первичным внешним публикациям. Диапазон относится к оригинальному файлу. Статическое исследование, без запуска образцов.
S28 / BlackLotus UEFI bootkit: Myth confirmed ↗
Martin Smolár / ESET Research · 01.03.2023. Первичный внешний источник. Доступ: 12.09.2026.
E19 / BlackIris-main/src/Boot/Loader.c
Строки 9–22 · Достижимая из входа инициализация ограничена установкой ExitBootServices hook.
Локальный снимок · файл: 22 строк · ссылка на публичный commit не установлена.
SHA-256 d109ec001c162ac5a3145bdf21083d1a566cc6acf9b8d25c9b3048d94bb3109c
Посмотреть фрагмент исходника · строки 16–19
16 Status = InstallExitBootServicesHook();
17 if (EFI_ERROR(Status)) {
18 return Status;
19 }E25 / BlackIris-main/src/Shared/SyscallBridge.c
Строки 19–33 · SMI-функция явно placeholder; отдельный локальный массив патча слишком мал.
Локальный снимок · файл: 52 строк · ссылка на публичный commit не установлена.
SHA-256 28fe6edcb56e8b47cbea1f48fb34e2bd48b800a235a3466472a123cb7451bdcb
Посмотреть фрагмент исходника · строки 19–22
19 BOOLEAN InstallSMIHandler(VOID* HandlerFunc) {
20 LogInfo(L"SMI Handler installed (placeholder).");
21 return TRUE;
22 }E22 / BlackIris-main/src/Boot/MemTools.c
Строки 5–26 · Локальная функция с именем MmMapIoSpace использует AllocatePages; это не Windows DDI.
Локальный снимок · файл: 26 строк · ссылка на публичный commit не установлена.
SHA-256 1cb87560aac88e6e795ced89d04f2ad85d56398716a794b8363845417ed7b004
E20 / BlackIris-main/src/Boot/DXEHook.c
Строки 11–31 · Фиксированное копирование тела функции и вызов без параметра SystemTable.
Локальный снимок · файл: 31 строк · ссылка на публичный commit не установлена.
SHA-256 71307a623e9089577d029ee1b058aa43261e6f638de816905dfe56e556d115b5
E21 / BlackIris-main/src/KernelMode/BotStartup.c
Строки 13–35 · KernelMain остаётся функцией с UEFI-типами, принимающей SystemTable.
Локальный снимок · файл: 36 строк · ссылка на публичный commit не установлена.
SHA-256 26767647b36b3e9f71844b75f555a0453507db770ee80dcfe6af9244242ec149
S24 / UEFI 2.11: Runtime Services ↗
UEFI Forum · 2.11. Первичный внешний источник. Доступ: 12.09.2026.
E23 / BlackIris-main/src/KernelMode/RemoteControl.c
Строки 11–28 · Инициализация лишь возвращает TRUE; polling читает локальный буфер.
Локальный снимок · файл: 28 строк · ссылка на публичный commit не установлена.
SHA-256 ad9f9af9b440ac4fbb7fbd8fad89f547024a688c318b88b76a19a9a284b5756c
Посмотреть фрагмент исходника · строки 11–14
11 BOOLEAN InitRemoteControl(void) {
12 LogInfo(L"Started successfully\n");
13 return TRUE;
14 }E24 / BlackIris-main/src/KernelMode/Keylogger.c
Строки 6–37 · Чтение EFI console input; не Windows keyboard stack.
Локальный снимок · файл: 37 строк · ссылка на публичный commit не установлена.
SHA-256 e56871a4a89cca497f8a69b546c6d03e0f5433823f834e61da5e51f1a200a4ac
E27 / BlackIris-main/src/Boot/PatchSMI.c
Строки 11–46 · Поиск условного маркера памяти не показывает преодоление аппаратной защиты SMRAM.
Локальный снимок · файл: 46 строк · ссылка на публичный commit не установлена.
SHA-256 fa6ab793cb394c08e847fcab2d3471366c4547f2ba1723ac363c338877f55265
E26 / BlackIris-main/src/Encryptor/CryptoDefs.h
Строки 42–72 · Комментарий прямо отрицает полноценную реализацию AES; ниже собственное преобразование.
Локальный снимок · файл: 75 строк · ссылка на публичный commit не установлена.
SHA-256 221627915332bc03dd0230fe2e4633b7aff575701f63cf43b4d2554fd26bc725
Посмотреть фрагмент исходника · строки 42–45
42
43 //
44 // Inline functions for encrypting and decrypting fcking blocks
45 // It does not implement full real AES by size, but simulates a complex XOR + SBOX.