eXeLab
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 28 января!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Русский / Russian English / Английский

Сейчас на форуме: hlmadip (+3 невидимых)
 · Начало · Статистика · Регистрация · Поиск · ПРАВИЛА ФОРУМА · Язык · RSS · SVN ·

 eXeL@B —› Крэки, обсуждения —› UEFI руткиты
<< . 1 . 2 .
Посл.ответ Сообщение


Ранг: 577.9 (!)
Статус: Модератор
Research & Development

Создано: 23 октября 2018 17:00 New!
Цитата · Личное сообщение · #1

Собираем в этой теме инфу по UEFI руткитам и трюкам.

Начало серии постов ntldr о руткитах:
--> Link <--

LoJax - руткит

Статья на русском:
- LoJax: первый известный UEFI руткит, используемый во вредоносной кампании

Документ на английском:
- ESET-LoJax.pdf

| Сообщение посчитали полезным: yashechka, WildGoblin


Ранг: 364.2 (мудрец)
Статус: Участник

Создано: 15 декабря 2018 15:45 · Поправил: ntldr New!
Цитата · Личное сообщение · #2

Основной источник информации о UEFI - исходники EDK и коммерческих биосов. Основной источник информации о компонентах винды - дизассемблер IDA.

Как будет время, я постараюсь изложить в этом топике свои представления о нескольких разных подходах к созданию UEFI руткитов. Достоинства, недостатки и некоторые проблемные места. В частности есть способы прыгнуть из EFI модуля сразу в ядро ОС уже после его загрузки. Без дрочива с патчем бутлоадеров. Есть и вообще тупой вариант как взять и запихнуть в биос любой первый попавшийся троян (привет разработчикам Computrace, чтоб им всем икалось!).

Добавлено спустя 5 часов 4 минуты
Сразу оговорюсь: нижеизложенное в этом и последующий постах не является руководством по написанию вредоносных программ. Это теоретические рассуждения на основе открытых данных. Описанные подходы также применимы в разработке инструментов для реверсинга и информационной безопасности.
Будет несколько постов, рассмотрим разработку кода под legacy BIOS, затем как устроены классические буткиты, потом отличия и особенности гипотетических зловредов под UEFI.

Начнём с вопроса написания программ под BIOS такого рода как загрузчики, резидентные коды (такие как обработчики дискового шифрования) ну и буткиты тоже. На чём и как писать?

Самое очевидное решение - писать на ассемблере под 16ти битный реалмод. Годится для Джедаев ассемблера, трудно совместимо со сколь-нибудь сложным функционалом. Пример такого кода - резидентный загрузчик от DiskCryptor 0.2.5b. Все нужные алгоритмы (в том числе криптография) пишутся базонезависимым ассемблерным кодом и компилятся сразу в бинарник для секторов MBR или в модуль legacy BIOS. Берёте каменный топор и вырубаете все вручную. Ещё можно откопать на кладбище древний MS Visual C++ 1.5 и писать на каком-никаком но всё-же си. Более современных инструментов разработки - нет и не будет.

Если всё-же хочется писать с комфортом на нормальном языке, использовать возможности современных компиляторов и иметь возможность применять готовые куски кода - нужно собирать под 32х битный x86 любым удобным компилятором а затем конвертировать PE модуль в бинарник простого формата, который в свою очередь загружается ассемблерным предзагрузчиком и работает в защищенном режиме. Ассемлерная часть небольшая, она обеспечивает простейший интерфейс модуля с внейшней средой. В случае DiskCryptor - это функции для вызова реалмодовых функций с передачей и возвратом контекста, а так-же интерфейс для обратного вызова. 32х битный код может вызывать 16ти битные прерывания BIOS и может обрабатывать хуки 16ти битных прерываний в 32х битном режиме. Поверх этого весь функционал пишется на современном си, без заморочек. Текущую версию загрузчика DiskCryptor, проект под VS2015 и инструменты для сборки (конвертор PEшников в бинарник и fasm для ассемблерной части) так-же выкладываю здесь.

