Windows была изменена и отключена патчгардом
Обновлено: 21.11.2024
Это будет серия сообщений, состоящая из нескольких частей, описывающих внутренние механизмы и назначение Secure Kernel Patch Guard, также известного как HyperGuard. В этой первой части основное внимание будет уделено тому, что такое SKPG и как он инициализируется.
С точки зрения безопасности Windows, PatchGuard — это уникальная недокументированная и вряд ли какая-либо «неофициальная» документация. Таким образом, существуют противоречивые мнения и слухи о том, как он работает, а различные «обходы PatchGuard», которые публикуются, не очень надежны. Тем не менее, каждые несколько лет публикуется полезный анализ PG, проливающий некоторый свет на эту загадочную особенность. Этот пост в блоге не о PatchGuard, поэтому мы не будем вдаваться в подробности, но в нем обсуждается похожая и связанная функция, поэтому необходимы некоторые базовые знания о PatchGuard. Вот несколько вещей, которые необходимы для понимания остальной части поста:
- Задачей PatchGuard является мониторинг системы на наличие изменений в пространстве ядра, которые не должны происходить в обычной системе, и аварийное завершение работы при их обнаружении. Это не означает каких-либо необычных изменений данных — PatchGuard отслеживает заранее определенный список структур данных, которые являются общими целями для эксплуатации ядра или руткитов, таких как модификации HalDispatchTable или массивов обратных вызовов, или изменения в управляющих регистрах или MSR для отключения функций безопасности. . Полный список отслеживаемых структур и указателей не документирован, а информация, которая публикуется Microsoft, намеренно оставлена расплывчатой.
- PatchGuard не все время отслеживает. Он запускается периодически, проверяя определенные изменения при каждом запуске — он не обязательно приведет к сбою системы сразу после внесения злонамеренного изменения, и система может работать долгое время с такими изменениями. Нет никакой гарантии, что PatchGuard когда-либо обнаружит и приведет к сбою системы. Это также означает, что трудно проверить потенциальные обходные пути.
Основной недостаток PatchGuard и причина всей неясности вокруг его реализации заключается в том, что он отслеживает код и данные кольца 0 — из кода, который выполняется в кольце 0 . Ничто не мешает руткиту, уже получившему привилегии выполнения кода Ring 0, исправлять код самого PatchGuard и отключать или обходить его. Единственное, что останавливает этот сценарий, — это неизвестность PatchGuard и тот факт, что его код трудно найти, и он использует ряд методов запутывания, чтобы его было трудно проанализировать и отключить.
Можно еще многое сказать о PatchGuard, но, как я уже говорил, это не тема поста. Итак, я сразу перейду к обсуждению нового брата PatchGuard — HyperGuard, также известного как Secure Kernel Patch Guard или SKPG. Эта новая функция использует существование Hyper-V и VBS для создания новых возможностей мониторинга и защиты, которые аналогичны PatchGuard, но не подвержены тем же недостаткам, поскольку не работают как обычный код Ring 0 и не могут быть взломаны обычными руткитами.
HyperGuard использует VBS — безопасность на основе виртуализации. Эта возможность, добавленная за последние несколько лет, стала возможной благодаря созданию Hyper-V и виртуальных уровней доверия (VTL). Гипервизор позволяет создать систему, в которой большинство вещей выполняется в VTL0, но некоторые, более привилегированные вещи, выполняются в более высоких VTL (в настоящее время реализована только VTL1), где они недоступны обычным процессам независимо от их уровня привилегий, включая VTL0. код ядра. Проще говоря, никакой код VTL0 не может каким-либо образом взаимодействовать с памятью в VTL1.
Наличие памяти, которую нельзя изменить даже из обычного кода ядра, позволяет использовать множество новых функций безопасности, о некоторых из которых я писал ранее, а другие описаны в других блогах, выступлениях на конференциях и в официальной документации Microsoft. Несколько примеров включают KCFG , HVCI и KDP .
Это также то, что позволяет Microsoft реализовать HyperGuard — функцию, аналогичную PatchGuard, которую нельзя подделать даже с помощью вредоносного кода, которому удалось подняться до запуска в ядре. По этой причине HyperGuard не нужно каким-либо образом скрывать или запутывать себя, и его намного проще анализировать с помощью инструментов статического анализа.
Ядро VTL1, также известное как защищенное ядро, управляется с помощью SecureKernel.exe . Это также двоичный файл, в котором реализован HyperGuard. Если мы откроем securekernel.exe в IDA, мы можем легко найти весь код, реализующий HyperGuard, который использует префикс Skpg:
В этой серии статей будут рассмотрены некоторые из этих функций, начиная с первой, вызываемой во время загрузки: SkpgInitSystem:
Инициализация HyperGuard в основном происходит во время инициализации Фазы 1 обычного ядра, но требует нескольких шагов. Первый шаг начинается с безопасного вызова, где SKSERVICE=SECURESERVICE_PHASE3_INIT.Это приводит к SkInitSystem, который инициализирует SKCI (Secure Kernel Code Integrity) и вызывает SkpgInitSystem. Эта функция устанавливает основные компоненты SKPG — его обратный вызов, таймер, таблицу расширений и функции перехвата, которые я буду обсуждать более подробно позже в этой серии. На данный момент SKPG не полностью инициализирован — это происходит позже в ответ на другой запрос от обычного ядра. На данный момент устанавливаются только несколько глобальных переменных SKPG:
После инициализации всех глобальных переменных функция возвращается, а остальная часть безопасной инициализации ядра продолжается. На данный момент таймер не запланирован, и HyperGuard фактически «бездействует». HyperGuard полностью «активируется» позже — через вызов SkpgConnect .
Существует три способа вызова SkpgConnect, и все они начинаются с вызова обычным ядром:
Подключение программного прерывания — путь PatchGuard
Самый интересный способ активации HyperGuard — через PatchGuard. Этот путь активации SKPG, как и все остальные, начинается с безопасного вызова. Этот безопасный вызов с SKSERVICE= SECURESERVICE_CONNECT_SW_INTERRUPT исходит из обычной функции ядра VslConnectSwInterrupt. Это, как обычно, приводит к безопасному обработчику ядра, который вызывает IumpConnectSwInterrupt, а оттуда — SkpgConnect, передавая ему все данные, отправленные обычным ядром.
Когда мы ищем вызовы VslConnectSwInterrupt, мы видим два вызова: один из PsNotifyCoreDriversInitialized, о котором я скоро расскажу, и второй из KiConnectSwInterrupt:
KiConnectSwInterrupt вызывается только одним вызывающим объектом — анонимной функцией в ntoskrnl.exe, у которой нет имени в общедоступных символах. Это чрезвычайно большая функция, которая вызывает другие анонимные функции и имеет множество странных и, казалось бы, несвязанных между собой функций. Это одна из процедур инициализации PatchGuard, которая выполняет «настоящую» активацию HyperGuard, предоставляя безопасному ядру диапазоны и цели защиты памяти, которые я буду обсуждать позже, когда буду говорить об экстентах SKPG.
Я призываю вас самостоятельно следить за стеком вызовов и немного разбираться в тайнах инициализации PatchGuard, но если я начну подробно рассказывать о PatchGuard, эта серия быстро превратится в книгу, поэтому я пропущу здесь подробности. Давайте просто поверим мне, когда я скажу, что все это также происходит в контексте инициализации Фазы 1 и является первой точкой, где активируется HyperGuard.
После полной активации HyperGuard для глобальной переменной SkpgInitialized устанавливается значение TRUE . Эта переменная проверяется каждый раз, когда вызывается SkpgConnect, и если она установлена, функция немедленно вернется и не внесет никаких изменений в какие-либо данные инициализации SKPG. Это означает, что два других пути активации, которые будут описаны здесь, будут активировать HyperGuard только в том случае, если PatchGuard не запущен, и приведут к менее надежной защите машины. Если PatchGuard активен, два других пути активации вернутся без каких-либо действий.
Программное прерывание подключения — инициализация фазы 1
Второй путь кода к VslConnectSwInterrupt проходит через PsNotifyCoreDriversInitialized . Это также происходит как часть инициализации Фазы 1, но позже, чем путь PatchGuard:
Как мы видим здесь, вызов VslConnectSwInterrupt выполняется с пустыми входными переменными, что означает, что в HyperGuard не отправляются диапазоны памяти или дополнительные данные, и он будет использовать только свои основные функции. Если PatchGuard запущен, то в этот момент SKPG уже должен быть инициализирован, и вызов вернется без изменений в SKPG, поэтому этот путь нужен только в том случае, если PatchGuard не активен.
Фаза 3 Инициализация
Последний случай активации HyperGuard происходит во время фазы 3 инициализации. Это происходит в ответ на безопасный вызов с SKSERVICE=SECURESERVICE_REGISTER_SYSTEM_DLLS. Он также будет вызывать SkpgConnect без входных данных, просто для его инициализации, если ничего другого еще не было.
На обычной стороне ядра: в PspInitPhase3 система проверяет глобальную переменную VslVsmEnabled, чтобы узнать, работает ли Hyper-V и включен ли VSM. Если это так, система вызывает VslpEnterIumSecureMode — общую функцию для создания безопасного вызова с заданным сервисным кодом и аргументами, упакованными в MDL. Система переходит в безопасный режим с сервисным кодом SECURESERVICE_REGISTER_SYSTEM_DLLS:
После того, как безопасный вызов достигает безопасного ядра, он обрабатывается IumInvokeSecureService , который в значительной степени представляет собой просто большой оператор switch, вызывающий правильную функцию или функции для каждого кода службы. В случае кода SECURESERVICE_REGISTER_SYSTEM_DLLS он вызывает SkpgConnect, а затем использует данные, переданные ядром, для регистрации системных библиотек DLL:
Как я уже упоминал, SkpgConnect вызывается в последний раз в самом конце инициализации системы. Это делается на тот случай, если SKPG еще не был инициализирован на более раннем этапе. В этом случае SkpgConnect вызывается практически без входных данных, чтобы инициализировать только самые основные функции SKPG. Если SKPG уже был инициализирован ранее, этот вызов вернется без каких-либо изменений.
Активация HyperGuard — схема
Это первая часть этой серии. До сих пор мы рассмотрели только общее представление о том, что такое HyperGuard, и пути его инициализации. В следующий раз мы углубимся в SkpgConnect, чтобы узнать, что происходит во время активации SKPG, и узнать больше о типах данных, которые SKPG защищает, и о том, как это сделать.
В этом текстовом файле представлен общий обзор/схема обхода проверки подписи критически важных системных файлов (в основном, ntoskrnl) на
этапе загрузки Vista/Win 7. Это документация шагов, предпринятых от начала до конца для достижения желаемой цели удаления
защиты ядра "PatchGuard" без использования драйвера. Мы будем называть это «ленивым/простым» способом убить PatchGuard.
Мы не можем изменить ntoskrnl без проблем с winload.
winload.exe — это загрузчик Windows для Vista и Windows 7. Наряду с этим он выполняет некоторую проверку цифровых подписей и
проверяет, не были ли файлы изменены. Если модификация ntoskrnl обнаружена, результатом будет то, что winload *отказывается*
загружать Windows и запускает WinPE в режиме восстановления.
ЧАСТЬ I: разборка и модификация winload.exe
Начиная с OslpMain, после загрузки кустов системного реестра (реестра). происходит вызов OslInitializeCodeIntegrity:
.text:00000000004016C3 вызов OslpLoadSystemHive
.text:00000000004016C3
.text:00000000004016C8 cmp eax, ebx
.text:00000000004016CA mov edi, eax6CCl
.text:0000000 loc_401A08
.text:00000000004016CC
.text:00000000004016D2 mov ecx, ebp
.text:00000000004016D4 call OslInitializeCodeIntegrity >
48 8B C4 53
.text:00000000004057E8 mov rax, rsp
.text:00000000004057EB push rbx
.text:00000000004057EC push rbp
с: 0B0h, 01h, 0C3h, 090h . которые производят:
Сохраните как winload.exe как osloader.exe (или что-то еще) и исправьте контрольную сумму PE (подойдет LordPE и/или CFF_Explorer). Скопируйте osloader.exe в \Windows\System32
ЧАСТЬ II – новая запись BCD:
bcdedit /copy /d "PatchGuard отключен"
"Запись успешно скопирована в " >
INIT:000000014055D359 sub rsp, 0F58h
INIT:000000014055D360 xor edi, edi
INIT:000000014055D362 cmp cs:InitSafeBootMode, edi
>INIT:000000014055D368 jz short loc_14055D371
INIT:000000014055D368
INIT:000000014055D36A mov al, 1
INIT:000000014055D36C jmp loc_1405600D9
модифицированный код -->>
INIT:000000014055D359 sub rsp, 0F58h
INIT:000000014055D360 xor edi, edi
INIT:000000014055D362 cmp cs:InitSafeBootMode, edi
INIT: 000000014055D368 nop
INIT:000000014055D369 nop
INIT:000000014055D36A mov al, 1
INIT:000000014055D36C jmp loc_1405600D9 >
bcdedit /set ядро ntkrnlmp.exe
При перезагрузке системы загрузка модифицированного ядра должна пройти успешно. Он загрузится без инициализации PatchGuard, что позволит вам
еще раз играть в режиме ядра, не получая в результате BSOD.
Это также можно включить в код буткита mbr. это выходит за рамки наших намерений.
ссылки:
*1: Обход PatchGuard в Windows x64, Skywing, 01.12.2005
EfiGuard — это портативный буткит x64 UEFI, который исправляет диспетчер загрузки Windows, загрузчик и ядро во время загрузки, чтобы отключить PatchGuard и проверку подписи драйверов (DSE).
В настоящее время поддерживает все EFI-совместимые версии Windows x64, когда-либо выпущенные, от Vista SP1 до Server 2019.
Простота в использовании: можно загрузиться с USB-накопителя или раздела Windows EFI с помощью загрузчика, который автоматически находит и загружает Windows. Драйвер также можно загрузить и настроить вручную с помощью оболочки UEFI или загрузчика.
Широко использует библиотеку дизассемблера Zydis для быстрого декодирования инструкций во время выполнения, чтобы обеспечить более надежный анализ, чем это возможно при сопоставлении сигнатур, которое часто требует изменений с новыми обновлениями ОС.
Работает пассивно: драйвер не загружается и не запускает менеджер загрузки Windows. Вместо этого он действует при загрузке bootmgfw.efi диспетчером загрузки прошивки через меню выбора загрузки или приложение EFI, такое как загрузчик. Если загружается ОС, отличная от Windows, драйвер автоматически выгружается.
Поддерживает четырехэтапное исправление, когда bootmgfw.efi запускает bootmgr.efi, а не winload.efi. Это тот случай, когда файл WIM загружается для загрузки WinPE, программы установки Windows или режима восстановления Windows.
Мягкое восстановление: в случае сбоя исправления драйвер отобразит информацию об ошибке и предложит продолжить загрузку или перезагрузить компьютер, нажав ESC. Это верно даже до финальной стадии исправления ядра, потому что последняя стадия исправления происходит до вызова ExitBootServices. Многие буткиты UEFI для Windows перехватывают OslArchTransferToKernel, который, хотя и легко найти путем сопоставления с образцом, представляет собой функцию, которая выполняется в защищенном режиме после ExitBootServices. Это означает, что никакие службы загрузки не могут сообщить пользователю, что что-то пошло не так.
Смоделированный сбой исправления с информацией об ошибке
Отлаживаемый: может выводить сообщения в отладчик ядра и на экран (хотя и в буфере) на этапе исправления ядра, а также на последовательный порт или небуферизованные на экран на этапах диспетчера загрузки и исправления загрузчика. Если драйвер скомпилирован с отладочной информацией PDB, символы отладки можно загрузить в любой момент после инициализации HAL, указав базу виртуального драйвера DXE и отладив ее, как обычный драйвер NT.
Обход DSE: доступно либо как простое отключение DSE в стиле UPGDSED во время загрузки, либо как ловушка в службе времени выполнения EFI SetVariable(). Последний служит произвольным бэкдором для чтения/записи в режиме ядра, который можно вызвать из Windows с помощью NtSetSystemEnvironmentValueEx и позволяет установить g_CiEnabled / g_CiOptions в нужное значение. Для этого можно использовать небольшое приложение в стиле DSEFix с именем EfiDSEFix.exe. Также можно оставить DSE включенным и отключить только PatchGuard. Загрузчик будет использовать метод ловушки SetVariable по умолчанию из-за того, что некоторые антивирусные и античит-программы не понимают разницы между читами или вредоносными программами и самозаверяющими драйверами в целом и нацелены на исправление UPGDSED.
Поддерживает модифицированные ядра и загрузчики на диске, исправляя ImgpValidateImageHash на каждом этапе, а также ImgpFilterValidationFailure , который может незаметно передать некоторые классы нарушений в TPM или файл журнала SI.
Позволяет безопасной загрузке работать с Windows 7 (это не шутки!). Сама Windows 7 не обращает внимания на безопасную загрузку, поскольку не поддерживает ее или (официально) даже загрузку без CSM. Это полезно для людей, которые хотят использовать Windows 7 на заблокированном устройстве, требующем безопасной загрузки WHQL. Запись Wiki о том, как заставить это работать здесь.
WinObjEx64 в Windows 7 с включенной безопасной загрузкой
Проблемы и ограничения
- EfiGuard не может отключить проверку целостности кода, обеспечиваемую гипервизором (HVCI или HyperGuard), поскольку HVCI работает с более высоким уровнем привилегий. EfiGuard может сосуществовать с HVCI и даже успешно отключать PatchGuard в обычном ядре, но на практике это бесполезно, потому что HVCI перехватывает то, что ранее делал PatchGuard. Оба типа обхода DSE становятся бесполезными для HVCI: исправление времени загрузки не имеет никакого эффекта, потому что ядро уступает безопасному ядру для проверки целостности, а хук SetVariable вызовет проверку на ошибку SECURE_KERNEL_ERROR, если он используется для записи в g_CiOptions . ли>
- Проверенные ядра не поддерживаются из-за различий в коде инициализации PatchGuard и DSE, вызванных отключенными оптимизациями и добавленными утверждениями, а также дополнительными изменениями в PatchGuard в проверенных ядрах. Это не должно быть проблемой, так как проверенные ядра обычно бесполезны без подключенного отладчика ядра, который отключает PatchGuard.
Загрузка загрузчика
- Загрузите или скомпилируйте EfiGuard, перейдите в раздел EFI/Boot и переименуйте один из файлов Loader.efi или Loader.config.efi в bootx64.efi . Они идентичны, за исключением того, что Loader.efi загружается без взаимодействия с пользователем, тогда как Loader.config.efi предложит вам настроить метод исправления DSE, используемый драйвером (если вы хотите его изменить).
- Поместите файлы на загрузочный диск, например на USB-накопитель (для физических машин) или на ISO-образ или виртуальный диск (для виртуальных машин).Пути должны быть /EFI/Boot/
.efi . Рекомендуется использовать USB-накопители с файловой системой FAT32. - Загружайте машину с нового диска вместо загрузки Windows. В большинстве прошивок для этого предусмотрено загрузочное меню (доступно через F10/F11/F12). В противном случае вам потребуется настроить BIOS для загрузки с нового диска.
- Если вы используете загрузчик по умолчанию, теперь Windows должна загружаться, и во время загрузки вы должны видеть сообщения EfiGuard. Если вы используете настраиваемый загрузчик, ответьте на запросы конфигурации, и Windows загрузится.
- Если вы загружались с обработчиком SetVariable (по умолчанию), запустите EfiDSEFix.exe -d из командной строки после загрузки, чтобы отключить DSE. Запустите EfiDSEFix.exe, чтобы просмотреть полный список параметров.
Использование оболочки UEFI для загрузки драйвера
- Выполните шаги 1 и 2, описанные выше, но не переименовывайте загрузчик в bootx64.efi . Вместо этого либо используйте оболочку BIOS (если она у вас есть), либо загрузите оболочку UEFI EDK2 и переименуйте ее в bootx64.efi .
- Загрузите компьютер в оболочку UEFI.
- перейдите в /EFI/Boot в нужной файловой системе и запустите load EfiGuardDxe.efi, чтобы загрузить драйвер.
- (Необязательно) Запустите Loader.efi или Loader.config.efi из того же каталога, чтобы загрузить Windows. Вы также можете продолжить работу в оболочке или выйти, чтобы вернуться в меню BIOS/загрузки и загрузиться оттуда.
- После загрузки примените исправление DSE, как указано выше, если применимо.
Компиляция EfiGuardDxe и загрузчика
Для сборки EfiGuard требуется EDK2. Если у вас не установлен EDK2, сначала выполните шаги, описанные в разделе Начало работы с EDK2, поскольку система сборки EDK2 довольно сложна в настройке. В этом разделе предполагается, что у вас есть каталог рабочей области, на который указывает ваша переменная среды WORKSPACE, а копия EDK2 извлечена в workspace/edk2. Поддерживаемые компиляторы: MSVC, Clang, GCC и ICC.
- Клонируйте репозиторий EfiGuard в workspace/edk2/EfiGuardPkg .
- Откройте приглашение или оболочку, которая устанавливает переменные среды для EDK2.
- Запустите build -a X64 -t VS2017 -p EfiGuardPkg/EfiGuardPkg.dsc -b RELEASE , заменив VS2017 своей набором инструментов.
Это создаст файлы EfiGuardDxe.efi и Loader.efi в workspace/Build/EfiGuard/RELEASE_VS2017/X64 . Чтобы создать интерактивно настраиваемый загрузчик, добавьте -D CONFIGURE_DRIVER=1 к команде сборки.
Для сборки EfiDSEFix требуется Visual Studio.
Выходной двоичный файл EfiDSEFix.exe будет находиться в Application/EfiDSEFix/bin .
Решение Visual Studio также включает проекты для EfiGuardDxe.efi и Loader.efi, которые можно использовать с VisualUefi, но эти проекты не создаются по умолчанию, поскольку они не будут компоноваться без дополнительного кода, а результат сборки будет хуже ( больше), чем то, что производит EDK2. Loader.efi вообще не будет связываться из-за того, что в VisualUefi отсутствует UefiBootManagerLib. Таким образом, эти файлы проекта предназначены только для помощи в разработке, а файлы EFI все равно должны быть скомпилированы с помощью EDK2. Чтобы настроить VisualUefi для этой цели, клонируйте репозиторий в workspace/VisualUefi и откройте EfiGuard.sln .
Хотя EfiGuard — это буткит UEFI, он изначально не был таковым. Первоначально EfiGuard представлял собой средство исправления на диске, работающее в NT (похожее на UPGDSED), предназначенное для проверки жизнеспособности подхода на основе дизассемблера, в отличие от использования символов PDB и сигнатур для конкретной версии. PatchNtoskrnl.c по-прежнему очень похож на оригинальный дизайн. Только после того, как этот подход оказался успешным, без каких-либо модификаций кода, необходимых в течение более чем года обновлений Windows, UEFI стал известен как способ дальнейшего улучшения возможностей и простоты использования.
Некоторые преимущества буткитного подхода включают:
- Никаких модификаций ядер или загрузчиков на диске не требуется.
- Нет необходимости изменять хранилище конфигураций загрузки с помощью bcdedit .
- Нет необходимости исправлять ImgpValidateImageHash (хотя это можно сделать по желанию).
- Как ни странно, использование буткита позволяет включить безопасную загрузку при условии, что у вас есть ключ платформы и вы можете добавить свой личный сертификат в хранилище базы данных.
Первоначальное воплощение EfiGuard в виде буткита было попыткой заставить UEFI-буткит dude719 работать с последними версиями Windows 10, потому что он устарел и больше не работает с последними версиями (например, UPGDSED, часто вызванный версией -чувствительные сканы шаблонов). Хотя я в конечном итоге заставил это работать, я был недоволен результатом, в основном из-за выбора перехвата OslArchTransferToKernel , который, как отмечалось выше, выполняется в защищенном режиме и после вызова ExitBootServices.Кроме того, меня не устраивало то, что я мог исправлять только некоторые версии Windows 10; Я хотел, чтобы буткит работал на каждой EFI-совместимой версии Windows x64, выпущенной на сегодняшний день. По этой причине я переписал буткит с нуля со следующими целями:
- Для предоставления информации об исправлении на каждом этапе загрузки, включая само исправление ядра.
- Для поддержки всех совместимых с EFI версий версий Windows (на момент написания).
- Для включения ленивой реализации буткита и, при необходимости, бэкдора ядра с помощью перехватчиков системной таблицы EFI.
Общий обзор окончательного процесса загрузки EfiGuard показан на диаграмме выше. Чтобы узнать об хуках и исправлениях для отдельных компонентов, см. EfiGuardDxe/PatchXxx.c в исходных файлах. Информацию об инициализации/выгрузке драйвера и перехватчиках EFI Boot и Runtime Services см. в EfiGuardDxe.c.
-
авторы hfiref0x и Fyyre авторы zyantific статьи о PatchGuard v1, v2 и v3 автор Skywing автор dude719
EfiGuard распространяется под лицензией GPLv3. Файлы в подмодуле EfiGuardDxe/Zydis распространяются под лицензией MIT.
В операционной системе Microsoft Windows методы эксплуатации ядра были значительно смягчены благодаря средствам защиты, которые Microsoft внедрила, таким как защита от исправлений ядра (PatchGuard) и проверка подписи драйверов.
PatchGuard — это попытка Microsoft предотвратить несанкционированное изменение таблиц системных служб, таблицы дескрипторов прерываний, глобальной таблицы дескрипторов и данных, принадлежащих ядру, таких как библиотеки, драйверами устройств в 64-разрядных операционных системах Windows. Драйверы устройств имеют те же привилегии, что и само ядро, поскольку драйверы должны быть загружены в пространство памяти ядра, чтобы в достаточной степени взаимодействовать с оборудованием, с которым оно взаимодействует. В конечном счете, PatchGuard предотвращает исправление памяти, принадлежащей ядру, из драйверов устройств, а не один драйвер устройства, исправляющий другой. Если PatchGuard обнаруживает, что память ядра была изменена, он запускает «проверку на наличие ошибок», и операционная система показывает синий экран.
Принудительное применение подписи драйверов, впервые реализованное в Windows Vista, позволяет загружать в ядро только действительные подписанные драйверы. Microsoft реализовала это, чтобы предотвратить загрузку произвольного кода в ядро и предоставление привилегий ядра. Начиная с обновления 1607 для Windows 10, Microsoft должна подписывать любые драйверы, загружаемые в ядро, которые также должны быть подписаны с помощью действительного сертификата подписи кода с расширенной проверкой, чтобы даже быть обработанными Microsoft. Эти строгие требования были созданы, чтобы разрешить загрузку в пространство ядра только надежного и тщательно протестированного кода. Microsoft установила определенные правила для обеспечения обратной совместимости с драйверами, которые еще не соответствуют этим требованиям, которые будут показаны позже.
Обход методов предотвращения
Техника, которую мы будем использовать здесь для обхода ограничений, описанных выше, заключается в использовании действительного драйвера устройства для загрузки нашего собственного драйвера в пространство ядра. В частности, мы будем использовать эксплойт в драйвере режима ядра VirtualBox, который неоднократно использовался злоумышленниками для загрузки руткитов и получения привилегий ядра от непривилегированного пользователя. Этот эксплойт является примером опасностей, связанных с разработкой кода на уровне ядра, и серьезных угроз безопасности, которые могут исходить от любой части программного обеспечения, требующего доступа к ресурсам ядра.
Разбор VBoxDrv.sys
Когда пакет VirtualBox установлен на хосте, на машину загружается драйвер VBoxDrv.sys. Этот драйвер позволяет любому непривилегированному пользователю открывать устройство «\\.\VBoxDrv» и выдавать IOCTL с режимом буферизации METHOD_NEITHER без какой-либо проверки. Это позволяет ненадежному коду пользовательского режима передавать произвольные адреса ядра в качестве аргументов драйверу. С помощью специально сконструированного ввода злоумышленник может использовать функции драйвера для исправления адресов ядра и выполнения произвольного кода в режиме ядра. При обработке IOCTL метод связи должен быть предварительно определен между приложением пользовательского режима и модулем драйвера. Выбранный метод будет определять, как I/O Manager манипулирует буферами памяти, используемыми при обмене данными.
(1) Проверяет код IOCTL, введенный пользователем, на соответствие константам, определенным как функции. Приведенные ниже определения находятся в файле «SUPDrvIOC.h».
/** IOCtl быстрого пути: VMMR0_DO_HWACC_RUN */
/** Просто вызов NOP для профилирования задержки быстрого вызова ioctl
| SUP_IOCTL_FLAG, METHOD_NEITHER,
В SUP_CTL_CODE_FAST() используется METHOD_NEITHER, что означает, что указатель, переданный в «DeviceIOControl», будет отправлен непосредственно драйверу без буферизации в диспетчере ввода-вывода. Это означает, что драйвер должен надлежащим образом проверять и подтверждать адреса, полученные от пользователя. «VBoxDrv.sys» не проверяет должным образом буфер, отправляемый в объекте IRP, что позволяет злоумышленнику выполнять запись по любому адресу памяти в пространстве ядра.
(2) Значение, возвращаемое функцией «supdrvIOCtlFast()», сохраняется в «rc».
(3) Значение в «rc» записывается непосредственно в буфер. Поскольку этот адрес памяти предоставляется драйверу из пользовательского ввода, это может быть произвольный адрес в пространстве ядра.
Читайте также: