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

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

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

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

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

Категории

Все категории
Loading categories
EDRSandblast-GodFault — EDRSandblast-GodFault | Kitploit
Инструменты/GitHubGitHub/gabriellandau/edrsandblast-godfault
Оборонительные ИнструментыПовышение привилегийКриминалистика памятиЭксплуатацияПост-эксплуатацияRed TeamingРазработка Полезной НагрузкиArchived
GitHubgabriellandau/edrsandblast-godfault

EDRSandblast-GodFault

EDRSandblast-GodFault

Репозиторий
273502 лет назадПроверено Kitploit

Популярное

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

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

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

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

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

EDRSandblast-GodFault

Автор: Gabriel Landau из Elastic Security. Модификация EDRSandblast - см. оригинальный README ниже.

Интегрирует GodFault в EDR Sandblast, достигая того же результата без использования каких-либо уязвимых драйверов.

Пример вывода```

C:\Users\user\Desktop\Offsets>EDRSandblast.exe --kernelmode cmd


| | __ | __ \ / | | | | | | | | | | | | | | |) | ( __ _ _ __ | | | | | __ _ | | | | | | | | _ / _ \ / | '_ \ / _ | ' | |/ ` / __| __| | || || | | \ \ ) | (| | | | | (| | |) | | (| _ | | ||_____/|| _|/ _,|| ||_,|_./||_,|__/__|

D3FC0N 30 Edition | Thomas DIOT (@_Qazeer) & Maxime MEIGNAN (@th3m4ks)

[!] If kernel mode bypass is enabled, it is recommended to enable usermode bypass as well (e.g. to unhook the NtLoadDriver API call)

[===== KERNEL MODE =====]

[+] Setting up prerequisites for the kernel read/write primitives... [+] Loading kernel related offsets from the CSV file [*] System's ntoskrnl.exe file version is: ntoskrnl_22621-1702.exe [+] Offsets are available for this version of ntoskrnl.exe (ntoskrnl_22621-1702.exe)! [+] Checking if any EDR kernel notify rountines are set for image loading, process and thread creations... [+] [NotifyRountines] Enumerating process creation callbacks [+] Running command: GodFault.exe -t 2684 [?] Server does not appear to be running. Attempting to install it... [+] CSRSS PID is 748 [+] Testing initial ability to acquire PROCESS_ALL_ACCESS to System: Failure [+] Ready. Spawning WinTcb. [+] SpawnPPL: Waiting for child process to finish. [+] Thread 2684 (KTHREAD FFFF910961E4C080) has been blessed by GodFault [+] [NotifyRountines] fffff8034df25500 [cng.sys + 0x5500] [+] [NotifyRountines] fffff8034e9efdc0 [WdFilter.sys + 0x4fdc0] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff803487bc460 [ksecdd.sys + 0x1c460] [+] [NotifyRountines] fffff8034eff3fd0 [tcpip.sys + 0x13fd0] [+] [NotifyRountines] fffff8034f5ed980 [iorate.sys + 0xd980] [+] [NotifyRountines] fffff8034dea8890 [CI.dll + 0x88890] [+] [NotifyRountines] fffff803525079f0 [dxgkrnl.sys + 0x179f0] [+] [NotifyRountines] fffff80352be0a70 [vm3dmp.sys + 0x10a70] [+] [NotifyRountines] fffff8036ebccd00 [peauth.sys + 0x3cd00] [+] [NotifyRountines] fffff8036eda1550 [wtd.sys + 0x1550] [+] [NotifyRountines] Found a total of 1 EDR / security products driver(s) [+] [NotifyRountines] Enumerating thread creation callbacks [+] [NotifyRountines] fffff8034e9f15c0 [WdFilter.sys + 0x515c0] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff8034e9f1350 [WdFilter.sys + 0x51350] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff8036eb71010 [mmcss.sys + 0x1010] [+] [NotifyRountines] Found a total of 2 EDR / security products driver(s) [+] [NotifyRountines] Enumerating image loading callbacks [+] [NotifyRountines] fffff8034e9f0820 [WdFilter.sys + 0x50820] [+] [NotifyRountines] Found callback belonging to EDR driver WdFilter.sys [+] [NotifyRountines] fffff80352ab5710 [ahcache.sys + 0x25710] [+] [NotifyRountines] Found a total of 1 EDR / security products driver(s)

[+] Checking if EDR callbacks are registered on processes and threads handle creation/duplication... [+] [ObjectCallblacks] Enumerating Process object callbacks : [+] [ObjectCallblacks] Callback at FFFF800C5E2F2940 for handle creations & duplications: [+] [ObjectCallblacks] Status: Enabled [+] [ObjectCallblacks] Preoperation at 0xfffff8034e9eda30 [WdFilter.sys + 0x4da30] [+] [ObjectCallblacks] Callback belongs to an EDR and is enabled! [+] [ObjectCallblacks] Enumerating Thread object callbacks : [+] [ObjectCallblacks] Object callbacks are present !

[+] [ETWTI] Checking the ETW Threat Intelligence Provider state... [+] [ETWTI] ETW Threat Intelligence Provider is ENABLED!

[+] Process is NOT "safe" to launch our payload, removing monitoring and starting another process...

[+] [ETWTI] Disabling the ETW Threat Intel provider by patching ProviderEnableInfo at 0xffff91095ce8c430 with 0x00. [+] [ETWTI] The ETW Threat Intel provider was successfully disabled!

[+] Removing kernel callbacks registered by EDR for process creation, thread creation and image loading... [+] [NotifyRountines] Removing process creation callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c2a8 | callback struct: 0xffff91095dbf3a5f | callback function: 0xfffff8034e9efdc0] [+] [NotifyRountines] Removing thread creation callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c4a0 | callback struct: 0xffff91095dbf3b1f | callback function: 0xfffff8034e9f15c0] [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c4a8 | callback struct: 0xffff91095dbf3b4f | callback function: 0xfffff8034e9f1350] [+] [NotifyRountines] Removing image loading callbacks [+] [NotifyRountines] Removing callback of EDR driver "WdFilter.sys" [callback addr: 0xfffff8034970c6a0 | callback struct: 0xffff91095dbf3e4f | callback function: 0xfffff8034e9f0820]

