D2
Администратор
- Регистрация
- 19 Фев 2025
- Сообщения
- 4,380
- Реакции
- 0
Получив доступ к взломанной системе, атакующий первым делом реализует техники уклонения от обнаружения, которые позволяют ослабить мониторинг безопасности инфраструктуры и, как следствие, действовать максимально незаметно.
Сегодня давай разберем ряд техник, которые помогают злоумышленникам обойти расширенный мониторинг. В качестве подопытного инструмента будем использовать Sysmon.
Эта статья логически делится на две части — по источникам информации, на основе которых Sysmon формирует свои события. В первой мы посмотрим, как можно нарушить взаимодействие между драйвером SysmonDrv и службой Sysmon64, во второй — поговорим о воздействии на подсистему ETW. Итак, поехали!
Сегодня мы посмотрим еще пару техник, с помощью которых можно воздействовать на процесс передачи информации от модуля ядра SysmonDrv службе Sysmon64, а соответственно, и на формирование событий безопасности.
Для понимания работы этой техники давай вспомним, как работает инструмент Sysmon. В его состав входят два компонента:
А что будет, если атакующий попытается подменить эту ссылку? Давай посмотрим.
В системе существует специальный вызов DefineDosDevice, который позволяет создавать (и переопределять) символические ссылки на устройства:
Код: Скопировать в буфер обмена
Однако это нужно успеть сделать до того момента, как процесс Sysmon64.exe ее откроет. Для этого вредоносный процесс FakeDosDevice.exe должен быть зарегистрирован в качестве службы, а у сервиса Sysmon64 в зависимостях должна быть указана ссылка на него.
Для регистрации служб есть специальная функция CreateService:
Код: Скопировать в буфер обмена
В этом случае мы можем изменить конфигурацию Sysmon64 напрямую в реестре — добавить ключик DependOnService. Для работы с реестром нам понадобятся две функции: RegCreateKey и RegSetValueEx.
Функция RegCreateKeyA получает доступ к заданной ветке реестра:
Код: Скопировать в буфер обмена
В параметре hKey указываем ветку HKEY_LOCAL_MACHINE. В lpSubKey — путь к параметрам службы Sysmon64:
Код: Скопировать в буфер обмена
В phkResult получаем результат в виде хендла, указывающего на ветку реестра.
Чтобы создать ключ DependOnService, воспользуемся функцией RegSetValueEx:
Код: Скопировать в буфер обмена
В журнале Microsoft-Windows-Sysmon\Operational мы увидим событие аналогичное тому, что было при манипуляциях с дескриптором безопасности.
Сегодня давай посмотрим на такую же технику, но на сей раз попробуем собственноручно подменить хендл объекта
Это можно сделать с помощью вызова NtSuspendProcess(), который на вход принимает единственный аргумент — хендл, указывающий на процесс Sysmon64.exe с маской PROCESS_SUSPEND_RESUME.
Код: Скопировать в буфер обмена
Посмотрим в таблицу хендлов.
Эта операция выполняется с помощью вызова NtQueryInformationProcess, который мы подробно рассматривали в предыдущем материале.
Закрываем хендл устройства \\Device\SysmonDrv (0x32c) и повторно смотрим в таблицу хендлов.
Убеждаемся, что у процесса Sysmon64.exe больше нет дескриптора для устройства \\Device\SysmonDrv.
Хендл закрывается с помощью вызова DuplicateHandle:
Код: Скопировать в буфер обмена
Эта операция выполняется с помощью вызова CreateFile, который мы подробно рассматривали в предыдущем материале.
Делаем инъекцию этого хендла в процесс Sysmon64.
И возобновляем выполнение процесса Sysmon64.exe.

Это делается с помощью вызова NtResumeProcess(), который, как и NtSuspendProcess(), принимает единственный аргумент — хендл процесса с маской PROCESS_SUSPEND_RESUME:
Код: Скопировать в буфер обмена
Давай посмотрим в журнал Microsoft-Windows-Sysmon\Operational.
Видим множество однотипных событий EventID 255 и получаем еще один детект:
Код: Скопировать в буфер обмена
Кроме того, в том же самом материале мы меняли параметры фильтрации для системной сессии NT Kernel Logger, выключая все события. Этот подход относительно незаметен, но он отрубал лишь малую часть событий.
За поведение провайдера «внутри сессии» отвечает структура _TRACE_ENABLE_INFO.
Эта структура содержит два интересных нам параметра, с помощью которых можно «отфильтровать события»: MatchAnyKeyword и MatchAllKeyword. Давай остановимся на них подробнее.
Что же такое кейворды? Каждый провайдер содержит заранее предопределенный перечень событий. Сами по себе события могут быть объединены в группы. А каждой группе можно навесить теги, это и есть кейворды. Этот механизм позволяет делать выборку событий по категориям внутри сессии.
Как говорится в официальной документации, параметр MatchAnyKeyword представляет собой битовую маску, с помощью которой можно определить, какие события будут передаваться в сессию ETW. Причем, чтобы событие провайдера было передано в сессию трассировки, достаточно, чтобы любой из кейвордов был установлен в MatchAnyKeyword. Давай посмотрим это на примере EventID 8 провайдера Microsoft-Windows-Kernel-EventTracing.
На это событие навешано два кейворда — ETW_KEYWORD_PROVIDER и ETW_KEYWORD_REGISTRATION. Таким образом, чтобы оно попало в сессию, в параметре MatchAnyKeyword должны быть установлены в единицу 6-й или 10-й биты. Могут быть установлены как оба бита одновременно — 0x220 (544), так и любой из них в отдельности — 0x200 (512) или 0x20 (32).
Параметр MatchAllKeyword отличается от MatchAnyKeyword тем, что для того, чтобы событие было передано в сессию, должны быть установлены сразу все биты в маске. Для EventID 8 (провайдера Microsoft-Windows-Kernel-EventTracing) параметр MatchAllKeyword должен иметь значение 0x220 (544).
На практике часто значение MatchAllKeyword равно нулю, а параметр MatchAnyKeyword — 0xFFFFFFFF'FFFFFFFF. Это позволяет потреблять все события от провайдера.
Изменить эти параметры из пользовательского пространства можно с помощью вызова EnableTraceEx2:
Код: Скопировать в буфер обмена
Эта сессия потребляет события от одного провайдера — Microsoft-Windows-Sysmon. Причем потребляет все события (параметр MatchAnyKeyword). Давай попробуем изменить этот параметр и посмотрим, что будет.
Команда set manykeyword <SessionHandle> <ProviderGuid> <Bitmask> вызывает функцию EnableTraceEx2() и устанавливает параметр MatchAnyKeyword.
После проделанных манипуляций проверяем журнал Microsoft-Windows-Sysmon\Operational и убеждаемся, что события больше не формируются. При этом сам Sysmon даже никак не оповестил нас об этом.
Давай попробуем изменить параметр MatchAllKeyword.
Повторно смотрим в журнал Sysmon и убеждаемся в отсутствии событий.
На этом, пожалуй, закончим издеваться над Sysmon и пойдем думать о том, как все это детектировать. Спасибо всем, у кого хватило терпения дочитать до конца!
Автор @driverenok, twitter.com/driverenok
Источник xakep.ru
Сегодня давай разберем ряд техник, которые помогают злоумышленникам обойти расширенный мониторинг. В качестве подопытного инструмента будем использовать Sysmon.
Эта статья логически делится на две части — по источникам информации, на основе которых Sysmon формирует свои события. В первой мы посмотрим, как можно нарушить взаимодействие между драйвером SysmonDrv и службой Sysmon64, во второй — поговорим о воздействии на подсистему ETW. Итак, поехали!
ВОЗДЕЙСТВУЕМ НА УСТРОЙСТВО SYSMONDRV
В моем предыдущем материале я рассказывал о том, как ослепить расширенный мониторинг, манипулируя с дескриптором безопасности объекта коммуникационного устройства \\Device\SysmonDrv и провоцируя Sysmon на повторное открытие хендла этого устройства (вызов DuplicateHandle() с опцией DUPLICATE_CLOSE_SOURCE).Сегодня мы посмотрим еще пару техник, с помощью которых можно воздействовать на процесс передачи информации от модуля ядра SysmonDrv службе Sysmon64, а соответственно, и на формирование событий безопасности.
Фейковый DosDevice
Суть этой техники заключается в том, чтобы создать символическую ссылку (симлинк) на коммуникационное устройство \\Device\SysmonDrv раньше, чем это сделает драйвер Sysmon. Успешная эксплуатация позволит атакующему подменить объект коммуникационного устройства и тем самым ослепить Sysmon. Процесс режима пользователя Sysmon64.exe не сможет получать никакую информацию и, как следствие, не будет формировать события.Для понимания работы этой техники давай вспомним, как работает инструмент Sysmon. В его состав входят два компонента:
- Драйвер, который с помощью колбэков и мини‑фильтров отслеживает события, происходящие в системе: создание и завершение процессов, создание файлов, доступ к памяти процесса, создание удаленного потока, загрузку библиотек и другие.
- Служба режима пользователя, которая получает информацию от драйвера SysmonDrv и формирует события безопасности.

