Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
BlackLotus-analysis-stage2-bootkit-rootkit-stage — Z2A-BlackLotus Challenge: анализ bootkit-rootkit, этап 2 | Kitploit
Инструменты/GitHubGitHub/spiralbl0ck/blacklotus-analysis-stage2-bootkit-rootkit-stage
Статический анализДинамический анализ (песочница)Обратная инженерияОтладчикиАнализ вредоносных программАнализ Бинарных ФайловОбучение и ОбразованиеАнализ Прошивок
GitHub
spiralbl0ck/blacklotus-analysis-stage2-bootkit-rootkit-stage

BlackLotus-analysis-stage2-bootkit-rootkit-stage

Z2A-BlackLotus Challenge: анализ bootkit-rootkit, этап 2

Репозиторий
17543 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

BlackLotus-analysis-stage2-bootkit-rootkit-stage

Анализ bootkit-rootkit второй стадии BlackLotus

Прежде чем мы окунёмся в эту божественную хрень (поверьте, это действительно божественная хрень, так как никто не может сделать это без Воли Бога (по крайней мере, таково моё мнение)) ,вот хэш файла буткита

1

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

1
2
``` C:\Windows\system32>BCDEdit

Windows Boot Manager

identifier {bootmgr} device partition=\Device\HarddiskVolume9 path \EFI\MICROSOFT\BOOT\BOOTMGFW.EFI description Windows Boot Manager locale en-US inherit {globalsettings} default {current} resumeobject {3f80ecd0-df10-11ed-bafc-80a84b2564bb} displayorder {current} toolsdisplayorder {memdiag} timeout 30

``` So how do we set up a breakpoint in order to debug the bootkit? Well that's we we compiled the ovmf image as debug rather than release. If you specifically start qemu with that command you'll have qemu run and debug messages will be logged in a file called debug.log , which looks like this ```

Windows Boot Loader

identifier {current} device partition=C: path \Windows\system32\winload.efi description Windows 10 locale en-US inherit {bootloadersettings} recoverysequence {3f80ecd2-df10-11ed-bafc-80a84b2564bb} displaymessageoverride Recovery recoveryenabled Yes isolatedcontext Yes allowedinmemorysettings 0x15000075 osdevice partition=C: systemroot \Windows resumeobject {3f80ecd0-df10-11ed-bafc-80a84b2564bb} nx OptIn bootmenupolicy Standard

root@kitploit:~
Теперь, что касается моего анализа: мне так и не удалось заразить свою машину, поэтому я воспользуюсь примером из уже упомянутого поста в блоге азиатского исследователя, где показано, как должна выглядеть заражённая машина.```
    // Windows Boot Manager
    // --------------------
    // identifier              {9dea862c-5cdd-4e70-acc1-f32b344d4795}
    // description             Windows Boot Manager
    // locale                  en-US
    // inherit                 {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
    // bootdebug               Yes
    // displayorder            {57e1b615-0355-11ec-abb0-005056c00008}
    // timeout                 30

    // Windows Boot Loader
    // -------------------
    // identifier              {57e1b615-0355-11ec-abb0-005056c00008}
    // device                  boot
    // path                    \system32\hvloader.efi
    // description             Hoy la disco se flota
    // locale                  en-US
    // inherit                 {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
    // truncatememory          0x10000000
    // avoidlowmemory          0x1000
    // nointegritychecks       Yes
    // testsigning             Yes
    // isolatedcontext         Yes
    // osdevice                boot
    // systemroot              \
    // ems                     Yes

=============================================================================

=============================================================================

Прежде чем мы начнём, как вообще настроить окружение для анализа EFI-модуля? Что ж, спасибо @MaverickMusic__ , в ходе обсуждения с ним он передал мне это( https://zhuanlan-zhihu-com.translate.goog/p/343293521?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-GB ). Я не полностью следовал шагам оттуда, так что вот что именно я сделал, чтобы поднять окружение:

-Во-первых, я установил edk2(https://github.com/tianocore/tianocore.github.io/wiki/Windows-systems)

-Во-вторых, я настроил свой ovmf в режиме debug, а не release(это поможет нам позже). Вот команда build -a X64 -t VS2019 -b DEBUG -p OvmfPkg/OvmfPkgX64.dsc

-В-третьих, мне нужно было настроить windbg. Как, чёрт возьми, я это сделал? Я скачал всё по этой ссылке(git clone https://github.com/microsoft/WinDbg-Samples). Затем я скомпилировал ExdiGdbSrv.sln. Затем я следовал всему из этой ссылки(https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/setting-up-qemu-kernel-mode-debugging-using-exdi), от того места, где было сказано Use regsvr32 to register the DLL in an Administrator command prompt. до PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files". Понимаю, это запутанно, но, пожалуйста, подождите терпеливо, я обязательно сделаю видео, где объясню каждый шаг! Круто, теперь, когда у нас есть настроенное окружение для отладки, как, чёрт возьми, мы отлаживаем код? Итак, запускаем qemu, в моём случае я сделал это, выполнив qemu-system-x86_64.exe -L . -bios OVMF.fd -hdd dos.img -debugcon file:debug.log -global isa-debugcon.iobase=0x402 . Как только я выполнил команду qemu, я сразу перешёл и выбрал compat_monitor0 в меню view в qemu. Когда вы это сделаете, это должно выглядеть так.

Также после выбора этого вам нужно ввести gdbserver, чтобы запустить удалённый экземпляр отладки gdb, к которому мы подключимся с помощью windbg, используя эту команду .\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64. Круто, как только мы подключимся, это будет выглядеть так

1
1

Так, теперь разберёмся с этим выводом. В нашем случае единственная значимая строка — EntryPoint=0x000062C9A8C, это что-то вроде предпочтительного адреса загрузки при запуске буткита. Для данного буткита он варьируется между 0x62C4A8C or 0x62C9A8C. Теперь можно переопределить базу программы в IDA и заниматься обычной работой :) . Наслаждайтесь остальной частью блога!

=============================================================================

Сравниваем через BinDiff оригинальный winload.efi с тем, который оставляет BlackLotus

1
2
3
4

Мы видим некоторые сходства, но также и расхождения, но ничего полезного, в общем-то....

=============================================================================

Круто, так что давайте начнём эту вечеринку.

1
1

Отлично, давайте препарировать. Сначала мы видим, что есть функция, которая вызывается. И что насчёт неё? Ну

1
2

Круто, ещё одна функция. Не совсем... Замечаете что-то знакомое?

1
2
3

4

5

Всё ещё ничего???

Нет проблем, может, теперь

1
2

Та же функция деманглинга! Привет, старый друг :)))