[+] Disabling kernel callbacks registered by EDR for process and thread opening or handle duplication... [+] [ObjectCallblacks] Disabling WdFilter.sys callback...

[+] All EDR drivers were successfully removed from Kernel callbacks!

================================================== Starting a new unmonitored process...

[!] If kernel mode bypass is enabled, it is recommended to enable usermode bypass as well (e.g. to unhook the NtLoadDriver API call)

[===== KERNEL MODE =====]

[+] Setting up prerequisites for the kernel read/write primitives... [+] Loading kernel related offsets from the CSV file [*] System's ntoskrnl.exe file version is: ntoskrnl_22621-1702.exe [+] Offsets are available for this version of ntoskrnl.exe (ntoskrnl_22621-1702.exe)! [+] Checking if any EDR kernel notify rountines are set for image loading, process and thread creations... [+] [NotifyRountines] Enumerating process creation callbacks [+] Running command: GodFault.exe -t 8344 [+] Thread 8344 (KTHREAD FFFF91096169F080) has been blessed by GodFault [+] Initial blessing successful [+] [NotifyRountines] fffff8034df25500 [cng.sys + 0x5500] [+] [NotifyRountines] fffff803487bc460 [ksecdd.sys + 0x1c460] [+] [NotifyRountines] fffff8034eff3fd0 [tcpip.sys + 0x13fd0] [+] [NotifyRountines] fffff8034f5ed980 [iorate.sys + 0xd980] [+] [NotifyRountines] fffff8034dea8890 [CI.dll + 0x88890] [+] [NotifyRountines] fffff803525079f0 [dxgkrnl.sys + 0x179f0] [+] [NotifyRountines] fffff80352be0a70 [vm3dmp.sys + 0x10a70] [+] [NotifyRountines] fffff8036ebccd00 [peauth.sys + 0x3cd00] [+] [NotifyRountines] fffff8036eda1550 [wtd.sys + 0x1550] [+] [NotifyRountines] No EDR driver(s) found! [+] [NotifyRountines] Enumerating thread creation callbacks [+] [NotifyRountines] fffff8036eb71010 [mmcss.sys + 0x1010] [+] [NotifyRountines] No EDR driver(s) found! [+] [NotifyRountines] Enumerating image loading callbacks [+] [NotifyRountines] fffff80352ab5710 [ahcache.sys + 0x25710] [+] [NotifyRountines] No EDR driver(s) found!

[+] Checking if EDR callbacks are registered on processes and threads handle creation/duplication... [+] [ObjectCallblacks] Enumerating Process object callbacks : [+] [ObjectCallblacks] Callback at FFFF800C5E2F2940 for handle creations & duplications: [+] [ObjectCallblacks] Status: Disabled [+] [ObjectCallblacks] Preoperation at 0xfffff8034e9eda30 [WdFilter.sys + 0x4da30] [+] [ObjectCallblacks] Callback belongs to an EDR but is disabled. [+] [ObjectCallblacks] Enumerating Thread object callbacks : [+] [ObjectCallblacks] Object callbacks are not found !

[+] [ETWTI] Checking the ETW Threat Intelligence Provider state... [+] [ETWTI] ETW Threat Intelligence Provider is DISABLED!

[+] Process is "safe" to launch our payload

[+] Kernel callbacks have normally been removed, starting cmd.exe WARNING: EDR kernel callbacks will be restored after exiting the cmd prompt (by typing exit) WARNING: While unlikely, the longer the callbacks are removed, the higher the chance of being detected / causing a BSoD upon restore is!

Microsoft Windows [Version 10.0.22621.1702] (c) Microsoft Corporation. All rights reserved.

C:\Users\user\Desktop\Offsets>

root@kitploit:~
# EDRSandBlast

`EDRSandBlast` — это инструмент, написанный на `C`, который использует уязвимый подписанный драйвер для обхода детектирования EDR (колбэков Notify Routine, Object Callbacks и провайдера `ETW TI`) и защиты `LSASS`. Также реализованы несколько методов развертывания пользовательских хуков для обхода мониторинга на уровне пользователя.

На момент выпуска комбинация техник пользовательского режима (`--usermode`) и режима ядра (`--kernelmode`) использовалась для дампа памяти `LSASS` под наблюдением EDR, не будучи заблокированной и не вызывая событий, связанных с «OS Credential Dumping», в консоли продукта (облачной). Тесты проводились на 3 различных продуктах EDR и в каждом случае были успешными.

## Описание

### Обход EDR через удаление Kernel Notify Routines

Продукты EDR используют колбэки Kernel «Notify Routines» в Windows для уведомления ядром о системной активности, такой как создание процессов и потоков, а также загрузка образов (`exe` / `DLL`).

Эти колбэки ядра определяются на уровне ядра, обычно из драйвера, реализующего колбэки, с помощью ряда документированных API (`nt!PsSetCreateProcessNotifyRoutine`, `nt!PsSetCreateThreadNotifyRoutine` и т.д.). Эти API добавляют предоставленные драйвером процедуры колбэков в недокументированные массивы процедур в пространстве ядра:
  - `PspCreateProcessNotifyRoutine` для создания процессов
  - `PspCreateThreadNotifyRoutine` для создания потоков
  - `PspLoadImageNotifyRoutine` для загрузки образов