А что будет, если атакующий попытается подменить эту ссылку? Давай посмотрим.
В системе существует специальный вызов DefineDosDevice, который позволяет создавать (и переопределять) символические ссылки на устройства:
Код: Скопировать в буфер обмена
Код:
BOOL DefineDosDeviceW(
[in] DWORD dwFlags,
[in] LPCWSTR lpDeviceName,
[in, optional] LPCWSTR lpTargetPath
);
- В параметре dwFlags передаются флаги, контролирующие работу функции. Укажем DDD_NO_BROADCAST_SYSTEM, что будет означать «не сообщать никому об изменении».
- Во втором параметре (lpDeviceName) указываем имя симлинка — SysmonDrv, а в третьем (lpTargetPath) — фейковый путь к устройству (\??\Device\fakedrv).

Однако это нужно успеть сделать до того момента, как процесс Sysmon64.exe ее откроет. Для этого вредоносный процесс FakeDosDevice.exe должен быть зарегистрирован в качестве службы, а у сервиса Sysmon64 в зависимостях должна быть указана ссылка на него.
Для регистрации служб есть специальная функция CreateService:
Код: Скопировать в буфер обмена
Код:
SC_HANDLE CreateServiceA(
[in] SC_HANDLE hSCManager,
[in] LPCSTR lpServiceName,
[in, optional] LPCSTR lpDisplayName,
[in] DWORD dwDesiredAccess,
[in] DWORD dwServiceType,
[in] DWORD dwStartType,
[in] DWORD dwErrorControl,
[in, optional] LPCSTR lpBinaryPathName,
[in, optional] LPCSTR lpLoadOrderGroup,
[out, optional] LPDWORD lpdwTagId,
[in, optional] LPCSTR lpDependencies,
[in, optional] LPCSTR lpServiceStartName,
[in, optional] LPCSTR lpPassword
);
- Первым параметром (hSCManager) передается хендл базы данных диспетчера управления службами. Его можно получить с помощью функции OpenSCManager.
- Второй (lpServiceName) и третий (lpDisplayName) параметры принимают имя регистрируемой службы. Установим их равными FakeDosDevice.
- Так как вызов CreateService возвращает хендл на созданную службу, с которым можно работать дальше, а сама служба — это объект ядра, в четвертом параметре (dwDesiredAccess) передается запрашиваемый доступ.
- Далее мы указываем тип службы — SERVICE_WIN32_OWN_PROCESS (параметр dwServiceType).
- С помощью параметра dwStartType указываем тип автозапуска. В нашем случае он равен SERVICE_AUTO_START.
- В параметре dwErrorControl передается уровень критичности и действие в случае ошибки (SERVICE_ERROR_NORMAL).
- В конце (lpBinaryPathName) указываем путь к исполняемому файлу FakeDosDevice.exe, получаемый динамически с помощью функции QueryFullProcessImageName.
- Оставшиеся параметры установим в NULL.

В этом случае мы можем изменить конфигурацию Sysmon64 напрямую в реестре — добавить ключик DependOnService. Для работы с реестром нам понадобятся две функции: RegCreateKey и RegSetValueEx.
Функция RegCreateKeyA получает доступ к заданной ветке реестра:
Код: Скопировать в буфер обмена
Код:
LSTATUS RegCreateKeyA(
[in] HKEY hKey,
[in, optional] LPCSTR lpSubKey,
[out] PHKEY phkResult
);
Код: Скопировать в буфер обмена
SYSTEM\CurrentControlSet\Services\Sysmon64\
В phkResult получаем результат в виде хендла, указывающего на ветку реестра.
Чтобы создать ключ DependOnService, воспользуемся функцией RegSetValueEx:
Код: Скопировать в буфер обмена
Код:
LSTATUS RegSetValueExA(
[in] HKEY hKey,
[in, optional] LPCSTR lpValueName,
DWORD Reserved,
[in] DWORD dwType,
[in] const BYTE *lpData,
[in] DWORD cbData
);
- С помощью параметра hKey передаем хендл на ранее открытую ветку реестра.
- Во втором параметре (lpValueName) указываем имя нового ключа — DependOnService.
- В dwType — его тип (REG_MULTI_SZ).
- В параметре lpData передаем указатель на буфер данных, которые будут использованы как значение ключа реестра.
- Последним параметром (cbData) передаем размер передаваемого буфера.
В журнале Microsoft-Windows-Sysmon\Operational мы увидим событие аналогичное тому, что было при манипуляциях с дескриптором безопасности.