Исходники к посту:
dcrypt_0.2.5b_boot-src.zip
dcrypt_new_boot.zip

| Сообщение посчитали полезным: sefkrd, Jupiter, plutos, WildGoblin, superakira, dosprog



Ранг: 401.4 (мудрец)
Статус: Участник
_Вечный_Студент_

Создано: 16 декабря 2018 09:58 New!
Цитата · Личное сообщение · #3

superakira пишет:
там на немецком


Там много и на английском (диаграммы, listings, etc.).
А остальной текст легко переводится google translate. Фразы короткие и ясные.
главное - терпение...


Ранг: 401.4 (мудрец)
Статус: Участник
_Вечный_Студент_

Создано: 20 декабря 2018 08:02 · Поправил: plutos New!
Цитата · Личное сообщение · #4

ntldr пишет:
Текущую версию загрузчика DiskCryptor, проект под VS2015 и инструменты для сборки (конвертор PEшников в бинарник и fasm для ассемблерной части) так-же выкладываю здесь.


Пожалуйста, опишите подробно, (если можно, то пошагово) процесс сборки. А то открываю solution (dcrypt.sln), а там половины проэктов не хватает. Что-то я явно делаю не так...

Ранг: 5.8 (гость)
Статус: Участник

Создано: 21 декабря 2018 14:56 New!
Цитата · Личное сообщение · #5

ntldr не забывай про тред плиз. запили пост про рк в таком ключе.

Ранг: 35.3 (посетитель)
Статус: Участник

Создано: 21 декабря 2018 16:04 New!
Цитата · Личное сообщение · #6

Microsoft обещает в ближайшем будущем выпустить open source код стандартизироваванного UEFI загрузчика, чтобы не было такого, что один вендор в лес, а другой по дрова

Ранг: 54.7 (постоянный)
Статус: Участник

Создано: 21 декабря 2018 23:11 New!
Цитата · Личное сообщение · #7

Не загрузчика, а самой фирмвари. Основана на стандартном edk2 но с удалением разных устарелых и небезопасных фич. А выпустили уже давно, это просто некоторые только сейчас заметили.

https://microsoft.github.io/mu/
https://github.com/Microsoft/mu

| Сообщение посчитали полезным: SegFault, ntldr, plutos


Ранг: 364.2 (мудрец)
Статус: Участник

Создано: 22 декабря 2018 20:09 · Поправил: ntldr New!
Цитата · Личное сообщение · #8

Теперь рассмотрим "классический" буткит.

Этим термином называют разновидность загрузочной малвари, которая не изменяет файловую систему на диске, а проникает внутрь ОС манипуляциями в памяти. Буткит для BIOS должен перехватывать реалмодовые прерывания INT13 и INT15.

Через INT15 ОС получает карту памяти, буткит должен разместить свою резидентную часть в верхних килобайтах базовой памяти (это та которая 0-640кб). По адресу 0x0413 лежит WORD с числом свободных килобайт. Правим его и правим карту памяти возвращаемую INT15, так чтобы в карте памяти наш диапазон адресов был E820_RESERVED. На первый взгляд ничего не мешает включить A20 рейт и разместить резидент в верхней памяти, но я не советую (будет геморрой с настройкой MTRR регистров проца, чтобы включить кеш. И ещё есть всякие проблемные биосы...).

Через INT13 ОС читает сектора диска на стадиях загрузки до монтирования системного тома. А это немалый такой набор файлов: все загрузчики, ядро, все boot start драйвера, файлы реестра BCD и SYSTEM. Всё это пролетает сквозь обработчик INT13, который ищет в потоке данных знакомые бинарные сигнатуры и патчит их на ходу. В минимальном варианте (теоретический буткит для Windows XP) ищем устойчивый участок кода ядра который вызывается после всей инициализации, вставляем туда маленький шелкод код и физический адрес блока памяти где сохранёны оригинальные байты ядра и лежит контент следующей стадии. Задача шеллкода - сделать MmMapIoSpace этого блока памяти и прыгнуть в него, в нём лежит большой шеллкод который первым делом восстанавливает байтики ядра из сохранёнки, затем разворачивает в памяти несуществующий на диске драйвер и вызывает его DriverEntry по завершению которой передается управление на начало восстановленной функции. Итог алгоритма - в ядре появился новый модуль могущий делать почти всё то-же самое что обычные драйвера. На этом заканчивается загрузочная часть, дальше идёт обычный драйверный руткит.