`EDRSandBlast` перечисляет процедуры, определённые в этих массивах, и удаляет любые процедуры колбэков, связанные с предопределённым списком драйверов EDR (поддерживается более 1000 драйверов продуктов безопасности, см. [раздел обнаружения драйверов EDR](#edr-drivers-and-processes-detection)). Перечисление и удаление становятся возможными благодаря эксплуатации примитива произвольного чтения/записи памяти ядра, полученного путём эксплуатации уязвимого драйвера (см. [раздел об уязвимых драйверах](#vulnerable-drivers-detection)).

Смещения вышеупомянутых массивов восстанавливаются с помощью нескольких техник. Пожалуйста, обратитесь к [разделу о смещениях](#ntoskrnl-and-wdigest-offsets).

### Обход EDR через удаление Object Callbacks

Продукты EDR (и даже EPP) часто регистрируют «Object callbacks» с помощью API ядра `nt!ObRegisterCallbacks`. Эти колбэки позволяют продукту безопасности получать уведомления при каждом создании дескриптора на определённых типах объектов (теперь Windows поддерживает колбэки объектов, связанных с процессами, потоками и рабочими столами). Создание дескриптора может происходить при открытии объекта (вызов `OpenProcess`, `OpenThread` и т.д.), а также при дублировании дескриптора (вызов `DuplicateHandle` и т.д.).

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

При каждой регистрации колбэка с помощью `ObRegisterCallbacks` в двусвязный список `CallbackList`, присутствующий в объекте `_OBJECT_TYPE`, описывающем тип объекта, затронутого колбэком (процесс, поток или рабочий стол), добавляется новый элемент. К сожалению, эти элементы описываются структурой, которая не документирована и не публикуется Microsoft в файлах символов. Однако её изучение в различных версиях `ntoskrnl.exe` показывает, что структура не менялась по крайней мере между сборками Windows 10 10240 и 22000 (с 2015 по 2022 год).

Упомянутая структура, представляющая регистрацию колбэка объекта, выглядит следующим образом:```C
typedef struct OB_CALLBACK_ENTRY_t {
    LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList
    OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications
    BOOL Enabled;            // self-explanatory
    OB_CALLBACK* Entry;      // points to the structure in which it is included
    POBJECT_TYPE ObjectType; // points to the object type affected by the callback
    POB_PRE_OPERATION_CALLBACK PreOperation;      // callback function called before each handle operation
    POB_POST_OPERATION_CALLBACK PostOperation;     // callback function called after each handle operation
    KSPIN_LOCK Lock;         // lock object used for synchronization
} OB_CALLBACK_ENTRY;

Структура OB_CALLBACK, упомянутая выше, также не документирована и определяется следующим образом:```C typedef struct OB_CALLBACK_t { USHORT Version; // usually 0x100 USHORT OperationRegistrationCount; // number of registered callbacks PVOID RegistrationContext; // arbitrary data passed at registration time UNICODE_STRING AltitudeString; // used to determine callbacks order struct OB_CALLBACK_ENTRY_t EntryItems[1]; // array of OperationRegistrationCount items WCHAR AltitudeBuffer[1]; // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer } OB_CALLBACK;

root@kitploit:~
Для отключения обратных вызовов объектов, зарегистрированных EDR, в `EDRSandblast` реализованы три метода; однако на данный момент включен только один.

#### Использование поля `Enabled` структуры `OB_CALLBACK_ENTRY`
Это метод по умолчанию, включенный в `EDRSandblast`. Для обнаружения и отключения связанных с EDR обратных вызовов объектов просматривается список `CallbackList`, расположенный в объектах `_OBJECT_TYPE`, связанных с типами *Process* и *Thread*. Оба `_OBJECT_TYPE` указываются глобальными символами ядра `PsProcessType` и `PsThreadType`.

Предполагается, что каждый элемент списка соответствует структуре `OB_CALLBACK_ENTRY`, описанной выше (предположение, которое, по-видимому, справедливо по крайней мере для всех сборок Windows 10 на момент написания статьи). Функции, определенные в полях `PreOperation` и `PostOperation`, проверяются на принадлежность драйверу EDR, и если это так, обратные вызовы просто отключаются переключением флага `Enabled`.

Хотя это довольно безопасный метод, он имеет недостаток, заключающийся в использовании недокументированной структуры; чтобы снизить риск небезопасного манипулирования этой структурой, выполняются базовые проверки для подтверждения того, что некоторые поля имеют ожидаемые значения:
* `Enabled` имеет значение `TRUE` или `FALSE` (*не смейтесь, `BOOL` — это `int`, поэтому он может быть чем угодно, кроме `1` или `0`*);
* `Operations` содержит `OB_OPERATION_HANDLE_CREATE`, `OB_OPERATION_HANDLE_DUPLICATE` или оба;
* `ObjectType` указывает на `PsProcessType` или `PsThreadType`.

#### Открепление списка `CallbackList` для потоков и процессов
Другая стратегия, которая не опирается на недокументированную структуру (и поэтому теоретически более устойчива к изменениям ядра NT), заключается в откреплении всего `CallbackList` как для процессов, так и для потоков. Объект `_OBJECT_TYPE` выглядит следующим образом:```C
struct _OBJECT_TYPE {
	LIST_ENTRY TypeList;
	UNICODE_STRING Name;
	[...]
	_OBJECT_TYPE_INITIALIZER TypeInfo;
	[...]
	LIST_ENTRY CallbackList;
}

Установка указателей Flink и Blink списка CallbackList структуры _OBJECT_TYPE на саму LIST_ENTRY фактически делает список пустым. Поскольку структура _OBJECT_TYPE опубликована в символах ядра, эта техника не зависит от жестко закодированных смещений/структур. Однако у нее есть некоторые недостатки.

Первый — невозможность отключить только колбэки от EDR; действительно, техника затрагивает все объектные колбэки, которые могли быть зарегистрированы "легитимным" программным обеспечением. Тем не менее, следует отметить, что объектные колбэки не используются ни одним предустановленным компонентом в Windows 10 (на момент написания), поэтому их отключение не должно повлиять на стабильность системы (тем более, если отключение временное).

Второй недостаток заключается в том, что операции с дескрипторами процессов или потоков происходят очень часто (почти непрерывно) при нормальной работе ОС. Таким образом, если используемый примитив записи в ядро не может выполнить запись QWORD "атомарно", велика вероятность, что указатель _OBJECT_TYPE.CallbackList.Flink будет доступен ядру в процессе его перезаписи. Например, уязвимый драйвер MSI RTCore64.sys может за раз выполнять только запись DWORD, поэтому для перезаписи указателя потребуется 2 разных IOCTL, между которыми ядро с высокой вероятностью использует его (что приведет к сбою). С другой стороны, уязвимый драйвер DELL DBUtil_2_3.sys может выполнять запись произвольных размеров за один IOCTL, поэтому использование этого метода с ним не рискует вызвать сбой.

Полное отключение объектных колбэков

Еще одна найденная нами техника — полностью отключить поддержку объектных колбэков для потоков и процессов. Внутри структуры _OBJECT_TYPE, соответствующей типам процесса и потока, находится поле TypeInfo, следующее документированной структуре _OBJECT_TYPE_INITIALIZER. Последняя содержит битовое поле ObjectTypeFlags, флаг которого SupportsObjectCallbacks определяет, поддерживает ли описываемый тип объекта (Process, Thread, Desktop, Token, File и т. д.) регистрацию объектных колбэков. Как уже упоминалось, на момент написания в Windows только типы объектов Process, Thread и Desktop поддерживают эти колбэки.

Поскольку флаг SupportsObjectCallbacks проверяется функциями ObpCreateHandle или ObDuplicateObject еще до чтения CallbackList (и, конечно, до выполнения колбэков), переключение этого бита во время выполнения ядра фактически отключает выполнение всех объектных колбэков.

Основной недостаток метода заключается в том, что KPP ("PatchGuard") отслеживает целостность некоторых (всех?) структур _OBJECT_TYPE и инициирует 0x109 Bug Check с параметром 4, равным 0x8, что означает изменение структуры типа объекта.

Однако выполнение отключения / повторного включения (и "вредоносного" действия между ними) достаточно быстро должно позволить "обогнать" PatchGuard (если только вам не не повезет, и периодическая проверка не произойдет в самый неподходящий момент).

Обход EDR путем деактивации поставщика ETW Microsoft-Windows-Threat-Intelligence

Поставщик ETW Microsoft-Windows-Threat-Intelligence регистрирует данные об использовании некоторых API Windows, часто используемых в злонамеренных целях. Сюда входит API nt!MiReadWriteVirtualMemory, вызываемый nt!NtReadVirtualMemory (используется для дампа памяти LSASS) и отслеживаемый функцией nt!EtwTiLogReadWriteVm.

Продукты EDR могут потреблять логи, создаваемые поставщиком ETW TI, через службы или процессы, работающие как, соответственно, SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT или PS_PROTECTED_ANTIMALWARE_LIGHT и связанные с драйвером Early Launch Anti Malware (ELAM).

Как опубликовано slaeryan в блоге CNO Development Labs, поставщик ETW TI можно полностью отключить, пропатчив в памяти ядра его атрибут ProviderEnableInfo в 0x0. За дополнительной информацией о технике обращайтесь к упомянутой выше отличной записи в блоге.

Аналогично удалению колбэков ядра, необходимые смещения в ntoskrnl.exe (nt!EtwThreatIntProvRegHandleOffset, GuidEntry из _ETW_REG_ENTRY и ProviderEnableInfo из _ETW_GUID_ENTRY) вычисляются в файле NtoskrnlOffsets.csv для ряда версий ядра Windows.

Обход EDR путем обхода перехвата в пользовательском режиме

Как работает перехват в пользовательском режиме

Чтобы легко отслеживать действия, выполняемые процессами, продукты EDR часто используют механизм, называемый перехватом в пользовательском режиме. Сначала продукты EDR регистрируют колбэк ядра (обычно колбэки загрузки образа или создания процесса, см. выше), который позволяет им получать уведомления при каждом запуске процесса.

Когда процесс загружается Windows, и до его фактического запуска, EDR может внедрить в адресное пространство процесса пользовательскую DLL, содержащую его логику мониторинга. При загрузке эта DLL внедряет "хуки" в начало каждой функции, подлежащей мониторингу EDR. Во время выполнения, когда отслеживаемые функции вызываются процессом под наблюдением, эти хуки перенаправляют поток управления в некоторый код контроля, присутствующий в DLL EDR, что позволяет проверять аргументы и возвращаемые значения этих вызовов.

В большинстве случаев отслеживаемыми функциями являются системные вызовы (такие как NtReadVirtualMemory, NtOpenProcess и т. д.), реализации которых находятся в ntdll.dll. Перехват вызовов функций Nt* позволяет продуктам быть как можно ближе к границе пользовательского режима / режима ядра (оставаясь в пользовательском режиме), но также могут отслеживаться функции из некоторых библиотек DLL более высокого уровня.

Ниже приведены примеры одной и той же функции до и после перехвата продуктом EDR:```assembly NtProtectVirtualMemory proc near mov r10, rcx mov eax, 50h test byte ptr ds:7FFE0308h, 1 jnz short loc_18009D1E5 syscall retn loc_18009D1E5: int 2Eh retn NtProtectVirtualMemory endp

root@kitploit:~
(No content to translate)```assembly
NtProtectVirtualMemory proc near
	jmp     sub_7FFC74490298     ; --> "hook", jump to EDR analysis function
	int 3                        ; overwritten instructions
	int 3                        ; overwritten instructions
	int 3                        ; overwritten instructions
	test byte_7FFE0308, 1        ; <-- execution resumes here after analysis
	jnz short loc_7FFCB44AD1E5
	syscall
	retn
loc_7FFCB44AD1E5:
	int 2Eh
	retn
NtProtectVirtualMemory   endp			

Обнаружение хуков

Пользовательские хуки имеют «слабость» — они расположены в пользовательской памяти, а значит, непосредственно наблюдаемы и модифицируемы анализируемым процессом. Для автоматического обнаружения хуков в адресном пространстве процесса основная идея состоит в сравнении различий между оригинальной DLL на диске и библиотекой, находящейся в памяти, которая потенциально могла быть изменена EDR. Для выполнения этого сравнения EDRSandblast следует следующим шагам:

  • Список всех загруженных DLL перечисляется с помощью InLoadOrderModuleList, расположенного в PEB (чтобы избежать вызова API, которые могут быть отслеживаемы и подозрительны).
  • Для каждой загруженной DLL её содержимое на диске читается и разбираются её заголовки. Соответствующая библиотека, находящаяся в памяти, также анализируется для идентификации секций, экспортов и т.д.
  • Релокации DLL разбираются и применяются с учётом базового адреса соответствующей загруженной библиотеки. Это позволяет содержимому библиотеки в памяти и DLL с диска иметь абсолютно одинаковое содержимое (в секциях, где применяются релокации), делая сравнение надёжным.
  • Экспортированные функции перечисляются, и сравниваются первые байты версий «в памяти» и «на диске». Любое различие указывает на изменение, внесённое после загрузки DLL, и, следовательно, с высокой вероятностью является хуком EDR.

Примечание: Этот процесс можно обобщить для поиска различий в любых незаписываемых секциях, а не только в начале экспортированных функций, например, если продукты EDR начнут устанавливать хуки в середине функции :) Хотя этот подход не используется инструментом, он реализован в findDiffsInNonWritableSections.

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

Обход хуков с помощью... анхукинга

Наиболее интуитивный метод обхода мониторинга на основе хуков — удалить хуки. Поскольку хуки находятся в памяти, доступной самому процессу, для удаления хука процесс может просто:

  • Изменить разрешения на странице, где расположен хук (RX -> RWX или RW).
  • Записать оригинальные байты, известные благодаря содержимому DLL на диске.
  • Вернуть разрешения обратно на RX.

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

Однако у этого подхода есть два основных недостатка. EDR, вероятно, отслеживает использование NtProtectVirtualMemory, поэтому его применение для изменения разрешений на странице, где установлены хуки, (по крайней мере, концептуально) является плохой идеей. Кроме того, если поток, запущенный EDR, периодически проверяет целостность хуков, это также может вызвать обнаружение.

Детали реализации смотрите в кодовом пути функции unhook(), когда unhook_method равен UNHOOK_WITH_NTPROTECTVIRTUALMEMORY.

Важное примечание: для простоты этот метод реализован в EDRSandblast как базовый, используемый для демонстрации других методов обхода; каждый из них показывает, как получить немониторируемую версию NtProtectVirtualMemory, но после этого выполняет ту же операцию (анхукинг конкретного хука).

Обход хуков с помощью пользовательского трамплина

Для обхода конкретного хука можно просто «перепрыгнуть» через него и выполнить остальную часть функции как есть. Сначала необходимо восстановить из файла DLL оригинальные байты отслеживаемой функции, которые были перезаписаны EDR для установки хука. В нашем предыдущем примере кода это были бы байты, соответствующие следующим инструкциям:```assembly mov r10, rcx mov eax, 50h

root@kitploit:~
Идентификация этих байтов является простой задачей, поскольку мы можем выполнить чистую *diff* как памяти, так и дисковых версий библиотеки, как описано ранее. Затем мы собираем инструкцию перехода, которая создана для перенаправления потока управления на код, следующий сразу за хуком, по адресу `NtProtectVirtualMemory + sizeof(overwritten_instructions)````assembly
jmp NtProtectVirtualMemory+8

Наконец, мы объединяем эти опкоды, сохраняем их в (новую) исполняемую память и сохраняем указатель на них. Этот объект называется "trampoline" и может использоваться как указатель на функцию, строго эквивалентный оригинальной функции NtProtectVirtualMemory.

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

Детали реализации смотрите в коде функции unhook(), когда unhook_method равен UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE. Пожалуйста, помните, что техника только демонстрируется в нашей реализации и, в конечном счёте, используется для удаления хуков из памяти, как и все последующие техники.

Обход хука с использованием собственного трамплина EDR

Чтобы хук работал, продукт EDR должен сохранить где-то в памяти опкоды, которые он удалил. Что ещё хуже (или «лучше» с точки зрения атакующего), для эффективного использования исходных инструкций EDR, вероятно, сам выделил себе trampoline где-то для выполнения оригинальной функции после перехвата вызова.

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

Чтобы найти трамплин в памяти, мы просматриваем всё адресное пространство с помощью VirtualQuery в поисках зафиксированной и исполняемой памяти. Для каждой такой области памяти мы сканируем её в поисках инструкции перехода, которая ведёт на адрес, следующий за перезаписанными инструкциями (NtProtectVirtualMemory+8 в нашем предыдущем примере). Затем трамплин можно использовать для вызова хукируемой функции без активации хука.

Эта техника работает на удивление хорошо, так как позволяет восстановить практически все трамплины на протестированных EDR. Детали реализации смотрите в коде функции unhook(), когда unhook_method равен UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE.

Обход хука с помощью дублированной DLL

Ещё один простой способ получить доступ к немониторируемой версии функции NtProtectVirtualMemory — загрузить дублированную версию библиотеки ntdll.dll в адресное пространство процесса. Так как две одинаковые DLL могут быть загружены в один и тот же процесс при условии, что у них разные имена, мы можем просто скопировать легитимный файл ntdll.dll в другое место, загрузить его с помощью LoadLibrary (или перереализовать процесс загрузки) и получить доступ к функции с помощью, например, GetProcAddress.

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

Тем не менее, эта техника реализована в EDRSandblast. Детали реализации смотрите в коде функции unhook(), когда unhook_method равен UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY.

Обход хука с помощью прямых системных вызовов

Для использования функций, связанных с системными вызовами, программа может перереализовать системные вызовы (на ассемблере), чтобы вызывать соответствующие возможности ОС без фактического обращения к коду в ntdll.dll, который может мониториться EDR. Это полностью обходит любой пользовательский хукинг, выполняемый на функциях системных вызовов в ntdll.dll.

Тем не менее, у этого есть некоторые недостатки. Во-первых, это подразумевает возможность знать список номеров системных вызовов функций, необходимых программе, который меняется для каждой версии Windows. Это, тем не менее, смягчается реализацией нескольких эвристик, которые, как известно, работают во всех прошлых версиях Windows NT (сортировка экспортов Zw* в ntdll, поиск инструкции mov rax, #syscall_number в соответствующей функции ntdll и т.д.), и проверкой того, что все они возвращают один и тот же результат (подробнее см. Syscalls.c).

Кроме того, функции, которые технически не являются системными вызовами (например, LoadLibraryX/LdrLoadDLL), также могут мониториться и не могут быть просто перереализованы с помощью системного вызова.

Техника прямых системных вызовов реализована в EDRSandblast. Как уже упоминалось, она используется только для безопасного выполнения NtProtectVirtualMemory и удаления всех обнаруженных хуков.

Детали реализации смотрите в коде функции unhook(), когда unhook_method равен UNHOOK_WITH_DIRECT_SYSCALL.

Эксплуатация уязвимых драйверов

Как уже упоминалось, каждое действие, требующее чтения или записи в память ядра, основано на уязвимом драйвере, предоставляющем этот примитив. В EDRSandblast добавление поддержки нового драйвера, предоставляющего примитив чтения/записи, может быть выполнено «легко»; нужно реализовать только три функции:

  • Функция ReadMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer), которая копирует Size байтов из адреса ядра Address в буфер пользовательского режима Buffer;
  • Функция WriteMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer), которая копирует Size байтов из буфера пользовательского режима Buffer в адрес ядра Address;
  • Функция CloseDriverHandle_DRIVERNAME(), которая гарантирует закрытие всех дескрипторов драйвера (необходима перед операцией удаления, которая не зависит от драйвера, на данный момент).

В качестве примера, два драйвера в настоящее время поддерживаются EDRSandblast: RTCore64.sys (SHA256: 01AA278B07B58DC46C84BD0B1B5C8E9EE4E62EA0BF7A695862444AF32E87F1FD) и DBUtils_2_3.sys (SHA256: 0296e2ce999e67c76352613a718e11516fe1b0efc3ffdb8918fc999dd76a73a5). Следующий код в KernelMemoryPrimitives.h должен быть обновлён, если используемый уязвимый драйвер необходимо изменить, или если реализован новый.```C #define RTCore 0 #define DBUtil 1 // Select the driver to use with the following #define #define VULN_DRIVER RTCore

#if VULN_DRIVER == RTCore #define DEFAULT_DRIVER_FILE TEXT("RTCore64.sys") #define CloseDriverHandle CloseDriverHandle_RTCore #define ReadMemoryPrimitive ReadMemoryPrimitive_RTCore #define WriteMemoryPrimitive WriteMemoryPrimitive_RTCore #elif VULN_DRIVER == DBUtil #define DEFAULT_DRIVER_FILE TEXT("DBUtil_2_3.sys") #define CloseDriverHandle CloseDriverHandle_DBUtil #define ReadMemoryPrimitive ReadMemoryPrimitive_DBUtil #define WriteMemoryPrimitive WriteMemoryPrimitive_DBUtil #endif

root@kitploit:~
### EDR drivers and processes detection
В настоящее время используется несколько методов для определения, принадлежит ли конкретный драйвер или процесс продукту EDR или нет.

Во-первых, для этой цели можно просто использовать имя драйвера. Действительно, Microsoft выделяет специальные номера, называемые «Altitudes», для всех драйверов, которым необходимо вставлять обратные вызовы в ядро. Это обеспечивает детерминированный порядок выполнения обратных вызовов, независимый от порядка регистрации, а только от использования драйвера. Список (производителей) драйверов, зарезервировавших конкретную *высоту*, можно найти [на MSDN](https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/allocated-altitudes). Как следствие, Microsoft предоставляет практически полный список имен драйверов безопасности, связанных с продуктами безопасности, в основном в списках «FSFilter Anti-Virus» и «FSFilter Activity Monitor». Эти списки имен драйверов встроены в EDRSandblast, а также дополнительные дополнения.

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

Кроме того, драйверы должны быть напрямую подписаны Microsoft, чтобы их можно было загружать в пространство ядра. Хотя поставщик драйвера не является прямым подписантом самого драйвера, похоже, что имя поставщика все же включено в атрибут подписи; тем не менее, этот метод обнаружения еще предстоит исследовать и реализовать.

Наконец, столкнувшись с EDR, неизвестным EDRSandblast, лучший подход — запустить инструмент в режиме «audit» и проверить список драйверов, зарегистрировавших обратные вызовы ядра; затем имя драйвера можно добавить в список, перекомпилировать инструмент и запустить снова.

### RunAsPPL bypass

Механизм `Local Security Authority (LSA) Protection`, впервые представленный в Windows 8.1 и Windows Server 2012 R2, использует технологию `Protected Process Light (PPL)` для ограничения доступа к процессу `LSASS`. Защита `PPL` регулирует и ограничивает такие операции, как внедрение памяти или дамп памяти защищенных процессов, даже для процесса, обладающего привилегией `SeDebugPrivilege`. В модели защиты процессов только процессы, работающие с более высокими уровнями защиты, могут выполнять операции над защищенными процессами.

Структура `_EPROCESS`, используемая ядром Windows для представления процесса в памяти ядра, включает поле `_PS_PROTECTION`, определяющее уровень защиты процесса через его атрибуты `Type` (`_PS_PROTECTED_TYPE`) и `Signer` (`_PS_PROTECTED_SIGNER`).

Записывая в память ядра, процесс EDRSandblast может повысить свой собственный уровень защиты до `PsProtectedSignerWinTcb-Light`. Этого уровня достаточно для дампа памяти процесса `LSASS`, поскольку он «доминирует» над `PsProtectedSignerLsa-Light`, уровнем защиты процесса `LSASS`, работающего с механизмом `RunAsPPL`.

`EDRSandBlast` реализует самозащиту следующим образом:
  - открыть дескриптор текущего процесса
  - утечка всех системных дескрипторов с помощью `NtQuerySystemInformation`, чтобы найти открытый дескриптор текущего процесса и адрес структуры `EPROCESS` текущего процесса в памяти ядра.
  - использовать уязвимость произвольного чтения/записи драйвера `Micro-Star MSI Afterburner` для перезаписи поля `_PS_PROTECTION` текущего процесса в памяти ядра. Смещения поля `_PS_PROTECTION` относительно структуры `EPROCESS` (определенные используемой версией `ntoskrnl`) вычисляются в файле `NtoskrnlOffsets.csv`.

### Credential Guard bypass

Microsoft `Credential Guard` — это технология изоляции на основе виртуализации, представленная в Microsoft `Windows 10 (Enterprise edition)`, которая предотвращает прямой доступ к учетным данным, хранящимся в процессе `LSASS`.

Когда `Credential Guard` активирован, в `Virtual Secure Mode` создается процесс `LSAIso` (*LSA Isolated*), функция, которая использует расширения виртуализации ЦП для обеспечения дополнительной безопасности данных в памяти. Доступ к процессу `LSAIso` ограничен даже для доступа с контекстом безопасности `NT AUTHORITY\SYSTEM`. При обработке хеша процесс `LSA` выполняет вызов `RPC` к процессу `LSAIso` и ожидает результат `LSAIso` для продолжения. Таким образом, процесс `LSASS` не будет содержать никаких секретов и вместо этого будет хранить `LSA Isolated Data`.

Как указано в оригинальном исследовании, проведенном `N4kedTurtle`: «`Wdigest` можно включить в системе с Credential Guard, пропатчив значения `g_fParameter_useLogonCredential` и `g_IsCredGuardEnabled` в памяти». Активация `Wdigest` приведет к хранению учетных данных в открытом виде в памяти `LSASS` для любых новых интерактивных входов в систему (без необходимости перезагрузки системы). Обратитесь к [оригинальной статье в блоге](https://teamhydra.blog/2020/08/25/bypassing-credential-guard/) для получения более подробной информации об этом методе.

`EDRSandBlast` просто делает оригинальный PoC немного более дружественным в плане OpSec и обеспечивает поддержку ряда версий `wdigest.dll` (через вычисленные смещения для `g_fParameter_useLogonCredential` и `g_IsCredGuardEnabled`).

### Offsets retrieval
Для надежного выполнения операций обхода мониторинга ядра EDRSandblast должен точно знать, где читать и писать в память ядра. Это делается с использованием смещений глобальных переменных внутри целевого образа (ntoskrnl.exe, wdigest.dll), а также смещений определенных полей в структурах, определения которых публикуются Microsoft в файлах символов. Эти смещения специфичны для каждой сборки целевых образов и должны быть собраны хотя бы один раз для конкретной версии платформы.

Выбор использования «жестко закодированных» смещений вместо поиска по шаблону для определения структур и переменных, используемых EDRSandblast, оправдан тем, что недокументированные API, отвечающие за добавление/удаление обратных вызовов ядра, могут измениться, и любая попытка чтения или записи в память ядра по неправильному адресу может (и часто будет) приводить к `Bug Check` (`Blue Screen of Death`). Сбой машины неприемлем как в сценариях red-teaming, так и в обычном тестировании на проникновение, поскольку машина, которая вылетает, становится очень заметной для защитников и теряет все учетные данные, которые все еще находились в памяти в момент атаки.

Для получения смещений для каждой конкретной версии Windows реализованы два подхода.

#### Manual offset retrieval
Требуемые смещения `ntoskrnl.exe` и `wdigest.dll` можно извлечь с помощью предоставленного Python-скрипта `ExtractOffsets.py`, который использует `radare2` и `r2pipe` для загрузки и разбора символов из PDB-файлов и извлечения из них необходимых смещений. Затем смещения сохраняются в CSV-файлах для последующего использования EDRSandblast.

Для поддержки из коробки широкого спектра сборок Windows многие версии двоичных файлов `ntoskrnl.exe` и `wdigest.dll` указаны в [Winbindex](https://winbindex.m417z.com/) и могут быть автоматически загружены (и их смещения извлечены) скриптом `ExtractOffsets.py`. Это позволяет извлекать смещения практически из всех файлов, когда-либо опубликованных в пакетах обновлений Windows (на сегодняшний день доступны и предварительно вычислены смещения для более чем 450 версий `ntoskrnl.exe` и более 30 версий `wdigest.dll`).

#### Automatic offsets retrieval and update
В `EDRSandBlast` была реализована дополнительная опция, позволяющая программе самостоятельно загружать необходимые `.pdb` файлы с Microsoft Symbol Server, извлекать требуемые смещения и даже обновлять соответствующие `.csv` файлы, если они присутствуют.

Использование опции `--internet` значительно упрощает выполнение инструмента, но при этом вносит дополнительный риск OpSec, поскольку в процессе загружается и сохраняется на диск файл `.pdb`. Это требуется функциям `dbghelp.dll`, используемым для разбора базы символов; однако в будущем может быть реализован полный разбор PDB в памяти, чтобы устранить это требование и уменьшить след инструмента.

## Usage

Уязвимый драйвер `RTCore64.sys` можно получить по адресу:```
http://download-eu2.guru3d.com/afterburner/%5BGuru3D.com%5D-MSIAfterburnerSetup462Beta2.zip

Быстрое использование```

Usage: EDRSandblast.exe [-h | --help] [-v | --verbose] <audit | dump | cmd | credguard> [--usermode [--unhook-method ]] [--kernelmode] [--dont-unload-driver] [--dont-restore-callbacks] [--driver <RTCore64.sys>] [--service <SERVICE_NAME>] [--nt-offsets <NtoskrnlOffsets.csv>] [--wdigest-offsets <WdigestOffsets.csv>] [--add-dll ]* [-o | --dump-output <DUMP_FILE>]

root@kitploit:~
### Параметры```
-h | --help             Show this help message and exit.
-v | --verbose          Enable a more verbose output.

Actions mode:

        audit           Display the user-land hooks and / or Kernel callbacks without taking actions.
        dump            Dump the LSASS process, by default as 'lsass' in the current directory or at the
                        specified file using -o | --output <DUMP_FILE>.
        cmd             Open a cmd.exe prompt.
        credguard       Patch the LSASS process' memory to enable Wdigest cleartext passwords caching even if
                        Credential Guard is enabled on the host. No kernel-land actions required.

--usermode              Perform user-land operations (DLL unhooking).
--kernelmode            Perform kernel-land operations (Kernel callbacks removal and ETW TI disabling).

--unhook-method <N>
   Choose the userland un-hooking technique, from the following:

        1 (Default)     Uses the (probably monitored) NtProtectVirtualMemory function in ntdll to remove all
                        present userland hooks.
        2               Constructs a 'unhooked' (i.e. unmonitored) version of NtProtectVirtualMemory, by
                        allocating an executable trampoline jumping over the hook, and remove all present
                        userland hooks.
        3               Searches for an existing trampoline allocated by the EDR itself, to get an 'unhooked'
                        (i.e. unmonitored) version of NtProtectVirtualMemory, and remove all present userland
                        hooks.
        4               Loads an additional version of ntdll library into memory, and use the (hopefully
                        unmonitored) version of NtProtectVirtualMemory present in this library to remove all
                        present userland hooks.
        5               Allocates a shellcode that uses a direct syscall to call NtProtectVirtualMemory,
                        and uses it to remove all detected hooks

Other options:

--dont-unload-driver                    Keep the vulnerable driver installed on the host
                                        Default to automatically unsinstall the driver.
--dont-restore-callbacks                Do not restore the EDR drivers' Kernel Callbacks that were removed.
                                        Default to restore the callbacks.

--driver <RTCore64.sys>                 Path to the vulnerable driver file.
                                        Default to 'RTCore64.sys' in the current directory.
--service <SERVICE_NAME>                Name of the vulnerable service to intall / start.

--nt-offsets <NtoskrnlOffsets.csv>      Path to the CSV file containing the required ntoskrnl.exe's offsets.
                                        Default to 'NtoskrnlOffsets.csv' in the current directory.
--wdigest-offsets <WdigestOffsets.csv>  Path to the CSV file containing the required wdigest.dll's offsets
                                        (only for the 'credguard' mode).
                                        Default to 'WdigestOffsets.csv' in the current directory.

--add-dll <dll name or path>            Loads arbitrary libraries into the process' address space, before starting
                                        anything. This can be useful to audit userland hooking for DLL that are not
                                        loaded by default by this program. Use this option multiple times to load
                                        multiple DLLs all at once.
                                        Example of interesting DLLs to look at: user32.dll, ole32.dll, crypt32.dll,
                                        samcli.dll, winhttp.dll, urlmon.dll, secur32.dll, shell32.dll...

-o | --output <DUMP_FILE>               Output path to the dump file that will be generated by the 'dump' mode.
                                        Default to 'lsass' in the current directory.

-i | --internet                         Enables automatic symbols download from Microsoft Symbol Server
                                        If a corresponding *Offsets.csv file exists, appends the downloaded offsets to the file for later use
                                        OpSec warning: downloads and drops on disk a PDB file for ntoskrnl.exe and/or wdigest.dll

Сборка

EDRSandBlast (только x64) был собран в Visual Studio 2019 (Windows SDK Версия: 10.0.19041.0 и набор инструментов платформы: Visual Studio 2019 (v142)).

Использование ExtractOffsets.py

Обратите внимание, что ExtractOffsets.py тестировался только в Windows.```

Installation of Python dependencies

pip.exe install -m .\requirements.txt

Script usage

ExtractOffsets.py [-h] -i INPUT [-o OUTPUT] [-d] mode

positional arguments: mode ntoskrnl or wdigest. Mode to download and extract offsets for either ntoskrnl or wdigest

optional arguments: -h, --help show this help message and exit -i INPUT, --input INPUT Single file or directory containing ntoskrnl.exe / wdigest.dll to extract offsets from. If in download mode, the PE downloaded from MS symbols servers will be placed in this folder. -o OUTPUT, --output OUTPUT CSV file to write offsets to. If the specified file already exists, only new ntoskrnl versions will be downloaded / analyzed. Defaults to NtoskrnlOffsets.csv / WdigestOffsets.csv in the current folder. -d, --download Flag to download the PE from Microsoft servers using list of versions from winbindex.m417z.com.

root@kitploit:~
## Обнаружение
С точки зрения защитника (вендора EDR, Microsoft, SOC-аналитиков, изучающих телеметрию EDR и т.д.) существует множество индикаторов, которые можно использовать для обнаружения или предотвращения подобных техник.

### Белый список драйверов
Поскольку каждое действие, выполняемое инструментом в памяти режима ядра, опирается на уязвимый драйвер для чтения/записи произвольного содержимого, события загрузки драйверов должны тщательно проверяться продуктом EDR (или SOC-аналитиками) и вызывать предупреждение при любой необычной загрузке драйвера или даже блокировать известные уязвимые драйверы. Последний подход даже [рекомендуется самой Microsoft](https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/microsoft-recommended-driver-block-rules): любое устройство Windows с включенным HVCI (*целостность кода, защищенная гипервизором*) содержит список блокировки драйверов, и это постепенно станет поведением по умолчанию в Windows (на Windows 11 это уже так).

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

Как примечание, такого рода структуры данных могут быть защищены с помощью недавнего механизма [Kernel Data Protection (KDP)](https://www.microsoft.com/security/blog/2020/07/08/introducing-kernel-data-protection-a-new-platform-security-technology-for-preventing-data-corruption/), который опирается на виртуальную защиту, чтобы сделать массив обратных вызовов ядра недоступным для записи без вызова соответствующих API.

Та же логика может применяться к чувствительным переменным ETW, таким как `ProviderEnableInfo`, которыми злоупотребляет этот инструмент для отключения генерации событий ETW Threat Intelligence.

### Обнаружение в пользовательском режиме
Первый индикатор того, что процесс активно пытается обойти хуки пользовательского режима — это обращения к файлам каждой DLL, соответствующим загруженным модулям; при нормальном выполнении процессу пользовательского режима редко требуется читать DLL-файлы вне вызова `LoadLibrary`, особенно `ntdll.dll`.

Чтобы защитить API-хуки от обхода, продукты EDR могут периодически проверять, что хуки не изменены в памяти внутри каждого отслеживаемого процесса.

Наконец, для обнаружения обхода хуков (использование трамплина, прямые системные вызовы и т.д.), не подразумевающего удаления хуков, продукты EDR могли бы потенциально полагаться на обратные вызовы ядра, связанные с используемыми системными вызовами (например, `PsCreateProcessNotifyRoutine` для системного вызова `NtCreateProcess`, `ObRegisterCallbacks` для системного вызова `NtOpenProcess` и т.д.) и выполнять анализ стека вызовов пользовательского режима, чтобы определить, был ли системный вызов вызван из обычного пути (`kernel32.dll` -> `ntdll.dll` -> syscall) или аномального (например, `program.exe` -> прямой системный вызов).


## Благодарности

- Перечисление и удаление обратных вызовов ядра:
  https://github.com/br-sn/CheekyBlinder

- Примитивы чтения/записи памяти ядра через уязвимый
  драйвер `Micro-Star MSI Afterburner`:
  https://github.com/Barakat/CVE-2019-16098/

- Отключение провайдера ETW Threat Intelligence:
  https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider

- Установка/удаление драйвера: https://github.com/gentilkiwi/mimikatz

- Первоначальный список имен драйверов EDR:
  https://github.com/SadProcessor/SomeStuff/blob/master/Invoke-EDRCheck.ps1

- Обход Credential Guard путем повторного включения `Wdigest` через патчинг памяти
  `LSASS`: https://teamhydra.blog/2020/08/25/bypassing-credential-guard/


## Авторы

[Thomas DIOT (Qazeer)](https://github.com/Qazeer/)
[Maxime MEIGNAN (themaks)](https://github.com/themaks)

## Лицензия

Лицензия CC BY 4.0 - https://creativecommons.org/licenses/by/4.0/
Скачать инструмент