Круто, но что насчёт return (*(a1 + 88))(v2, &unk_62CEABC, 3i64); ?? Честно говоря, не знаю, что сказать, только лишь с точки зрения статического анализа, так что попробуем использовать отладчик, чтобы разобраться :))

Итак, после деманглинга строки получаем

1

Итак, дальше, когда мы добираемся до инструкции вызова

1

и мы не получаем никакой информации.... отлично, но почему? Потому что у нас нет .pdb-файла, чтобы получить отладочные символы.... Круто, по крайней мере IDA здесь помогает. Итак, мы знаем, что «большая» функция принимает на вход SystemTable->RuntimeServices, который имеет тип EFI_SYSTEM_TABLE. Если изучить его, это A pointer to the EFI Runtime Services Table. . Если поискать в гугле, мы наткнёмся на кучу документов, но один ключевой документ — https://uefi.org/sites/default/files/resources/UEFI\_Spec\_2\_1\_D.pdf . Там говорится

1

Круто, значит структура с кучей указателей, да, но давайте приблизим ещё.

Итак, сначала он деманглит VbsPolicyDisable. Если поискать в гугле, мы наткнёмся на анализ ESET, который утверждает: that this variable is evaluated by the Windows OS loader during boot and if defined, the core VBS features, such as HVCI and Credential Guard will not be initialized. , то есть по сути эта переменная отвечает за текущую «безопасность» на уровне загрузки. Круто, дальше у нас есть функция, которая принимает эту переменную и

1

и так мы можем прийти к выводу, что это должна быть функция, которая каким-то образом меняет состояние этой переменной. Круто, какие возможные функции могут это делать? В EFI_SYSTEM_TABLE есть только одна такая функция — EFI_SET_VARIABLE SetVariable;