Более сложной будет логика буткита с поддержкой Windows 7+. Там чтобы изменить ядро, нужно сначала пропатчить bootmgr и winload.exe убрав проверку цифровой подписи файлов. bootmgr к тому-же упакован алгоритмом LZNT1 в старых версиях и MPRESS в новых. Искать сигнатуры первого нужно уже в памяти. Удобный момент для этого - первый вызов INT15 который означает что bootmgr распаковался и пытается получить карту памяти. Сканируем нижние 500кб физических адресов, он где-то там. winload и всё что после него - можно патчить в обработчике INT13 во время чтения с диска. Дополнительный бонус: на ранней стадии загрузки легко отключается защита patch guard. Патчгуард сложно вырвать с корнями когда он уже работает, но можно не допустить его инициализации имитировав загрузку под отладчиком (символы KdDebuggerNotPresent и KdPitchDebugger в секции .data ядра). Дальше пей-гуляй как в старые времена, делай хоть SSDT хуки хоть сплайсинг хоть перехват sysenter, винда всё стерпит. Помимо этого в x86 можно убрать проверку адресов обработчиков исключений на присутствие внутри модуля. Чтобы работали исключения на x64 - нужно добавить ExceptionTable виртуального модуля в PsInvertedFunctionTable ядра.

Исходники к посту: signoff.7z (Патчер для отключения проверки подписи драйверов. Умеет перепаковывать bootmgr всех версий.)

Добавлено спустя 7 минут
Наконец: UEFI руткиты и буткиты.

UEFI буткит представляет собой EFI модуль, т.е. почти обычный PE файл. Он может быть как встроен в BIOS (предпочтительно на стадию DXE), так и загружаться с загрузочного раздела, из сети (по протоколу PXE), c CD диска, флешки, итд. Задача EFI буткита аналогичная предыдущей - внедрить свой модуль в ядро, манипулируя только памятью.

Чисто теоретически могу предложить три разных способа как пробраться из EFI модуля в ОС.

Первый способ: перехватываем протокол EFI_BLOCK_IO_PROTOCOL_GUID для загрузочного раздела. Правим читаемые с диска байтики аналогично классическому буткиту. Подробно расписывать не буду, приложу код UEFI загрузчика DiskCryptor, там всё есть. ИМХО: тупо и нудно.

Второй способ: последовательно патчить файлы bootmgfw.efi, winload.efi, ntoskrnl.exe. Переименовываем bootmgfw.efi и подменяем его своим файлом (либо изменяем порядок загрузки в переменных NVRAM). Наш загрузчик загружает оригинальный bootmgfw через BootServices->LoadImage и получает полный PE файл в памяти. Полный образ можно обрабатывать не только банальными сигнатурами байтиков, но и продвинутыми алгоритмами (поиск внутренних символов опираясь на релоки, на ссылки код-данные и частичное дизасcемблирование). Нас интересуют функции ImgpValidateImageHash и ImgpLoadPEImage. Достаточно найти ImgpValidateImageHash и поставить хук (который всегда возвращает rax = 0), в нём смотрим адрес возврата и находим участок ImgpLoadPEImage где вызывается функция BlEnNotifyEvent. Подменяем адрес call'а BlEnNotifyEvent на свой обработчик, парсим стек на предмет указателя на PE образ (в этот момент файл полностью загружен, релоки обработаны, можно патчить). Получаем полный PE образ следующего загрузчика (которым должен быть winload.efi). Повторяем трюк с ImgpValidateImageHash / ImgpLoadPEImage, иерархия функций у winload полностью аналогичная. Похукав winload мы будем получать PE образы ядра и всех boot start драйверов по мере их загрузки. Можно менять всё что угодно. Код, данные, точки входа. Патчить ядро в этом варианте не обязательно.

