BlackLotus UEFI bootkit. Часть 2

Приветствую вас, дорогие читатели! Сегодня мы продолжим изучать BlackLotus UEFI bootkit. В прошлой части мы рассмотрели темы:

В предыдущей части мы выполнили следующие шаги:

1.     Подготовка тестового стенда.

2.     Запуск CVE-2022–21894 (baton drop).

В этой части мы сосредоточимся на следующих шагах:

3.     Добавление сертификата в базу данных MOK.

4.     Компиляция payload и компонентов для его выполнения.

5.     Чтение и запись файлов в операционной системе Windows10 из файловой системы NTFS через grub.elf.

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

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

Использование информации осуществляется на ваш страх и риск.

Рассмотрим подробнее, зачем нам это нужно. Поскольку grub.elf компилируется вручную, он не имеет валидной цифровой подписи. В такой ситуации Secure Boot не позволит его запустить, блокируя выполнение неподтверждённого или неподписанного кода. Чтобы обойти это ограничение, мы должны подписать grub.elf и добавить подпись в MOK (Machine Owner Key), который управляет доверенными ключами системы. Это обеспечит корректный запуск на устройстве с включённым Secure Boot.

MOK — часть механизма Secure Boot, который защищает систему от загрузки поддельного или вредоносного кода на этапе инициализации. Для работы с MOK используется утилита MokManager, доступная в репозитории rhboot/shim на GitHub.

Чтобы автоматизировать процесс добавления подписи в MOK, мы планируем использовать уязвимость CVE-2022–21894. Это позволит обойти защитные ограничения и запустить payload, встроенный в grub.elf. Благодаря этому мы получим доступ к функциям чтения и записи в файлы на NTFS.

3. Добавление сертификата в базу данных MOK.

MOK (Machine Owner Key) — это сертификаты, которые добавляются пользователем для настройки доверенных ключей, используемых системой UEFI Secure Boot. В UEFI Secure Boot используется несколько ключевых переменных db, dbx и MokList, хранящихся в NVRAM, для обеспечения безопасности загрузки. NVRAM (Non-Volatile Random Access Memory) — это тип памяти, которая сохраняет данные даже после отключения питания. В контексте UEFI, NVRAM — это область памяти на материнской плате, куда записываются настройки и переменные UEFI, которые нужны для работы системы. Эти переменные сохраняются после перезагрузки или выключения компьютера.

— db (database)— основная база доверенных сертификатов. Это переменная, в которой хранятся доверенные сертификаты и хеши. Эти сертификаты используются для проверки подписи каждого компонента (загрузчика, драйвера и т. д.) при загрузке системы. Если сертификат или хеш компонента присутствует в `db`, то этот компонент считается доверенным, и его загрузка разрешена. Обычно в `db` хранятся ключи, подписанные производителями оборудования или операционных систем, такими как Microsoft. Это позволяет Secure Boot доверять стандартным загрузчикам операционных систем, драйверам и обновлениям.

— dbx (forbidden signatures database) — список заблокированных сертификатов. Это переменная, в которой хранятся сертификаты и хеши компонентов, загрузка которых запрещена. Этот список также называют списком заблокированных сертификатов. Если сертификат или хеш компонента присутствует в `dbx`, то его загрузка блокируется, даже если он есть в `db` или `MokList`. Это позволяет отклонять известные уязвимые или устаревшие компоненты. Производители ОС (например, Microsoft) периодически обновляют `dbx`, чтобы добавлять в него ключи устаревших или уязвимых загрузчиков и драйверов, предотвращая их загрузку.

— MokList — дополняет переменные `db` и `dbx` и создаёт более гибкую систему управления загрузочными компонентами. `MokList` (Machine Owner Key List) используется для хранения дополнительных сертификатов, которые пользователь или администратор системы добавил вручную. Пользователь может добавить свои сертификаты, например, с помощью утилиты `mokutil` в Linux, а затем подтвердить изменения через MOK Manager (rhboot/shim) при перезагрузке операционной системы.

Мы напишем свой код (кодовая база взята из проекта rhboot/shim), который будет добавлять нашу подпись в MokList. Этот код мы запустим с помощью CVE-2022–21894.