Итак, мы приходим к выводу, что эта функция просто берёт VbsPolicyDisable и устанавливает её в``` db 77h ; w .data:0000000180005034 db 59h ; Y .data:0000000180005035 db 3 .data:0000000180005036 db 32h ; 2 .data:0000000180005037 db 4Dh ; M .data:0000000180005038 db 0BDh ; ½ .data:0000000180005039 db 60h ; ` .data:000000018000503A db 28h ; ( .data:000000018000503B db 0F4h ; ô .data:000000018000503C db 0E7h ; ç .data:000000018000503D db 8Fh .data:000000018000503E db 78h ; x .data:000000018000503F db 4Bh ; K.

root@kitploit:~
Теперь, есть ли что-то важное в этих байтах? Ну да, если вам довелось прочитать первую часть анализа blacklotus, вы знаете, что я ссылался на работу азиатского исследователя. Этот исследователь был так любезен, что также проанализировал дропнутый буткит. Пожалуйста, ознакомьтесь с этим (https://www.cnblogs.com/DirWang/p/17294545.html#autoid-3-2-1) — в своём анализе он был так добр, что предоставил нам эту информацию. Он указывает нам на https://github.com/Mattiwatti/EfiGuard/blob/master/EfiGuardDxe/PatchWinload.c. Там мы видим похожую строку

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/33c755aa460f5bdc338c75f3f5e1322c731123299d59c43dcdf2be3b72d1276c.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/144b057568871a60a32e477ed1ae7e8d7090778a67b7fc24222f0f58fe44afc1.png" alt=""><figcaption></figcaption></figure>

</div>

Есть ли для этого конкретная причина? Честно говоря, я не знаю — это мой первый раз, когда я анализирую буткит. Пожалуйста, дайте мне знать или сделайте pr/pull request, чтобы отредактировать этот документ, если у вас больше опыта, чем у меня :) в этой области

\=============================================================================

Круто, дальше удача на нашей стороне: псевдокод из IDA похож на ассемблер

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/7457c9d8beb807556618728c7aba102109a472ef2f990f35ec344038fafc4cd5.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/e11c4b4e4260f7a91e6dc08bcabb7c3ac420dcee346b1bf9dff02835342f7837.png" alt=""><figcaption></figcaption></figure>

</div>

Итак, я предполагаю, что здесь происходит обычная инициализация EFI\_SYSTEM\_TABLE, которая, по сути, определяет, какой процесс продолжит процесс загрузки. А затем у нас есть вызов функции PatchBootManager

\=============================================================================

PatchBootManager

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/66c49bf5b64655af7e0edfe384ad715912c02fbeea1ac1313e4f65479ab58f80.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7a1dc3ac7c01cbd4cfd9b3ec614c357895210e4f03ae5d58000e6b047f84eb96.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/3fc22a51052c24c9e436ace83a1672ce88bf25fb11103b32d0143fa0ab4d7216.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/22c7869b067f26c6469e4baffcd4226535c47e82d4baaf7fa8e27820915b1580.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/38cf7697523141faa68a59b52abd2a1ca14d0d9053f1e6960052a5093e3a94bb.png" alt="3">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/505a3fd02b96bcb823bf108ee03a8a1204827852260c1e8ce3902638237259b3.png" alt=""><figcaption></figcaption></figure>

</div>

И из псевдокода

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/9c8482f0faa4d4de5f8643acc4276ebbbfc57386e9b00a4057793b5c67b1bf3b.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c44de61b9f089fd8972bcc8567110bc2d58c21e5465a7b4f14fc7beaefee30a3.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/6809c28e881b3626d73a476cd31631891539f6a7b71cf276619f9cd2244d83e9.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c8cd4870cd0488e57cde3448ba01fdd44063f266516d8530731f42e6ccc5be78.png" alt=""><figcaption></figcaption></figure>

</div>

Итак, первый вызов функции, который мы видим, — это HandleProtocol. Так что же делает этот код? К счастью, мы наткнулись на это при быстром поиске в Google (https://tianocore-docs.github.io/edk2-ModuleWriteGuide/draft/5\_uefi\_drivers/54\_communication\_between\_uefi\_drivers.html) и видим, что он `извлекает протоколы`. Круто, но в этом нет ничего, что я мог бы осмыслить. Да, я понял, братан. По сути, это извлекает методы коммуникационной информации, используемые другими UEFI-драйверами. Круто, копаем дальше. Мы видим, что второй параметр — это

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/703c3f52bd8c3d10eaf046fc801cbc60ca7a62e9162d67a6ba63caf4c9e9038d.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/9d41aacaed9c15391beb8b1b62739572bf7f873508938ade770610eec371a17c.png" alt=""><figcaption></figcaption></figure>

</div>

Если мы поищем эти конкретные байты, мы наткнёмся на это

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/f4a8ed3b81486c8481c0f8894175f9d7390ddf62f9974ba025aad9827dea119e.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/882b5116cfd08886c3dac510443fb77c9aa31781eb234208ec81fdf313544c29.png" alt=""><figcaption></figcaption></figure>

</div>

итак, какого чёрта делает EFI\_LOADED\_IMAGE\_PROTOCOL\_GUID? Цитируя (https://uefi.org/specs/UEFI/2.10/09\_Protocols\_EFI\_Loaded\_Image.html) `Может использоваться с любым дескриптором образа для получения информации о загруженном образе.`, какого типа информация? \`\`\`Этот раздел определяет EFI\_LOADED\_IMAGE\_PROTOCOL и EFI\_LOADED\_IMAGE\_DEVICE\_PATH\_PROTOCOL. Соответственно, эти протоколы описывают образ, который был загружен в память, и указывают путь устройства, использованный при загрузке PE/COFF-образа через EFI Boot Service LoadImage(). Эти описания включают источник, из которого был загружен образ, текущее местоположение образа в памяти, тип памяти, выделенной для образа, и параметры, переданные образу при его вызове.\`\`\`\`

Итак, в нашем случае он получает информацию о бутките. Теперь есть проблема: мы не можем реально проверить результат функции, потому что у нас нет отладочных символов :/ но мы можем предположить. И я склонен предполагать, что структура (результат предыдущего вызова функции) будет в rbx.

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b8f744ecd9fd4be572a1e2d191b06231559eca2b32aeaa981a399eec7f3ee710.png" alt=""><figcaption></figcaption></figure>

Далее мы вызываем деманглинг строки

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1fdc75d2dc9221250e6d46692770ad5240f7a0d6cda9cc5634749b327fc8c146.png" alt=""><figcaption></figcaption></figure>

что даёт нам

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e073b265ff13675b755ec8413554bec74ab4eae57dd002b25694632eb43cbc8e.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3654bb54071386cd020c43ed4a35fae40aec386897a0ca26a27b58b8e1a91c95.png" alt=""><figcaption></figcaption></figure>

</div>

а затем мы вызываем

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/c433aa63cddd2ecfb5ce0fd57a6774ad35b1c1ed4ee71e7cecb566cc861d2b80.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6834be566cdd81f2410ec7d4ee97936d14a27017a723371eea3046b8590609f4.png" alt=""><figcaption></figcaption></figure>

</div>

\=============================================================================

sub\_180002B14

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/483f2b789c0fa6fe9378ba324f8e349bc72cbb45e540bbc2355ef55acaf1b6b4.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d84d79115facbc0f9ff7afe06d70a18555e7d94bc196f6f9d0ff6b5cfd40408a.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/19e2366fddab99fa3aa4375b8306475ee31d3bf9a3c3737efeeb4d627868404e.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6c808c76821c756eca776cf6290482f6f9829167f539bf31b2ad82b3de0af829.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/ad0d06238e39e4ba1decb2f1305510a8375822b13ae9148d91e267d14762eb3b.png" alt="3">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/0e45e9ae64c3fbd8a61ffdf60ec2e532529d8cab6cfc7786fa2c91824233d347.png" alt=""><figcaption></figcaption></figure>

</div>

и псевдокод

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/c14b1eacbe8eef4155c4148b66fa95f93bbd9e6fc81e5ca80f1ddc5b2b9a7a16.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b7c452865661d95b79886a48a455eba663c2e3915e0a81ad16dc7ddd8c2c0189.png" alt=""><figcaption></figcaption></figure>

</div>

Круто, до if'а всё понятно само собой, а что насчёт if'а? Мы снова видим вызов с unk\_180005010 в качестве параметров, который снова является массивом байтов; при ближайшем рассмотрении это выглядит так

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c3bb66f35a4e559ae793ba590fc0c342bdde1e1c9765e144cb450a809009655d.png" alt=""><figcaption></figcaption></figure>

Теперь, если мы снова проверим первые байты и быстро поищем, мы наткнёмся на это (https://github.com/theopolis/uefi-firmware-parser/blob/master/uefi\_firmware/guids/efiguids\_ami.py), точнее, на это `'EFI_DEVICE_PATH_PROTOCOL_GUID': [0x09576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b]` .

Если мы снова зайдём на страницу спецификации UEFI, мы увидим, что `Может использоваться с любым дескриптором устройства для получения общей информации о пути/местоположении физического или логического устройства.`. Круто, мы также видим ещё вот это: `Путь устройства описывает местоположение устройства, для которого предназначен дескриптор`. Ок, круто, и если мы прокрутим чуть дальше, мы увидим функцию под названием \_EFI\_DEVICE\_PATH\_PROTOCOL. Ок, подводя итог, мы знаем, что это связано с EFI\_DEVICE\_PATH\_PROTOCOL\_GUID, но наша функция имеет тип EFI\_BOOT\_SERVICES. Так есть ли какая-либо функция в EFI\_BOOT\_SERVICES, которая могла бы делать что-то вроде обработки протокола? Да, есть. Если мы посмотрим раздел 4.4 в https://www.intel.com/content/dam/doc/product-specification/efi-v1-10-specification.pdf, мы увидим

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/918a0a5184849cbb87454df44c5ffa5e5fa586f223213287f6c7fbe737a0fbc8.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/fab94604327fe596d9eeb68368efcf0afc721ef7bfcdc07a8977392b4309238c.png" alt=""><figcaption></figcaption></figure>

</div>

точнее, в нём есть функция, которая нам знакома (HandleProtocol). Круто

Далее мы видим ещё один вызов функции, на этот раз неизвестной нам. Давайте посмотрим, какие аргументы она принимает: она принимает 2, затем длину переданной строки в юникоде и указатель на переменную

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/39e0d1d9baabff8d95da7109294db94f9fc4409a6ede34d37ece9662fb73651d.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/e116e90f20a09d48f21a981e7d24c49f7474ea9ac6007b6fa41973300af4e83d.png" alt=""><figcaption></figcaption></figure>

</div>

Теперь, если мы проверим это в отладчике

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/f412c3bf83f60da9213f4c29b39350c925a0aa6411c42de52d7fa4530c5bc3fe.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/5285bf4d5e52dbbef857e46e8738c3ba6e7f6cda87f9b67a4965b23cc70aba0e.png" alt=""><figcaption></figcaption></figure>

</div>

мы видим странную вещь: rcx содержит отладочную строку AllocatePool, которая появляется после вызова функции, поэтому мы делаем вывод, что это, возможно, был вызов AllocatePool; забавно, но если вы также заглянете в спецификации, вы увидите, что boot\_services также содержит указатель на AllocatePool, что только усиливает наше предположение.

Итак, если нам удастся выделить достаточно места (проверка >= 0 нужна, чтобы убедиться, что нам удалось выделить память, потому что если EFI\_OUT\_OF\_RESOURCES реализован как

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/bf08cd5dd33ad9ca16ff4e6a44a4cbfd51cd1f8b0300d9b6b44984c4306fcb6e.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c28af9995294473937be13a6094de90cb57a688c83727617ca9f667c2705d7cd.png" alt=""><figcaption></figcaption></figure>

</div>

остаётся только предположить, что

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/3741ef8be2dc989f601d26568907381f1847d29c0bf514add76485b0f0fef4b6.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/cdfc6ccb296659fc8156d4bfba6d777da8b2792e4af56677d0f0d57695932216.png" alt=""><figcaption></figcaption></figure>

</div>

используется для обозначения успешного выделения)

Один интересный факт: буфер после выделения не заполнен нулями, а содержит вот эти байты. Если кто-то знает больше об этом, пожалуйста, сделайте pr request, чтобы отредактировать этот документ

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e4b15da615e07faa4965d864435bf4deec0e01270f9d1ac1134fb5b20ad46892.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b229a700b321040fc8978f4f0f489a058381795c128d27dbcfbcfff5f9ffd3b2.png" alt=""><figcaption></figcaption></figure>

</div>

Ну да, в любом случае мы вызываем memcpy; после вызова наш буфер выглядит так

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/28e61d8725687245e9a9dae7e467929ac15d5a81e33178262f0ce886a3c4555c.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/f161ab0441b14d71dbade9fc3acebbd12b1453de5d53b77b09af98c0cf0ac6d6.png" alt=""><figcaption></figcaption></figure>

</div>

Затем мы добавляем несколько байтов, чтобы буфер выглядел так

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/80906384a49ef1d6eaea9667cb962459c27feb8e9deac857491a248be5443a4f.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7c703952c72c154d156603c457a00013305c48519ddee808925c32a62499135f.png" alt=""><figcaption></figcaption></figure>

</div>

А затем вызываем функцию FileDevicePath\_call, которая выглядит примерно так&#x20;

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/66c77ae12715ee6d982ba2cfb769ba6a650f52ce56d7bae54e3bd93686695f02.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/5f7e06800ec3eecb9559d1592b8a76868038c0cbb64744e5c928b65d189ef183.png" alt=""><figcaption></figcaption></figure>

И преобразуется в это

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/2b36492bb7dd46a7139c27de61371b59adac5bfbec989bbb542b58d34ce7982d.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/361e2b338c676b99393f7baa48e970ba886894f579065a4468fe113841c0783b.png" alt=""><figcaption></figcaption></figure>

</div>

Круто, но это не имеет смысла, если не объяснить... Итак...

Во-первых, у нас есть собственная реализация strlen, которую мы не будем препарировать, потому что это бесполезно :) Но вот результат

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/03a0aabe9f7c87f42b7e64bb284d74738ecdc81134136cfec68c70084644c3ea.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/823c30bd0a6a8c1d750ef1dfb0bce5be67a13a96de12e53b3e46b2226a1c2be1.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/5dd4684c37f3129c8234cd69574bb6371b4bef72ff7e027199b7900134cdd101.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/118ee749874a6b08d40286821735190f67af45ca8d4573fc94aee3a2cea04af2.png" alt=""><figcaption></figcaption></figure>

</div>

32 символа из len(of(str)+"\x00", а последние 4 байта, добавленные перед вызовом функции, — 0x4FF7F

Далее мы вызываем то, что я также взял из исследовательского блога азиатского исследователя, — PxepDevicePathInstanceCount, что по сути является strlen, потому что он просто подсчитывает каждую букву и имеет счётчик. Как видно здесь

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/130931a6676f0519da2b50a9762955b7581e7102434e587236137b216cc62ead.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ce1a6ad93452a8092d2fb71ffd6418df78c32fc8cdf4fb99133924cc9037f12e.png" alt=""><figcaption></figcaption></figure>

</div>

Итак, мы видим pop rbx, и после вызова мы видим rbx=0x48

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4c2eabdd91ec40fc82c100e67579d729def9e74c6bfd000fff287bc9c10b0f38.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/818bb3c8398d4a53c0260d9310d4d192cfa5b65a404348df5516c94fa3d8dcaa.png" alt=""><figcaption></figcaption></figure>

</div>

затем мы снова вызываем strlen для той же строки; думаю, это просто потому, что на следующей строке, точнее, `v6 + v4 * v5;`, мы делаем v4\*v5, что, как я предполагаю, является каким-то способом представления юникод-строк

В любом случае, затем мы снова выделяем память, используя gEfiBootServices + 64, с которым мы уже сталкивались ранее и который, как выяснилось, является AllocatePool.

Здесь мы также видим кое-что интересное, а именно

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/26d19e06bd335f1267946a5da2542cf3eb9f2965fab788d0bcf720d7e3c08d37.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/225c92cbe9a5e72214cb279e61ad5fcbaef0a243db835b67fce5ff7ef74e7c86.png" alt=""><figcaption></figcaption></figure>

</div>

тот факт, что здесь блок памяти содержит паттерн afafafaf в нём.

Итак, что происходит дальше: после выполнения основного цикла мы получаем два буфера, которые выглядят так

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/35f257d96c752ac436e81778da5f37c28bfcb79fc5614f3ea8e099888cc011c3.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b9c706cc28161a6e7274c5cabc895bedc1279728b3ed7c11084cb6cb38dbf9e3.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/52477a3825650e47112a5e619a098c74e7e0de778ebfeda5682e5b49d48f3923.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/762a6dd3897f3b630ce1d0faa371e58ed9b2bce755bb8edd54f958aab7c3b69b.png" alt=""><figcaption></figcaption></figure>

</div>

И, честно говоря, нас интересует только первый, потому что именно он возвращается, так что мы можем сделать вывод, что это, как я предполагаю, просто копирует путь устройства и очищает буфер от мусора. :))

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

Прежде чем закончить с этой функцией, я хотел бы указать на ещё один интересный факт: вот так таблица служб загрузки выглядит в памяти :) согласно спецификациям, с тем же заголовком в начале; просто подумал, что может быть интересно оставить это здесь для тех, кто захочет заняться будущей работой и найдёт в дампе эту строку BOOTSERVF — это точно таблица служб загрузки

\=============================================================================

Итак, что же происходит дальше??? Ну, мы проверяем, удалось ли нам найти файл winload.efi, и загружаем его в память. Вот псевдокод :)

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/b59f211cb997e5ad783cbb6421833c23bea4ef4f7f21743577cd8aba4656ad2f.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/a96f7410f6bd6f7e207b76dff36a411f3c17a3f40dcb1a9433d5292b46f775e2.png" alt=""><figcaption></figcaption></figure>

</div>

А вот так это выглядит в памяти

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e3ee7b08fdc84433a08e60c7065c74692fb3a4e26eb81def063b662aa5229558.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/445d40332ba97516eebf129d17c56a38e28688858515d787ebf90a99580daa51.png" alt=""><figcaption></figcaption></figure>

</div>

что такое rax? rax — это дескриптор образа :) не будьте такими тупыми, как я, когда я сначала думал, что это область памяти :)

Круто, прежде чем мы углубимся дальше, позвольте мне быстро объяснить, что такое winload.efi. Итак, `с развитием компьютеров традиционная загрузка BIOS устарела, и началось противостояние в области безопасности вокруг загрузки UEFI. Из блок-схемы ниже мы видим, что MBR и VBR больше не существуют в UEFI, но сама UEFI отвечает за загрузку bootmgr, что также означает безопаснее и быстрее`

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/d2443977ce3d56790e424fd6236d1d0594db283caa9357ed4e6abb9b8b30b8ed.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1259e1f45b2d2bb8edcb12609e057d089f7c1dcf907677973d799049c58bee4a.png" alt=""><figcaption></figcaption></figure>

</div>

Итак, как загружается обычный Windows-ПК? После BDS работа кода прошивки UEFI, хранящегося в SPI, завершена, затем диспетчер загрузки прошивки UEFI сначала запрашивает переменную NVRAM UEFI, чтобы найти ESP, и находит специфичный для ОС диспетчер загрузки bootmgfw.efi, чтобы вызвать его функцию входа (DXE-драйвер).