Модификация второго способа для EFI модуля встраиваемого в BIOS: на DXE стадии загрузки подписываемся на событие EFI_EVENT_SIGNAL_READY_TO_BOOT. В обработчике события перехватываем BootServices->LoadImage. В обработчике LoadImage детектим загрузку bootmgfw и производим вышеназванные манипуляции. Всё.

Ключевое преимущество этого способа - доступ к полным PE модулям целиком, а не по частям. Это простор для эвристических алгоритмов поиска нужных частей кода. К примеру в теле функции ImgpValidateImageHash есть ссылки вида mov edx, offset a1_3_6_1_4_1__0 ; "1.3.6.1.4.1.311.61.4.1, mov edx, offset a1_3_6_1_4_1__2 ; "1.3.6.1.4.1.311.61.5.1", сама собой напрашивается эвристика "ищем mov r32, offset, на offset'е мова стоит релок, offset указывает в секцию .rdata, по адресу offset читается строка 1.3.6.1.4.1.311.61.4.1". Нашли инструкции по эвристике, сканируем вниз до retn 14h (удостовериться что совпадает число параметров), сканируем вверх до пролога функции. Такие эвристики покрывают сразу много версий системных файлов и с большой вероятностью будут работать со следующими версиями.

Третий способ: спецификация UEFI поддерживает runtime сервисы, это функции EFI модулей которые может вызывать ОС уже после загрузки. Рантайм сервисы, их EFI модули и связанная с ними память остаются жить после ExitBootServices. Windows 8+ поддерживает эти фичи и вызывает EFI_RUNTIME_SERVICES->GetVariable, EFI_RUNTIME_SERVICES->SetVariable. Поймав такой вызов и пройдя по адресу возврата мы попадём в кодовую секцию hal. От этой отправной точки - дело техники распарсить структуры и добраться до API ядра. Применяем набор стандартных приёмов написания шелкода, как для local root эксплоитов.

Преимущество этого способа - можно прыгнуть из BIOS сразу в ядро, не нужно дрочиться с сигнатурами. Недостаток - не работает в Windows 7, нельзя пропатчить инициализацию ядра (PatchGuard и иже с ним).

Исходники к посту: DC_UEFI_CURRENT.7z. Исходники, бинарники, отладочные символы.

Добавлено спустя 9 минут
PS: извиняюсь за путанное описание. Задавайте уточняющие вопросы.

Добавлено спустя 54 минуты
Универсальный способ запихнуть произвольное говно в BIOS или загрузчик:

Дано: примитив для HDD block IO позволяющий читать/писать на блочные устройства. К примеру в legacy BIOS загрузчике DiskCryprtor есть такой набор функций:

Code:
  1. uint32_t dc_find_hdds();
  2. bool hdd_io(uint8_t hdd_n, void* buff, uint16_t sectors, uint64_t start, bool read);


Работает с жесткими дисками и USB накопителями. Доступ идёт на уровне диска.

В UEFI есть EFI_BLOCK_IO_PROTOCOL со сладкими функами:

Code:
  1. typedef
  2. EFI_STATUS
  3. (EFIAPI *EFI_BLOCK_READ)(
  4.   IN EFI_BLOCK_IO_PROTOCOL *This,
  5.   IN UINT32                 MediaId,
  6.   IN EFI_LBA                Lba,
  7.   IN UINTN                  BufferSize,
  8.   OUT VOID                 *Buffer
  9. );
  10.  
  11. typedef
  12. EFI_STATUS
  13. (EFIAPI *EFI_BLOCK_WRITE)(
  14.   IN EFI_BLOCK_IO_PROTOCOL *This,
  15.   IN UINT32                 MediaId,
  16.   IN EFI_LBA                Lba,
  17.   IN UINTN                  BufferSize,
  18.   IN VOID                  *Buffer
  19. );


UEFI в добавок ещё и парсит таблицы разделов. Доступ возможен как на уровне диска, так и на уровне раздела.