Подмена хендла SysmonDrv
В прошлом материале мы изменяли дескриптор безопасности устройства\\Device\SysmonDrv
и заставляли Sysmon повторно получать хендл, указывающий на это устройство (благо такая возможность есть в коде самого Sysmon).Сегодня давай посмотрим на такую же технику, но на сей раз попробуем собственноручно подменить хендл объекта
\\Device\SysmonDrv
. Эта техника носит название Handle Hijacking и подробно описана в статье на «Хакере». Кратко напомню алгоритм действий:- Приостанавливаем выполнение процесса с помощью вызова NtSuspendProcess().
- С помощью функции NtQueryInformationProcess() получаем таблицу хендлов процесса Sysmon64.exe.
- Закрываем хендл на устройство с помощью вызова DuplicateHandle.
- С помощью CreateFile() получаем описатель для устройства
\\Device\Tcp
(устройство может быть любым, отличным от SysmonDrv). - Внедряем новый описатель в процесс Sysmon, повторно вызывая DuplicateHandle(), и возобновляем его работу NtResumeProcess().

Это можно сделать с помощью вызова NtSuspendProcess(), который на вход принимает единственный аргумент — хендл, указывающий на процесс Sysmon64.exe с маской PROCESS_SUSPEND_RESUME.
Код: Скопировать в буфер обмена
Код:
NTSTATUS NTAPI NtSuspendProcess(
IN HANDLE ProcessHandle
);

Эта операция выполняется с помощью вызова NtQueryInformationProcess, который мы подробно рассматривали в предыдущем материале.
Закрываем хендл устройства \\Device\SysmonDrv (0x32c) и повторно смотрим в таблицу хендлов.

Убеждаемся, что у процесса Sysmon64.exe больше нет дескриптора для устройства \\Device\SysmonDrv.
Хендл закрывается с помощью вызова DuplicateHandle:
Код: Скопировать в буфер обмена
Код:
BOOL DuplicateHandle(
[in] HANDLE hSourceProcessHandle,
[in] HANDLE hSourceHandle,
[in] HANDLE hTargetProcessHandle,
[out] LPHANDLE lpTargetHandle,
[in] DWORD dwDesiredAccess,
[in] BOOL bInheritHandle,
[in] DWORD dwOptions
);
- Параметр hSourceProcessHandle принимает хендл процесса, из которого происходит копирование хендла. Доступ к процессу должен быть получен по маске PROCESS_DUP_HANDLE.
- В параметре hSourceHandle передается хендл устройства \\Device\SysmonDrv, который был получен на предыдущем шаге (с помощью вызова NtQueryInformationProcess()).
- Третьим (hTargetProcessHandle) передается хендл текущего процесса, получаемый с помощью GetCurrentProcess().
- В четвертом параметре (lpTargetHandle) передаем указатель на переменную типа HANDLE, в которую будет помещен скопированный хендл.
- И последним параметром (dwOptions) передаем опцию копирования DUPLICATE_CLOSE_SOURCE, которая указывает на необходимость закрыть исходный хендл после копирования («закрыть исходный хендл в процессе Sysmon»).

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

И возобновляем выполнение процесса Sysmon64.exe.

Это делается с помощью вызова NtResumeProcess(), который, как и NtSuspendProcess(), принимает единственный аргумент — хендл процесса с маской PROCESS_SUSPEND_RESUME:
Код: Скопировать в буфер обмена
Код:
NTSTATUS NTAPI NtResumeProcess(
IN HANDLE ProcessHandle
);