Эта функция сначала вызовет функцию EfiInitCreateInputParametersEx, которая в основном используется для преобразования параметра EfiEntry в формат параметров, ожидаемый bootmgfw.efi.

Затем вызывается функция BmMain — точка входа Windows Boot Manager.

В этой функции вызывается BmFwInitializeBootDirectoryPath для инициализации пути загрузочного приложения (BootDirectory) (\EFI\Microsoft\Boot).

Затем BootMgr прочитает файл конфигурации загрузки системы (BCD); если есть несколько вариантов загрузки, он вызовет BmDisplayGetBootMenuStatus для отображения меню загрузки.

Затем он вызовет функцию BmpLaunchBootEntry для запуска приложения (winload.efi).

Конечно, bootmgfw.efi делает не только это, но также проверяет целостность кода политики загрузки и инициализирует компоненты безопасной загрузки, так что я не буду вдаваться в подробности.

На финальном этапе Windows Boot Manager (BootMgr) функция BmpLaunchBootEntry выберет правильную загрузочную запись в соответствии с предыдущим значением BCD. Если включено полное шифрование тома (BitLocker), сначала будет расшифрован системный раздел, а затем управление может быть передано winload.efi.

Далее вызывается функция BmTransferExecution, проверяются параметры запуска, и поток выполнения передаётся функции BlImgStartBootApplication.

Затем функция BlImgStartBootApplication вызовет функцию ImgFwStartBootApplication и, наконец, функцию ImgArchStartBootApplication. В ней будет инициализирован режим защиты памяти winload.efi, затем будет вызвана функция BlpArchTransferTo64BitApplication; BlpArchTransferTo64BitApplication вызывает функцию Archpx64TransferTo64BitApplicationAsm, которая в конечном счёте передаёт управление winload.efi.