Прикручиваем сверху скотчем: парсер таблиц разделов (для BIOS), драйвер файловой системы NTFS (спиздить из ntfs-3g) и код для чтения/записи виндовых файлов реестра (где-то валялся. должен быть в паблике).

Ну а теперь ищем разделы с виндой и вкрячиваем туда какого угодно говнеца. Мешает антивирус - удаляем антивирус. Просто-напросто модифицируем файлы на системном разделе до загрузки винды.
Этот способ заражения BIOS давно и успешно используется трояном Computrace. Именно про него идёт речь в первом посте топика LoJax: первый известный UEFI руткит, используемый во вредоносной кампании. LoJax - это он и есть.

По моему мнению, такого рода поделие не может считаться буткитом или руткитом. Аналогично можно вбросить вредоносные файлы в Linux / MacOS и куда угодно ещё.

Защита по уму: SecureBoot работающий с самого бутблока биос, на основе TPM чипа. Выставление безопасного порядка загрузки в BIOS. Удаление лишней херни из прошивки биос чипа. Впрочем, зловред загружаемый с внешнего носителя может быть подписан ключом вендора. Прописывайте в BIOS свои ключи и переподписывайте загрузчики вручную.

Защита из говна и палок: зашифровать диски. Хотя-бы с паролем qwerty. Троян отрабатывает до старта бутлоадера и не может влезть на зашифрованный раздел.

| Сообщение посчитали полезным: plutos, mak, superakira, FlatL1neAPT, morgot



Ранг: 632.9 (!)
Статус: Участник
CyberMonk

Создано: 23 декабря 2018 15:03 New!
Цитата · Личное сообщение · #9

ntldr

Уже тянет на статейку в пдф

| Сообщение посчитали полезным: plutos



Ранг: 401.4 (мудрец)
Статус: Участник
_Вечный_Студент_

Создано: 24 декабря 2018 04:56 New!
Цитата · Личное сообщение · #10

mak пишет:
Уже тянет на статейку в пдф


а то и на книгу постепенно наберется!

Ранг: 364.2 (мудрец)
Статус: Участник

Создано: 24 декабря 2018 06:48 · Поправил: ntldr New!
Цитата · Личное сообщение · #11

Лучшая документация по таким вещам - это код. Не представляю о чём тут можно книги писать.

Реверсить EFI загрузчики от винды - как нефиг делать, для них есть отладочные символы. Это не только имена функций в диасме, но ещё и прототипы всех структур данных. Также символы есть для всех ядер.

Можно не изобретать уникальный велосипед для поиска внутренних функций, а тупо выкачать PDB'шники для всех существующих в природе файлов, распарсить их и составить таблицу с оффсетами всего нужного, либо сгенерировать базу бинарных сигнатур. Эта задача автоматизируется, нужна лишь полная коллекция файлов. Некрасивое, но простое и стабильное решение. Помнится, такой приём применялся в отладчике SoftIce.

С legacy bios загрузчиком чуть сложнее. К внутреннему PE файлу из bootmgr есть символы для старых версий, нет для новых. Но структура кода сохраняется, подсматривая дизасм старого загрузчика ищется аналогичный код в новом.

Ранг: 5.8 (гость)
Статус: Участник

Создано: 24 декабря 2018 13:10 New!
Цитата · Личное сообщение · #12

ntldr как это все отлаживать? если биос, то вроде на борще это отлаживали. сейчас с едк2 идет от интела на базе qemu отладочный стенд - ты на нем отлаживал, если говорить про рк? те я к чему - я не такой клевый, чтоб с 1 раза что-то закодить норм)

Ранг: 364.2 (мудрец)
Статус: Участник

Создано: 24 декабря 2018 14:58 · Поправил: ntldr New!
Цитата · Личное сообщение · #13

Именно отладчиком я пользовался всего пару раз, для отладки кода под legacy BIOS через BOCHS. К QEMU можно прикрутить биос OVMF.fd, оно запускается и на первый взгляд работает, но винда у меня на нём не загружалась.

VMWare последних версий поддеживает UEFI, причём как 32 так и 64 битные версии. Винда загружается, всё в целом работает. VMWare умеет писать лог-файл для виртуального COM порта.