Начнем с подготовки среды для компиляции кода, среду будем подготавливать в виртуальной машине Windows 10×64-BatonDrop созданной в первой части статьи:

  • Установим nasm https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/, после установки nasm, необходимо прописать nasm в переменную Path= C:\Users\user\AppData\Local\bin\NASM и добавить переменную NASM_PREFIX= C:\Users\user\AppData\Local\bin\NASM\

    8eaf59ddbe86abcfda9286bc4702327d.png

    Переходим в папку C:\VisualUefi\EDK-II и запускаем проект EDK-II с помощью visual studio 2017

    210e82769e6fbfd179e17201c8a28a3a.png

    Компилируем проект EDK-II

    81d82c552d49dc4850115bf507e7b664.png

    Скачиваем проект MyMOKManager с github (https://github.com/roman5888/BlackLotus-UEFI/tree/main/samples/MyMOKManager), кладем его в папку C:\VisualUefi\samples\, запускаем проект MyMOKManager в Visual Studio и компилируем его

    0d391699b151c39a00022013815821cf.png

    Копируем MyMOKManager.efi и кладем рядом с разделом EFI. Это необходим для проверки корректности работы MyMOKManager.efi, чтобы убедиться, что он запускается и выполняет свои функции без ошибок.

    5218869bf928e0d6e64483c7b16de15b.png

    Выключаем виртуальную машину Windows 10×64-BatonDrop

    791dc0d3cff46ccd0b10bdda197da306.png

    Замечание: чтобы запустить UEFI Shell необходимо отключить Secure Boot у виртуальной машины.

    be06274bb1c9e70bf73b17e956af0b9f.png

    Перейдем в UEFI Shell:

    2f9689e03b973f6a3321a09573323cc9.png

    И запустим MyMOKManager.efi для проверки работоспособности:

    92f6b415e039a747cb3a2e35a6f1af68.png

    4. Компиляция компонентов для запуска MyMOKManager.efi.

После того как мы научились добавлять свой сертификат в MokList. Нам необходимо запустить MyMOKManager.efi из контекста загрузочной среды UEFI, для этого воспользуемся CVE-2022–21894, которая состоит из двух частей.

  • Вторая часть CVE-2022–21894- это приложение, которое переключается в контекст прошивки (FiremareContext), что позволяет запустить MyMOKManager.efi. Скачиваем проект stage2 с github (https://github.com/roman5888/BlackLotus-UEFI/tree/main/samples/stage2), кладем его в папку C:\VisualUefi\samples\. Кодовая база для проекта stage2 взята из https://github.com/Wack0/batondrop_armv7/blob/master/src/stage2.c

Открываем MyMOKManager.efi в HxD (https://mh-nexus.de/en/hxd/)

be0ec0c28d77942130b3e3393b11c91f.png

Выделяем полностью байт код ctrl+A и копируем

39ec2f8aa48e01173e81dbb49e3c973d.png

Теперь открываем проект stage2 в VisualUefi и копируем байт код в массив PayloadBase из HxD и удаляем ненужный участок кода

7b2e98f010e4bb4a64c6977d9f829f82.png

Дальше компилируем stage2.

326f7c131d404571f11c5c236dd1b1ec.png

  • Первая часть CVE-2022–21894 — это mcupdate…dll, которая работает в контексте приложения (AplicatinContext) и запускает stage2. Скачиваем проект mcupdate с github (https://github.com/roman5888/BlackLotus-UEFI/tree/main/samples/mcupdate), кладем его в папку C:\VisualUefi\samples\.
    Кодовая база взята из проекта https://github.com/ASkyeye/CVE-2022–21894-Payload/blob/master/main.c

    Открываем stage2.dll в HxD

    011a4332a30416ff252eece492d80005.png

    Выделяем полностью байт код ctrl+A и копируем

    e766f23238f451cd8def24630d798960.png

    Теперь открываем проект mcupdate в VisualUefi и копируем байт код в массив efiApp из HxD и удаляем ненужный участок кода

    862a114314036e0ee698ea063e8f5534.png

    Дальше компилируем mcupdate.

    a9b5674df45b619affc689ba525ec4c6.png

    И копируем mcupdate.dll на флешку в папку EFI.

    cb7070f2f3ee1581c6999c76af9e4e98.png

5. Чтение и запись файлов в операционной системе Windows10 из файловой системы NTFS через grub.elf.

В этой части мы начнем с установки Ubuntu, чтобы извлечь из нее ключевые модули, обеспечивающие загрузку операционной системы, включая shim и связанные компоненты. Затем внесем собственный код в grub. После этого скомпилируем обновленный grubx64.efi и подпишем его для дальнейшего использования. В конце мы соберем все компоненты вместе и перезапишем файл в Windows 10.

Cкачаем Ubuntu с https://archive.org/details/ubuntu-18-and-20

c688447279e228050479983329921435.png

Прежде чем приступить к установке Ubuntu 20.04.2, необходимо установить Windows 10. Это связано с тем, что Windows 10 понадобится для проверки корректной работы системы. Кроме того, установка Windows позволяет активировать функцию Secure Boot, которая в случае установки только Ubuntu 20.04.2 остаётся недоступной для включения, так как соответствующая опция не актива.

cdbefee3d70662a12bbd968d4344be23.png

Создадим виртуальную машину Windows 10×64 (2) с Windows 10

914cfb89da115b2f0ff26c6689438c03.png

Включим secure boot в настройках виртуальной машины Windows 10×64 (2)

d8da68a0a65bc1f81c518807db2f4a97.png

Дождемся установки Windows 10 и выключим виртуальную машину Windows 10×64 (2)

840408c8d398f819d67474340d8acd56.png

Замечание: Так как Ubuntu 20.04.2 скачен не с официального сайта, будьте с ним осторожным.

Для установки Ubuntu 20.04.2 на виртуальную машину с Windows 10×64 (2) потребуется выбрать соответствующий ISO-образ операционной системы и подключить его к виртуальному дисководу.

f6b712bf40becbcada9533235378ec24.png

Создадим жесткий диск, на который установим Ubuntu 20.04.2

76053f1cf88a3cec757ffe59b94fa95c.png

Отключаем интернет на виртуальной машине Windows 10×64 (2). Это необходимо сделать, чтобы избежать обновления Ubuntu 20.04.2, которое приведёт к установке корректной версии shim.

d05ec72e64e66a2502a000ac8f5a2842.png

Теперь запускаем виртуальную машину Windows 10×64 (2)

bf9ad651ca95364ca81a66a569f5accf.png

В grub выбираем установку

f5b45cc51998fd3e4ba9c37cfcdd74ce.png

Дальше мы устанавливаем Ubuntu 20.04.2 и просто жмем далее…

2b8aee4b17cb68dcdda9ebbaf819afa8.png6796af3e9875c306d3940ad40373008f.pngb988e8a3d65e155c5eaf20a79a909e43.pngf8162cd68a36b4e69324258695698587.png0781ff9592fb7bcf25e2b166dc18ce72.png25883f2e9d027de5ef65e1befc47b8d5.png7dceccaa53cb80882c01f057df363250.png11c0cfe6b36263f58f2aaad6a5c6f584.png3618a6cfb819ff52407ddc3efa7f9037.png5f287885c944f09df5b31fbb5989ac1e.png

Выключаем виртуальную машину Windows 10×64 (2)

b938a29e9bb0c2b63a9c75992164ef01.png

Включим интернет на виртуальной машине Windows 10×64 (2)

d0e49dec42bb5fb78dcbe314cd954a49.png

Включаем виртуальную машину Windows 10×64 (2) и выбираем Ubuntu 20.04.2

0cf99d82a3b4a3f1c6ef2c62022b34a7.png

После того как мы установили Ubuntu 20.04.2 нам необходимо скопировать папку EFI на usb флешку, мы вернемся к этой папке позже.

4e13242717d0d4fa7aa20e620eb0b7c2.png

После завершения установки Ubuntu и успешного извлечения shim вместе со всеми необходимыми компонентами, следующим шагом станет загрузка GRUB (GitHub — a1ive/grub: Fork of GRUB 2 to add various features.).
wget https://github.com/a1ive/grub/archive/refs/heads/master.zip

f61be698a27f47d9e270e7ef7f81ed86.png

unzip master.zip

307806f54b9d414afe8c2ec9cfed74fa.png

cd grub-master

a133c445a6c4a0a070c919da8a83edd5.png

Далее мы полностью заменим код в файле grub-core/commands/cat.c на наш собственный, этот код работет с файловой системой NTFS. Исходный код можно найти и загрузить из репозитория на GitHub (https://github.com/roman5888/BlackLotus-UEFI/blob/main/cat.c).

a07efccfb5181b35de219787779297da.png

Дальше скомпилируем grub и для этого проделаем следующие шаги

apt-get update

7e674742fb45a39162fb6ea5e2446837.png

apt-get install gcc make autoconf automake bison flex libdevmapper-dev libzfslinux-dev liblzma-dev binutils gettext unifont xz-utils libfreetype-dev libfreetype6-dev autopoint libtool-bin libtool pkg-config git

81ee30ad0740c8da118282741e5fb4b0.png

./bootstrap

86ca844829b3bf99d2f80903f0e3a35d.png

./configure --target=x86_64  --with-platform=efi

95403f956950290b627555b9333fa074.png

make

31d7fc9ca4a6ddc3826c417b154817ac.png

make install

bce5076b4e6f87b4ea3698c274985ceb.png

cd grub-core

c239948feb324819f380e29875954ccc.png

…/grub-mkimage -O x86_64-efi -p »(hd0, gpt1)/EFI/ubuntu» -o grubx64.efi part_gpt probe part_msdos linux16 ntfs ntfscomp hfsplus fat exfat xzio ext2 normal chain boot configfile linux efi_uga loopback gfxterm videoinfo ls file efi_gop all_video video video_fb loadenv help reboot raid6rec raid5rec mdraid1x mdraid09 lvm diskfilter zfsinfo zfscrypt gcry_rijndael gcry_sha1 zfs true test sleep search search_fs_uuid search_fs_file search_label png password_pbkdf2 gcry_sha512 pbkdf2 part_apple minicmd memdisk lsacpi lssal lsefisystab lsefimmap lsefi disk keystatus jpeg iso9660 halt gfxterm_background gfxmenu trig bitmap_scale video_colors bitmap font fshelp efifwsetup echo terminal gettext efinet net priority_queue datetime bufio cat btrfs gzio lzopio crypto acpi extcmd mmap ntfs

Зачечание: »(hd0, gpt1)/EFI/ubuntu» — это путь где лежит grub.cfg файл.

8faf217c77eb7552d7fac35f27d17c80.png

Теперь необходимо подписать grubx64.elf, для этого выполним следующие команды

Создаем конфигурационный файл openssl.cnf

6180de7310adca68c1ba3c86f602c745.png

openssl req -config ./openssl.cnf -new -x509 -newkey rsa:2048 -nodes -days 3650 -outform DER -keyout MOK.key -out MOK.der

4bd6f2668a03aef9cf22adbd0ab59472.png

openssl x509 -in MOK.der -inform DER -outform PEM -out MOK.pem       

3df4bb894825da9a69eac6aec7e01e11.png

sbsign --key MOK.key --cert MOK.pem grubx64.efi --output grubx64.efi.signed

d24cfafb54d8fd2ae9adf192f36fde3b.png

Теперь проверим, что подпись и файл grubx64.efi работают, для этого сделаем snapshot виртуальной машины Windows 10×64 (2).

0d4e1d0d26c964e61ab276c04aee89e9.png

После snapshot«a скопируем grubx64.efi.signed в /boot/etf/ETF/ubuntu/grubx64.efi

ca07aaf7cac7230780d8ad0e800f6ced.png

Добавим MOK.der в MokList

27e754ff797ce2a0e695ab9615571654.png

Выключим и включим виртуальную машину Windows 10×64 (2), при включении выберем ubuntu

714b150309e84193beabb20dbf56b2cd.png

Диалоговое окно Shim UEFI key management показывает, что необходимо подтвердить сертификата MOK.der, пароль мы задавали с помощью утилиты mokutil

12792ff879397a058aa210adf79d320d.png

Замечание: Если не подтвердить или что то не так с сертификатом MOK.der, появиться ошибка

02171c3392852b9b182ff904499d0be4.png

И после перезагрузки видим, что запускается grub 2.11

9bf3510fce0a596a562bd82f942b09ad.png

Теперь вернемся к snapshot good

aecb6d79c9e8934c31d1facdb5bee1b3.png

И скопируем grubx64.efi.signed grubx64.efi MOK.der MOK.pem MOK.key на usb флешку

cf3beba86e90a2054b7dfc1bd12985cb.png

В заключении нам необходимо собрать все компоненты вместе и запустить poc

Запускаем виртуальную машину Windows 10×64-BatonDrop, созданную в первой части статьи, чтобы продолжить работу в подготовленной среде. Однако, на всякий случай, повторим все необходимые шаги.

Начнём с примонтировать «Системного раздела EFI».

Add-PartitionAccessPath -DiskNumber 0 -PartitionNumber 1 -AccessPath 'E:'

89fb12f3ea29eb5cab3fffa8a006d575.png

Создадим копию оригинального файла BCD и назовём её BCDR.

98da9f787d43a6014432c2e2d10a28e2.png

Импортируем bcd файл из poc_amd64_19041.iso с помощью bcdedit.exe.

f060e5c0ea634ded71c5e443028b5ca7.png

Копируем файлы из poc_amd64_19041.iso (https://github.com/Wack0/CVE-2022–21894/blob/main/pocs/poc_amd64_19041.iso) в системный раздел. (Total Commander нужно запускать с правами администратора).

a724220afc25542bcb62de4e269b9289.png

Копируем с флешки файл F:\EFI\ mcupdate.dll в E:\system32\mcupdate_GenuineIntel.dll и копируем с флешки файл F:\EFI\ mcupdate.dll в E:\system32\mcupdate_AuthenticAMD.dll

e833c45ee5f51662e2175ebf4e905ff6.png

Копируем с флешки папку F:\EFI\ubuntu в E:\EFI\ubuntu

4a181fb99b6a81ea58aa295016a0c9c2.png

Копируем с флешки файл F:\EFI\grubx64.efi.signed в E:\EFI\ubuntu\grubx64.efi

a28f5de2cc87c4ab47c0c8df9565d297.png

Копируем в E:\EFI\ubuntu\grub.cfg следующий код

menuentry 'Windows 10' {
	insmod part_gpt
	insmod fat
	insmod cat
	cat
	probe --set devuuid --fs-uuid (hd0,gpt1)
	search --fs-uuid --set=root $devuuid
	
	chainloader /EFI/Microsoft/Boot/bootmgfw.efi
	clear
} 

5fb4fea0bbd4defa41d41e0eb935deab.png

Копируем с флешки файл F:\EFI\Boot\fbx64.efi в E:\EFI\Boot\fbx64.efi

c9042e85967a7a104575318b4d97265e.png

Создадим папку certs в E:\EFI и скопируем с флешки файл F:\EFI\MOK.der в E:\EFI\certs\MOK.der

e51a971089dcd7b2d3b70aa935b523a0.png

Создадим файл test.txt на рабочем столе, этот файл будет изменен с помощью добавленного нами кода в grubx64.efi

b05ee09c3e6e1ba94f5fbfd4ec907de4.png

Выключаем виртуальную машину Windows 10×64-BatonDrop

aef2f7e13c720cfb136e3920f227f47f.png

Проверим что «Virtualize Intel VT-x/EPT or AMD-V/RVI» и «Enable secure boot» включены

94ccff378e93a5d31c8ee62efed80184.png

Включаем виртуальную машину Windows 10×64-BatonDrop

d9b5348b125724ca96ee809d2f802cc8.png

Мы наблюдаем срабатывание уязвимости CVE-2022–21894 (baton drop).

c609db177456ed6ed673d0f926aa534e.png

Перезапускаем виртуальную машину Windows 10×64-BatonDrop, после чего перед нами появляется загрузочное меню GRUB 2.11. В этом меню выбираем Windows 10 для продолжения работы.

493df9c513d0bce00f8b2b8b442942f5.png

После выбора Windows 10 в GRUB, загрузчик выполняет код, который активирует систему и инициализирует необходимые процессы. В рамках этого процесса выполнено действие по перезаписи файла test.txt, расположенного на рабочем столе пользователя в C:\Users\user\Desktop\

9283c4e36156177e23874c5ca146a604.png

В заключение, после выполнения всех операций и завершения процесса загрузки, мы можем обнаружить, что файл test.txt, находившийся на рабочем столе пользователя по пути C:\Users\user\Desktop\, был успешно перезаписан. Этот файл теперь содержит обновлённые данные, отражающие результаты завершённой операции, произошедших в ходе работы системы.

Такое завершение процесса подчеркивает итоговую трансформацию данных, а сам файл test.txt становится наглядным подтверждением выполненной задачи по изменению файла.

08bf71ab55adcf6af0b5e7a793ec02a5.png

© Habrahabr.ru