Видим множество однотипных событий EventID 255 и получаем еще один детект:
Код: Скопировать в буфер обмена
Provider.Name='Microsoft-Windows-Sysmon' and EventID='255' and EventData.ID= 'DriverCommunication' and EventData.Description='Failed to retrieve events - Last error: Параметр задан неверно.'
МАНИПУЛЯЦИИ С ETW
В одной из предыдущих статей мы меняли дескриптор безопасности на сессию сбора событий. Это позволяло полностью ослепить Sysmon, однако в оснастке «Просмотр событий» появлялось явное свидетельство того, что происходит что‑то неладное.Кроме того, в том же самом материале мы меняли параметры фильтрации для системной сессии NT Kernel Logger, выключая все события. Этот подход относительно незаметен, но он отрубал лишь малую часть событий.
Изменяем параметры отбора событий провайдера
Давай теперь посмотрим, как можно фильтровать (отбирать) события, формируемые провайдерами, на уровне сессий ETW. Эта техника позволит ослепить Sysmon без каких‑либо свидетельств в журнале Microsoft-Windows-Sysmon\Operational и дополнительных перезагрузок системы.За поведение провайдера «внутри сессии» отвечает структура _TRACE_ENABLE_INFO.

Эта структура содержит два интересных нам параметра, с помощью которых можно «отфильтровать события»: MatchAnyKeyword и MatchAllKeyword. Давай остановимся на них подробнее.
Что же такое кейворды? Каждый провайдер содержит заранее предопределенный перечень событий. Сами по себе события могут быть объединены в группы. А каждой группе можно навесить теги, это и есть кейворды. Этот механизм позволяет делать выборку событий по категориям внутри сессии.
Как говорится в официальной документации, параметр MatchAnyKeyword представляет собой битовую маску, с помощью которой можно определить, какие события будут передаваться в сессию ETW. Причем, чтобы событие провайдера было передано в сессию трассировки, достаточно, чтобы любой из кейвордов был установлен в MatchAnyKeyword. Давай посмотрим это на примере EventID 8 провайдера Microsoft-Windows-Kernel-EventTracing.

На это событие навешано два кейворда — ETW_KEYWORD_PROVIDER и ETW_KEYWORD_REGISTRATION. Таким образом, чтобы оно попало в сессию, в параметре MatchAnyKeyword должны быть установлены в единицу 6-й или 10-й биты. Могут быть установлены как оба бита одновременно — 0x220 (544), так и любой из них в отдельности — 0x200 (512) или 0x20 (32).
Параметр MatchAllKeyword отличается от MatchAnyKeyword тем, что для того, чтобы событие было передано в сессию, должны быть установлены сразу все биты в маске. Для EventID 8 (провайдера Microsoft-Windows-Kernel-EventTracing) параметр MatchAllKeyword должен иметь значение 0x220 (544).
На практике часто значение MatchAllKeyword равно нулю, а параметр MatchAnyKeyword — 0xFFFFFFFF'FFFFFFFF. Это позволяет потреблять все события от провайдера.
Изменить эти параметры из пользовательского пространства можно с помощью вызова EnableTraceEx2:
Код: Скопировать в буфер обмена
Код:
ULONG WMIAPI EnableTraceEx2(
[in] TRACEHANDLE TraceHandle,
[in] LPCGUID ProviderId,
[in] ULONG ControlCode,
[in] UCHAR Level,
[in] ULONGLONG MatchAnyKeyword,
[in] ULONGLONG MatchAllKeyword,
[in] ULONG Timeout,
[in, optional] PENABLE_TRACE_PARAMETERS EnableParameters
);
- В параметр TraceHandle передается хендл сессии трассировки.
- Второй параметр (ProviderId) принимает GUID провайдера.
- С помощью ControlCode указываем на необходимость изменить параметры работы провайдера (EVENT_CONTROL_CODE_ENABLE_PROVIDER).
- В параметрах MatchAnyKeyword и MatchAllKeyword указываем требуемый уровень выборки событий провайдера.

Эта сессия потребляет события от одного провайдера — Microsoft-Windows-Sysmon. Причем потребляет все события (параметр MatchAnyKeyword). Давай попробуем изменить этот параметр и посмотрим, что будет.

Команда set manykeyword <SessionHandle> <ProviderGuid> <Bitmask> вызывает функцию EnableTraceEx2() и устанавливает параметр MatchAnyKeyword.
После проделанных манипуляций проверяем журнал Microsoft-Windows-Sysmon\Operational и убеждаемся, что события больше не формируются. При этом сам Sysmon даже никак не оповестил нас об этом.
Давай попробуем изменить параметр MatchAllKeyword.

Повторно смотрим в журнал Sysmon и убеждаемся в отсутствии событий.
На этом, пожалуй, закончим издеваться над Sysmon и пойдем думать о том, как все это детектировать. Спасибо всем, у кого хватило терпения дочитать до конца!
Автор @driverenok, twitter.com/driverenok
Источник xakep.ru