Главный инструмент отладки - вывод отладочной информации в COM порт. На реальном железе - отлаживаем через RS232 кросс-кабель к другому компу. Хочешь посмотреть какие-нибудь внутренние структуры - пишешь код снимающий дамп. Свой код в части алгоритмов - можно отлаживать на винде, а затем переносить в EFI.

Если же хочешь ковырнуть что-то что происходит на реальном железе в ранних стадиях загрузки - модифицируешь UEFI капсулу (добавляешь новый модуль или заменяешь чужие модули пропатченными) и шьешь флеш чип SPI программатором. Советую покупать материнку с флешкой в DIP корпусе на панельке. Иначе придётся выпаивать SMD чип и приделывать болтающийся на проводах переходник для быстрой замены микросхем. Менять прошивки придётся часто. Будет не лишним купить несколько запасных микросхем SPI Flash.

Для отладки чужих модулей PEI стадии — отладочный код внедряется в нужный модуль. Инструмент для этого у меня написан на скорую руку, пока не выкладываю.


Ранг: 401.4 (мудрец)
Статус: Участник
_Вечный_Студент_

Создано: 25 декабря 2018 02:00 · Поправил: plutos New!
Цитата · Личное сообщение · #14

ntldr пишет:
Не представляю о чём тут можно книги писать


Тебе с твоим уровнем, многое кажется само собой разумеющимся и понятным, а мне например, порой непонятно с какой стороны подойти, так что писать есть о чем: о деталях, о мелких подробностях, причем желательно с наглядными примерами.
Ведь недаром говорят англичане: Devil is in the details.

и вот еще "до кучи", может кому будет интересно:
--> VeraCrypt <--is a free open source disk encryption software for Windows, Mac OSX and Linux.
С полным source code, среди которого EFI Bootloader for EFI Windows system encryption (LGPL).


Ранг: 401.4 (мудрец)
Статус: Участник
_Вечный_Студент_

Создано: 27 декабря 2018 08:05 · Поправил: plutos New!
Цитата · Личное сообщение · #15

для тех, кто страдает бессоницей и хочет основательно разобраться с данной темой:

LATEST VERSIONS OF THE UEFI SPECIFICATIONS

--> UEFI specification<--

--> ACPI Specification<--

Ранг: 39.1 (посетитель)
Статус: Участник

Создано: 27 декабря 2018 09:35 New!
Цитата · Личное сообщение · #16

plutos пишет:
--> UEFI specification<--

Вообще-то уже 2.7 версия, а ссылка на 2.4 (2013)
и там достаточно много изменений!


Ранг: 401.4 (мудрец)
Статус: Участник
_Вечный_Студент_

Создано: 27 декабря 2018 11:12 · Поправил: plutos New!
Цитата · Личное сообщение · #17

DrVB_5_6 пишет:
а ссылка на 2.4 (2013)


прошу прощения, не ту ссылку вставил. Поправил. (Version 2.7 Errata A August 2017)

Ранг: 44.8 (посетитель)
Статус: Участник

Создано: 29 декабря 2018 12:10 New!
Цитата · Личное сообщение · #18

ntldr пишет:
ничего не мешает включить A20 рейт

A20 устарело и не поддерживается

Добавлено спустя 2 минуты
ntldr пишет:
есть устройства достпные только на PEI стадии загрузки (после чего они выключаются установкой бита в регистре и пропадают из PCI Config space, обратно включить нельзя)

Это вполне стандартная фича PCH, хотя не полностью описанная в манах


Ранг: 43.1 (посетитель)
Статус: Участник

Создано: 2 января 2019 08:12 New!
Цитата · Личное сообщение · #19

https://media.ccc.de/v/35c3-9561-first_sednit_uefi_rootkit_unveiled
<< . 1 . 2 .
 eXeL@B —› Крэки, обсуждения —› UEFI руткиты

Оригинальный DVD-ROM: eXeL@B DVD !

Вы находитесь на форуме сайта EXELAB.RU
Проект ReactOS