Эта функция включит новые GDT и IDT, а затем полностью передаст управление winload.efi. На этом этапе BootMgr завершает свою миссию, и Winload начинает работу. — Конец цитат, украденных с китайского веб-сайта, на котором это обсуждается (пожалуйста, просмотрите его для получения дополнительной информации: https://bbs.kanxue.com/thread-268267.htm )И оттуда winload.efi выполняет свою работу, которая заключается в загрузке Windows и выполнении ещё некоторой работы с оборудованием, прежде чем передать управление ядру.

Теперь, после этого краткого брифинга, как мы и говорили,

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/65537ae888c278e8e487029f93d909fb1e4699069699cf1b7d5ad8fa1f9e0d69.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3b00c68a215f4568fca5d672ea6f892fecf9809e671c68795c067d2660fa3f1f.png" alt=""><figcaption></figcaption></figure>

</div>

далее мы проверяем, успешно ли оно загрузилось в память, и затем вызываем функцию ati\_analysis\_rdtsc\_aia\_cu\_4e1f, которая должна быть вам знакома, если вы уже читали первую часть этого анализа.

А теперь, ради интереса, давайте представим, что нам не удалось проанализировать эту функцию и мы были обнаружены. Посмотрим, как выглядит sub\_180002A08.

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4eb3ae379ab937e19e6a699339d992b2a5fd1fcb33202ca67355f62a5b1203b4.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/a4b252df16a31b5bf165d2a500ebe3c54ad5dad3c58cf9fe88a8a1da11ed6b63.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/dd594955a663274e25603804c348b516ca22755886b2732ef81dc8e1e0177544.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6fba01328584e8abb254912b81b048e8dcf80bda6d3eadc11573a52a5e84dd15.png" alt=""><figcaption></figcaption></figure>

</div>

мы снова видим gEfiSystemTable + 64, который на самом деле нам на этот раз не знаком, потому что он другого типа: это не bootservices, на этот раз это efisystemtable. Затем идут memcpy и ещё три вызова функций, которые нам неизвестны. Теперь, если мы запустим выполнение до начала цикла

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/20e0db7308860023b613310ea14e0880529a588540d9dabac2218b52dc93cefb.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b8f498165a4016c19d8d5797517680fc32dea241d343b38fcc613620270d58dd.png" alt=""><figcaption></figcaption></figure>

</div>

и если мы посмотрим на предыдущие параметры memcpy

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/21f546fbfb10a39e0e603186c8c505a3ae0679e8c7bad40f31643022f9ebfbcd.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/2ef8c97938b8f961abf92c03937ca15d5a48cd03eb58a0169891559fad27dde5.png" alt=""><figcaption></figcaption></figure>

</div>

и если мы посмотрим на вывод qemu, то увидим

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e4325617bfda31fb45f7920d0d1d977103fd6b85260e590fc7cfdca1efacb787.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/04e29142b4cf543a6e5b8f55de2c27d1f3f0034707a6d19e2b1ea45b8251e899.png" alt=""><figcaption></figcaption></figure>

</div>

Круто, так что давайте разберёмся во всём этом. Я снова обращусь к исследовательскому блогпосту Asian, потому что, честно говоря, я тут потерялся.

Итак, в своём блоге он говорит, что те две функции на самом деле были```
ConOut->ClearScreen(ConOut);
ConOut->OutputString(ConOut, String);

Ок, но что такое conOut? Ну, ещё он говорит, что conout имеет тип EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL и что conout получается через ConOut = gEfiSystemTable->ConOut;. Ок, и что это значит в коде??

Ок, давай копать глубже

определение

1

и GUID

2

Теперь мой умный зад забыл реально захватить это в отладчике, потому что, когда я впервые анализировал это, я перепутал типы данных между efisystemtable и bootservices и подумал, что это на самом деле allocatepool.

Итак, что делают эти функции?

Что ж, ClearScreen должен быть вполне понятен сам за себя, как и OutputString. Как исследователь мог прийти к выводу, что эта переменная имеет тип EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL? Ну, вероятно, он видел байты GUID в отладчике.

А что насчёт последней функции?

Ну, в своём посте в блоге он говорит, что последняя функция — это gEfiBootServices->Stall? Так что это, чёрт возьми, делает? Из спецификаций UEFI: Функция Stall() приостанавливает выполнение процессора как минимум на запрошенное количество микросекунд. На время приостановки процессор не переключается на другие задачи.

То есть по сути это заставляет наш процессор замереть. Круто, и насколько? 0x1C9C380 секунд. Охренеть как много, если спросите меня. Что опять же помещено в бесконечный цикл, так что да, мы попали :)))

И вот как это выглядит в отладчике

1

Теперь продолжаем с нашей главной функцией

1

если нам удастся загрузить bootmgfrw.efi (потому что winload.efi здесь — это настоящий загрузчик Windows), мы вызываем sub_180002538

============================================================================= sub_180002538

С точки зрения графа

1

С точки зрения ассемблера

2
3
4
5
6

Что-нибудь уже щёлкает? Нет? Ну, дайте этому минутку, дойдёт. А пока взгляните на псевдокод.

1
2

мы видим разбор exe :) Не знаю, насколько это будет похоже на то, что было в предыдущей части (части 1), но посмотрим :)

Итак, мы сравниваем нашу версию бинарника в памяти (bootmgfrw.efi) с классическим MZ-заголовком (0x5A4D), как вы можете видеть

1
1

ок, дальше делаем ещё одну классическую проверку — можем ли мы найти PE-заголовок

1

Круто, дальше мы вызываем sub_1800024C4(), которая выглядит так

1
2

Круто, здесь происходит следующее: мы находим определённые значения в памяти и, если находим их, возвращаем. Пожалуйста, обратитесь к sub_180002538.py.py для эмуляции.

В любом случае, вот sub_180002464

1

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

1

Итак, мы дополнительно сравниваем то, что находится по адресу rax+0xe, с 0x64. Хм, интересно. Смотрим, что в rax+0xe

1

Есть ли особая причина для этой конкретной проверки? Честно, не знаю. Может, и есть. Если знаете, пожалуйста, сделайте pull request и отредактируйте этот документ.

мы делаем ещё несколько сложений, а затем сравнение

1

Я хочу на минуту остановиться и снова сослаться на предыдущий источник вдохновения для этой статьи, когда я терялся. Так вот, в своём блоге он переименовал функцию, которая сравнивает значения, в RtlpImageDirectoryEntryToDataEx; если поискать, результатов нет, но есть нечто достаточно близкое к его именам — это RtlImageDirectoryEntryToData, которая в основном делает вот что: Функция RtlImageDirectoryEntryToData() возвращает виртуальный адрес и размер записи каталога, учитывая базовый адрес модуля ядра и индекс записи в каталоге данных(https://codemachine.com/articles/top\_ten\_kernel\_apis.html). В нашем случае, поскольку мы находимся в efi/uefi-приложении, мы можем считать, что 50, которое мы видим, — это размер в байтах/мб, не знаю, нашего корневого раздела, и что адрес в rax — это запись в нашем каталоге.

Прежде чем продолжить, нужно объяснить ещё одну интересную деталь. В своём исследовании он преобразует вывод RtlImageDirectoryEntryToData в вот эту структуру``` typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { union { struct { DWORD NameOffset : 31; DWORD NameIsString : 1; }; DWORD Name; WORD Id; }; union { DWORD OffsetToData; struct { DWORD OffsetToDirectory : 31; DWORD DataIsDirectory : 1; }; }; } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

root@kitploit:~
Итак, что за хрень с этой структурой?

ну, быстрый поиск по этой структуре приводит нас сюда(http://www.brokenthorn.com/Resources/OSDevPE.html), где сказано, что `Разбор ресурсов немного сложнее, чем у других типов каталогов. Как и в других разделах, существует базовая структура IMAGE_RESOURCE_DIRECTORY, которую можно получить из члена DataDirectory в optional header: бла-бла` и также что \`\`\`В этой структуре не так уж много интересных полей, кроме последних трёх.

Если вы работали с ресурсами Win32, вы знаете, что ресурсы могут идентифицироваться по ID или имени. Два члена этой структуры сообщают нам количество этих записей и общее количество записей (NumberOfNamedEntries + NumberOfIdEntries), что полезно для перебора всех записей. Как вы, вероятно, догадываетесь, записи находятся в массиве DirectoryEntries. DirectoryEntries состоит из массива структур IMAGE\_RESOURCE\_DIRECTORY\_ENTRY, которые имеют следующий формат:\`\`\`

так что в принципе это дерьмо используется внутри для разбора всякой всячины, и для нас это имеет смысл в контексте того, что мы работаем с каталогом, в котором есть ресурсы, круто.

Ещё, пожалуйста!

Итак, дальше

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/137d3d2aebf0db9501f550b09baddf01c3e50bf703ca8d13386a7185a567f19a.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/045c3a8a2bab306f516cdc7e9a59954e3c1ff16efe4189273c50f54b9e84f3e6.png" alt=""><figcaption></figcaption></figure>

</div>

что эта штука делает — в основном перебирает все ресурсы из каталога и проверяет, является ли каждый из них строковым типом

не буду врать, я не знаю, зачем он так делает, так что если я ошибаюсь — извините, если нет — ура!

дальше

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/a57c5815ee8b5498fed6d8dde92f48b9fc2bdfd2d4f4e231796ba96e5e28bea9.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/bd4513fdf1f8f165fc404b8462d6bc36644de4937e42d560d54f1a5f1c0e8799.png" alt=""><figcaption></figcaption></figure>

</div>

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

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/8f6655fb8117abf8a4d38b5173d51e4bc3ce67b86803c57cce36d47b73cd1e76.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ebdf5a9a749f2cb1b7a656be5f2d99419edfc9cd2a737e15c6845f2c008e3f11.png" alt=""><figcaption></figcaption></figure>

</div>

и затем мы повторяем тот же процесс, чтобы получить некоторые смещения

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/faa12c96d0b22e6128ef1cdf14110c31cc9ebca89325f28a07fc6a0a064daeba.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/216539eaf48a407a7f691d10cca06679a545471c3e54f25fedb31c38f0c61a66.png" alt=""><figcaption></figcaption></figure>

</div>

и повторяем тот же процесс, на этот раз проверяем тип VS\_VERSION\_INFO

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/ac2d2e82085f4ddbc3f5ae1ce35528dd8420924b0298c65db056d0837c3e4b6d.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/23788c642b82988c14654e9dac2afd2504cd22846be0487efce96cae4d6fe094.png" alt=""><figcaption></figcaption></figure>

</div>

так что за хрень такая VS\_VERSION\_INFO? ну, Microsoft(https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource) говорит, что `Определяет ресурс информации о версии`, например, я считаю, что это просто версия bootmgfrw.ef

и наконец, если мы нашли VS\_VERSION\_INFO, мы повторяем тот же алгоритм

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4f00ecf2c2c9b32b2d25fcbf3c62e9bb45679df1390a085371f5166a70d67933.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/facd25069491b5d7826500e4f2c04cafe213191075012ddb4c1fa9a8bc97c4c5.png" alt=""><figcaption></figcaption></figure>

</div>

на этот раз с изюминкой: мы возвращаем идентификатор сборки :) как видите

Итак, в качестве заключения, что здесь вообще произошло? Ну, судя по имени, которое использовал китайский исследователь(GetPeFileVersionInfo\_BuildNumber\_), можно заключить, что мы на самом деле получаем номер сборки загрузчика, как видно на первом изображении

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/b28007dda110fc31d53233931ff077ac42fc81146d803b91999069e204020a4d.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d19f1311c2ee242ced63da8334db384929ada3acae147009becc0dbf34d2b7fb.png" alt=""><figcaption></figcaption></figure>

</div>

где мы видим загруженный загрузчик в памяти

на втором изображении мы видим

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/2000f17c51ccc65267b46ac2c1d191bd033b3bc6e6b655973423dbbd8a1fc77e.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7c47fe45fe4b422618a400f2c26c28cd33fea9416f2b24086a2c852d08f1614b.png" alt=""><figcaption></figcaption></figure>

</div>

целое число в rcx, которое может быть либо номером сборки, либо версией PE-файла

и третье изображение

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/41729b1d4a4701480d64f058f421cd2ad8a8b9b871bf17675fd7b537cec3dd85.png" alt="3">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d2b17725eeb9af2336d725be9c556565fba221fd2a3517912c942f411f9ed33b.png" alt=""><figcaption></figcaption></figure>

</div>

что, как мы можем предположить, является номером сборки, поскольку ebx будет перемещён в rax :)

Итак, последнее замечание об этой функции: вау, потрясающая инженерия

=============================================================================

Теперь переходим к следующей задаче :) на основе вывода предыдущего этапа мы устанавливаем v10 либо в sub\_180001D80, либо в sub\_180001D48, как показано

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/33581031e03f29b5997d46b708c467bfd49ce58625e99381dd28c109cadae7d3.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6647119081cffb664dcca365392271398b2572ee04c24a0456141f33cbaaeecf.png" alt=""><figcaption></figcaption></figure>

</div>

и в нашем случае v10=sub\_180001D80

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/2af043a1449f6bf10e2925f06697438716976d24a1539a61ab42c4301c4a8435.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/0769d4dff6e1da51acaf9c5bac3a9a9b4b446aae9d7c593e7e54d865ec13c2ea.png" alt=""><figcaption></figcaption></figure>

</div>

=============================================================================

Затем мы делаем strcmp между нашим менеджером загрузки и этим массивом байтов

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/59164794afc69304133f0a4c008b9e4755671e8d57bd8dc4ea5a2b2e6ae54164.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/03b00f7c18ff7db73dfd5253f02d6966955e38732fa7d1cfb4840366c17355a1.png" alt=""><figcaption></figcaption></figure>

</div>

Я хочу остановиться здесь на короткое время: как вы могли догадаться, я заметил кое-что интересное в блоге китайского исследователя. Он назвал массив байтов SigImgArchStartBootApplication. Так что за хрень такая SigImgArchStartBootApplication, кому она принадлежит и какого чёрта этот массив называется именно так (migos). Если поискать в google(gulugulu) SigImgArchStartBootApplication, мы ничего не получим. Теперь, учитывая текущий контекст, мы используем менеджер загрузки Windows, давайте откроем его в IDA. Идём в C:\Windows\Boot\EFI, открываем бинарник в IDA и ищем SigImgArchStartBootApplication — ничего. Ищем ImgArchStartBootApplication — и нас встречает

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/1ad42d5236e8ca4da08688fe3d4c72e6b3de01fdce633a1bdaa870de421cdc40.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d6e211aa12b37dfba0244d48516a08703248484c070f8d7ffcf0a28f08e8a833.png" alt=""><figcaption></figcaption></figure>

</div>

Итак, ImgArchStartBootApplication .... что этот пёс делает...!? Ну... э-э... я позаимствую это у `@_xeroxz`(идите и подпишитесь на него, чёрт возьми, что вы делаете, если не следите за его работой....) так что по сути в одной статье он говорит, что `bootmgfw.ImgArchStartBootApplication между версиями Windows 2004-1709 вызывается для запуска winload.efi`, как мы также видим из его изображения(https://guidedhacking.com/threads/hyper-v-hacking-framework-works-on-every-version-of-windows-10-2004-1511-amd-intel.16251/)

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4967559cb05e49785841a2dc216e13fc0b94fe8be8f17d9bceaf1914722156ff.jpg" alt="1603213912596">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/4967559cb05e49785841a2dc216e13fc0b94fe8be8f17d9bceaf1914722156ff.jpg" alt=""><figcaption></figcaption></figure>

</div>

Если это было недостаточно ясно, в одной статье() мы видим, что `ImgArchStartBootApplication используется для перехвата момента, когда загрузчик ОС Windows (winload.efi) загружен в память, но ещё не выполнен`(https://rustrepo.com/repo/rusty-bootkit--uefi-bootkit-in-rust)

Круто, так какое отношение strcmp имеет к ImgArchStartBootApplication? Ну, давайте поближе посмотрим на IDA, и вскоре нам откроется ответ. Если мы поищем в коде загрузчика байты 41 b8 09, мы вскоре встретим виновника

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/91050c01f95eb88488cbc575c21af7f453228eeb13c665b94d415eecf5682a55.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7239d85f2dc9e220a2eab80f79b5db9705285a17c074f85958c041d122bfaf8e.png" alt=""><figcaption></figcaption></figure>

</div>

И в случае совпадения байтов нашего загруженного в память образа загрузчика с сигнатурой байтов мы выполняем sub\_180002398

И, конечно, как видно, мы нашли паттерн; в eax нам вернулась область памяти, где находятся байты, и мы благополучно переходим к выполнению sub\_180002398

=============================================================================

sub\_180002398

"Ассемблерный взгляд"

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/5aa624d92161499019e7ce6597bf46853c59ba89d37fec483a8ac7ee168ddbeb.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/afbf940a1eb535d73dce744606cc63c568c2b447c9cf85034c422a8e900859f4.png" alt=""><figcaption></figcaption></figure>

</div>

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6468513a220946bbccfab53328c056a620755e1fe94ad3e36d8c8958ed777794.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c5c36e7c29f1cdea6f42d55d7605ad3c2044d66397c867c221da6c0bf74f8d6a.png" alt=""><figcaption></figcaption></figure>

"Взгляд со стороны псевдокода"

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/5b1d8a264dad55f34a0cc958a2f4a26014a31987af5b66754e754589ea085097.png" alt="3">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1d3db7165e0f71a3fa76862ba8afb3869f821f59db6fc5a5c5e99d5002ecfba1.png" alt=""><figcaption></figcaption></figure>

</div>

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ae65504884fa2881cb50af2f88e846a0ad029c9431ee6296b28993de8f2e4a0d.png" alt=""><figcaption></figcaption></figure>

Итак, что делает этот пёс? Честно говоря, он выполняет какие-то вычисления, сложения и вычитания, и ничего действительно важного? Почему? Потому что это не так интересно. Нас интересует то, что происходит после возврата из функции. Мы видим rax

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/4eae862955421b2b1629c120bb09970714cf085e9255590d6cfa36a77bbc69e9.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/43917bf46096449ad92172baa282fd3e70ec0bec67fec2bbf2a276285d878b52.png" alt=""><figcaption></figcaption></figure>

</div>

окей, круто, но я всё равно не понимаю. Ну, rax = 0x5eec108, что указывает на 0x48c48b48. Ок, и что? Ну, я был так же сбит с толку, как и вы, поэтому снова вернулся к китайскому блогу. Итак, что описывает этот исследователь, происходит вот что: мы возвращаемся к началу функции ImgArchStartBootApplication. Но как, чёрт возьми, он до этого додумался? Ну, как уже упоминалось, rax =\
0x48c48b48, и если мы проверим booloadermnfr.efi, мы увидим

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/2dbe283fa0b0dd9cf837e79f1f42eaeb6dcd61252e76979c0a4af3cf2f68e8d8.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/624e1927cac5a0011d6fabea0f2ce4740b8dfd14102509656d6e5c0395a9c08d.png" alt=""><figcaption></figcaption></figure>

</div>

что является точно такой же последовательностью байтов в 0x5eec108. окей, теперь это круто :)

Пожалуйста, обратитесь к sub\_180002398.py, чтобы увидеть мою неудачную попытку эмулировать это поведение :)

=============================================================================

Круто, дальше?

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/432ad1832fa35743bc5676f7f8362ad9e2043e17387121136a1f6dfe1bdf16f1.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/aab798c5c80621b1c367ea6eecfff0d7caf9ecc368ae2fe2e947538e4f0e2b0c.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/f04ebd9c650ddadb5553e4f2c43c72af8a5ccbef372a4dbdc811600e9583b0c9.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3411e1620450739ea98f6db634346748487377106547324591b148cefe358df2.png" alt=""><figcaption></figcaption></figure>

</div>

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

Затем мы вызываем то, что я назвал patch\_something, и выглядит это так

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/0a31b0c154406b340e9bb044c4211afd6494bcac6ec197c99a10a6d0effb6a31.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3fcff1b34a5d9af3cdd70e4dac1188abd3edd13e74d11e4f0bba5d667d4f53a1.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/c2f9bb8ca36961def04d4a3111a7d4213bb219949d13094b525a1a906ab788f7.png" alt="2">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/accdd93e3428b9b03132eafceda3ec5e1cfda742a978f1cd7f2c6bcf1904ceaa.png" alt=""><figcaption></figcaption></figure>

</div>

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/e0f6c806d296e47269b9908ceab7b90954bbd219d3d9c13462ebee8344f854f3.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1ed164077989d04273ae3b40ec6daf7cf9b93ec42d917533b1e9758525231b7b.png" alt=""><figcaption></figcaption></figure>

</div>

Итак, из статического анализа видно, что это то, что известно как перехват (hooking). :) По сути, он пропатчивает байты ImgArchStartBootApplication, чтобы они указывали на sub\_180001D80, и сохраняет исходную функцию ImgArchStartBootApplication в byte\_180015C78

и, как мы видим, она меняется ровно на sub\_180001D80

<div>

<img src="https://assets.kitploit.com/production/public/readmes/44336/6c48bf4c9126a9a1466493aed943113cc27b4bbf9f7d68cdd251d0e14303ad8a.png" alt="1">

 

<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/633d84a62c16dba91229fe6bb73ed0318719fc06f63f7f2a9d19adba0d0e8cfe.png" alt=""><figcaption></figcaption></figure>

</div>

далее мы сбрасываем привилегии и оттуда передаём управление boomgrfw.efi :)

Итак, это официально знаменует завершение первой половины анализа :) в следующей части мы узнаем, как дальше отлаживать sub\_180001D80 и boomgrfw.efi(в нашем случае winload.efi). Так что, пожалуйста, сидите смирно, пока я учусь, как подготовить окружение для второй части анализа

=============================================================================

Теперь о второй половине анализа.... Как нам отлаживать boomgrfw.efi?
Скачать инструмент