HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Уязвимости
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 15.04.2026, 12:30
Сергей Попов
Новичок
Регистрация: 14.08.2015
Сообщений: 0
С нами: 5656404

Репутация: 0
По умолчанию



Антивирус говорит «система чиста», а сетевой трафик тем временем утекает на подозрительный C2-сервер. Знакомая картина? Значит, вы наткнулись на kernel-mode руткит. Не на ту поделку, что прячет файлы через перехват FindFirstFile в user-mode, а на зверя, который работает на одном уровне привилегий с самой ОС и напрямую ковыряет структуру ядра.

По данным Positive Technologies, руткиты - меньше 1% от всех вредоносных программ. Но каждый такой случай - это серьёзный инцидент: APT-кампании, скрытый майнинг на десятках тысяч машин. Причина простая: руткит режима ядра - верхняя точка эскалации, после которой атакующий контролирует всё, что видит (и чего не видит) операционная система.

В MITRE ATT&CK руткиты описаны как техника T1014 (Rootkit). Но реальный руткит - это не одна техника, а комбо (полную классификацию с матрицей обнаружения см. в обзоре техник руткитов): DKOM для скрытия процессов, SSDT hooking для перехвата системных вызовов, minifilter-драйверы для фильтрации файлового I/O и манипуляции с kernel callbacks, чтобы ослепить средства защиты (T1562.001, Disable or Modify Tools). Дальше разберём каждую из этих техник на уровне структур ядра Windows и покажем, как их ловить с помощью WinDbg и Volatility - не по туториалу из первой ссылки в Google, а по реальной методологии анализа.
DKOM атака Windows: как работает скрытие процессов через ActiveProcessLinks
DKOM (Direct Kernel Object Manipulation) - классика kernel-mode руткитов. Атакующий напрямую правит структуры данных ядра без штатных API. Самый ходовой сценарий - скрытие процесса через удаление из двусвязного списка
Код:
ActiveProcessLinks
.
Механика на уровне ядра
Каждый процесс в Windows представлен структурой
Код:
EPROCESS
. Эти структуры связаны через поле
Код:
ActiveProcessLinks
- элемент типа
Код:
LIST_ENTRY
с указателями
Код:
Flink
(forward link, на следующий процесс) и
Код:
Blink
(backward link, на предыдущий). Главный списка - глобальная переменная ядра
Код:
PsActiveProcessHead
.

Когда диспетчер задач или Process Explorer запрашивают список процессов через
Код:
NtQuerySystemInformation
, ядро обходит именно этот список. Руткит делает классическое удаление узла из двусвязного списка:

Код:


Код:
// Концептуальный псевдокод DKOM-скрытия
// Для демонстрации механизма - не рабочий эксплойт

PEPROCESS targetProcess;  // EPROCESS скрываемого процесса
PLIST_ENTRY prevEntry = targetProcess->ActiveProcessLinks.Blink;
PLIST_ENTRY nextEntry = targetProcess->ActiveProcessLinks.Flink;

// Перелинковка: предыдущий указывает на следующий, минуя целевой
prevEntry->Flink = nextEntry;
nextEntry->Blink = prevEntry;

// Замыкаем ссылки скрытого процесса на самого себя
targetProcess->ActiveProcessLinks.Flink = &targetProcess->ActiveProcessLinks;
targetProcess->ActiveProcessLinks.Blink = &targetProcess->ActiveProcessLinks;
После этой операции процесс продолжает работать - планировщик ядра использует другие структуры для переключения потоков - но становится невидимкой для любого инструмента, работающего через
Код:
PsActiveProcessHead
. Именно так работали руткиты FU и его потомки.

Нюанс: DKOM не ограничивается процессами. Та же техника применяется к спискам драйверов (
Код:
PsLoadedModuleList
), потокам и другим объектам ядра. По MITRE ATT&CK скрытие объектов ядра через DKOM - это T1014 (Rootkit) и более общая T1564 (Hide Artifacts).
Обнаружение DKOM в WinDbg
Первый шаг - получить список процессов двумя независимыми способами и сравнить. В WinDbg в kernel-mode сессии:

Код:


Код:
kd> !process 0 0
Эта команда обходит
Код:
PsActiveProcessHead
- тот самый список, из которого DKOM удаляет записи. Скрытый процесс здесь не всплывёт.

Теперь сравним с другим источником - пулом памяти ядра. Каждый
Код:
EPROCESS
распределён из nonpaged pool с тегом
Код:
Proc
:

Код:


Код:
kd> !poolfind Proc 0
Если pool scan находит
Код:
EPROCESS
-блок, чей PID отсутствует в выводе
Код:
!process 0 0
- это прямой индикатор DKOM. Имейте в виду:
Код:
!poolfind
может молотить десятки минут на больших дампах. На Windows 10 19H1+ (build 18362) и новее с segment heap pool scanning через
Код:
!poolfind
менее надёжен (можно предварительно проверить наличие тега через
Код:
!poolused Proc
) - в таких случаях лучше использовать
Код:
psscan
в Volatility. Также полезно проверить структуру конкретного подозрительного процесса:

Код:


Код:
kd> dt nt!_EPROCESS
Смотрим поля
Код:
ActiveProcessLinks.Flink
и
Код:
ActiveProcessLinks.Blink
- если оба указывают на саму структуру (замкнуты на себя), процесс был unlinkован из списка. Это как отпечаток пальца на месте преступления.

Для проверки целостности цепочки можно пройти весь список вручную:

Код:


Код:
kd> dl nt!PsActiveProcessHead 200 2
Команда
Код:
dl
проходит по двусвязному списку. Если при обходе вперёд и назад получаем разное количество элементов - список повреждён, что тоже указывает на DKOM.
Обнаружение DKOM в Volatility
Volatility решает проблему обнаружения DKOM через кросс-валидацию - сравнение разных источников информации о процессах. Ключевой плагин -
Код:
psxview
(только в Volatility 2). В Volatility 3 встроенного аналога нет - кросс-валидация делается вручную через сравнение выводов
Код:
windows.pslist
и
Код:
windows.psscan
.

Bash:


Код:
# Volatility 2
python vol.py -f memory.dmp --profile
=
Win10x64 psxview
# Volatility 3
python vol.py -f memory.dmp windows.pslist
python vol.py -f memory.dmp windows.psscan
Код:
psxview
сравнивает результаты из нескольких источников:

ИсточникЧто проверяетОбходится DKOMPsActiveProcessHeadДвусвязный список EPROCESSДаETHREAD scanningПотоки, ссылающиеся на процессНетPool tag scanning (psscan)Сигнатуры EPROCESS в памятиНетPspCidTableТаблица объектов по PID/TIDЧастичноCsrss handlesХэндлы csrss.exe к процессамЧастичноSession listСписок процессов в сессииЧастично

Если процесс виден в
Код:
psscan
(сканирование пула), но отсутствует в
Код:
pslist
(обход
Код:
ActiveProcessLinks
) - перед вами DKOM. Классический паттерн: в столбце
Код:
pslist
значение False, а в
Код:
psscan
- True. Лично у меня это был самый частый способ обнаружения - просто diff двух выводов.

Bash:


Код:
# Прямое сравнение двух плагинов
python vol.py -f memory.dmp windows.pslist
>
pslist_output.txt
python vol.py -f memory.dmp windows.psscan
>
psscan_output.txt
# Любой PID из psscan, отсутствующий в pslist - кандидат на DKOM
SSDT hooking rootkit: перехват таблицы системных вызовов
SSDT (System Service Descriptor Table) - таблица с адресами обработчиков системных вызовов ядра. Когда user-mode код вызывает
Код:
NtCreateFile
, процессор через
Код:
syscall
/
Код:
sysenter
переходит в kernel-mode, где диспетчер
Код:
KiSystemService
использует номер системного вызова как индекс в SSDT для вызова нужной функции. В MITRE ATT&CK SSDT hooking описывается техникой T1014 (Rootkit), тактика Defense Evasion. Примечание: тесты Atomic Red Team для T1014 есть только для Linux; на Windows валидация требует других подходов. Ранее существовала техника T1179 (Hooking), покрывавшая Persistence, Privilege Escalation и Credential Access, но её отозвали (deprecated) начиная с ATT&CK v8 (октябрь 2020); часть функциональности мигрировала в T1056.004 (Credential API Hooking) и другие суб-техники.
Механика SSDT hook
Руткит подменяет адрес в таблице SSDT, заставляя ядро вызывать свой обработчик вместо оригинального. Через это можно перехватить что угодно: скрывать файлы через хук
Код:
NtQueryDirectoryFile
, процессы через хук
Код:
NtQuerySystemInformation
, сетевые соединения через хук
Код:
NtDeviceIoControlFile
.

На современных 64-битных Windows SSDT хранит не абсолютные адреса, а относительные смещения. Каждая запись - 4-байтовое значение, где верхние 28 бит - смещение от базы
Код:
KeServiceDescriptorTable
, а нижние 4 бита - количество аргументов, передаваемых через стек. Это усложняет hooking по сравнению с 32-битными системами, но не делает его невозможным.

На 64-битных Windows с активным PatchGuard (Kernel Patch Protection) прямая модификация SSDT вызывает BSOD с кодом
Код:
CRITICAL_STRUCTURE_CORRUPTION
. Однако техники обхода PatchGuard задокументированы, и некоторые руткиты - Turla, FiveSys - успешно их применяли. PatchGuard проверяет целостность периодически, а не в реальном времени, что создаёт окно для атаки. Так-что не стоит считать его непробиваемым щитом.
Обнаружение SSDT hooking через WinDbg
Смотрим базу SSDT и проверяем, что все адреса указывают внутрь ntoskrnl.exe:

Код:


Код:
kd> dps nt!KiServiceTable L 0x200
Команда выведет таблицу с адресами и символами. Все записи должны резолвиться (DNS resolution) в функции
Код:
nt!Nt*
. Если какая-то запись указывает на адрес вне диапазона ntoskrnl - это хук, и тут уже пора напрягаться.

Проверяем диапазон ntoskrnl:

Код:


Код:
kd> lm m nt
Запоминаем Start и End адреса. Любой адрес в SSDT, выходящий за этот диапазон, - аномалия. На 64-битных системах с относительными смещениями:

Код:


Код:
kd> dd nt!KiServiceTable L 0x10
Каждое 4-байтовое значение - relative offset. Для преобразования в абсолютный адрес:
Код:
базовый_адрес + (offset >> 4)
. Если результат выходит за пределы ntoskrnl - хук.

Для проверки конкретного системного вызова, например
Код:
NtCreateFile
(syscall номер зависит от версии Windows):

Код:


Код:
kd> u nt!NtCreateFile
Если первые инструкции содержат
Код:
jmp
на адрес вне ntoskrnl - это inline hook. Ещё один вариант перехвата, при котором сама SSDT не тронута, но код функции подменён. Хитрее, но и обнаруживается несложно.
Обнаружение SSDT hooks в Volatility

Bash:


Код:
# Volatility 2
python vol.py -f memory.dmp --profile
=
Win10x64 ssdt
# Volatility 3
python vol.py -f memory.dmp windows.ssdt
Плагин
Код:
ssdt
выводит каждую запись SSDT с resolved символами. Ключевой индикатор: если функция резолвится не в
Код:
ntoskrnl.exe
или
Код:
win32k.sys
(для Shadow SSDT), а в неизвестный модуль или адрес вообще без модуля - это hooking.

Код:


Код:
# Пример подозрительного вывода (для демонстрации концепции)
Entry 0x0049: 0xfffff880012345678  unknown_driver.sys!HookedNtQueryDirectoryFile
Нормальные записи выглядят так:

Код:


Код:
Entry 0x0049: 0xfffff80001234567  ntoskrnl.exe!NtQueryDirectoryFile
Minifilter driver abuse: невидимая фильтрация файловых операций
Minifilter-драйверы - легитимный фреймворк Windows (Filter Manager,
Код:
fltmgr.sys
) для перехвата файловых операций ввода-вывода. Антивирусы, DLP-системы, средства шифрования - все используют minifilter для сканирования файлов на лету. Но тот же механизм с удовольствием эксплуатируют руткиты.
Как работает minifilter
Filter Manager организует minifilter-драйверы в стек по altitude - числовому значению, определяющему приоритет обработки. Антивирусные фильтры обычно имеют altitude 320000–329999, фильтры шифрования - 140000–149999. Каждый minifilter регистрирует callback-функции для конкретных операций (Pre-Operation и Post-Operation): создание файла, чтение, запись, запрос директории.

Вредоносный minifilter может:
  • Скрывать файлы руткита, фильтруя результаты
    Код:
    IRP_MJ_DIRECTORY_CONTROL
  • Блокировать доступ антивируса к вредоносным файлам через
    Код:
    IRP_MJ_CREATE
  • Подменять содержимое файлов при чтении через
    Код:
    IRP_MJ_READ
  • Перехватывать и эксфильтровать записываемые данные
По MITRE ATT&CK это связано с T1547.006 (Kernel Modules and Extensions) - сохранение состояния системы с помощью драйвера, T1014 (Rootkit) - скрытие файлов через minifilter callbacks, и T1562.001 (Disable or Modify Tools) - блокировка доступа антивируса к вредоносным файлам.
Обнаружение вредоносных minifilter-драйверов
В WinDbg проверяем загруженные minifilter-драйверы:

Код:


Код:
kd> !fltkd.filters
Расширение
Код:
!fltkd
даёт полный доступ к внутренним структурам Filter Manager. Команда выведет все зарегистрированные фильтры с их altitude и количеством зарегистрированных операций.

Код:


Код:
kd> !fltkd.frames
Показывает фреймы Filter Manager и все присоединённые фильтры. На что смотреть:
  • Фильтры с необычными именами или без цифровой подписи
  • Фильтры с altitude, не соответствующим их заявленному назначению (антивирус с altitude шифровальщика - подозрительно)
  • Фильтры, зарегистрировавшие callbacks для
    Код:
    IRP_MJ_DIRECTORY_CONTROL
    или
    Код:
    IRP_MJ_CREATE
    - именно они используются для скрытия файлов
Для проверки конкретного фильтра:

Код:


Код:
kd> !fltkd.filter
Покажет все зарегистрированные Pre/Post callback-функции. Адрес каждого callback должен резолвиться в известный модуль.

В Volatility minifilter-анализ доступен через плагин
Код:
driverirp
и анализ загруженных модулей:

Bash:


Код:
# driverirp -r fltmgr показывает IRP dispatch table самого fltmgr.sys,
# а НЕ callback-функции зарегистрированных minifilter-драйверов.
# Для анализа minifilter-стека используйте WinDbg с !fltkd.filters.
python vol.py -f memory.dmp --profile
=
Win10x64 driverirp -r
"fltmgr"
Для обнаружения скрытых minifilter-драйверов через Volatility используйте
Код:
driverscan
и
Код:
modscan
- они находят драйверы, скрытые из штатного списка загруженных модулей (
Код:
PsLoadedModuleList
), но всё ещё присутствующие в памяти. Для полного анализа minifilter-стека (зарегистрированные callback-функции, altitude, перехватываемые операции) основной метод - WinDbg с расширением
Код:
!fltkd.filters
; в продвинутых случаях возможен ручной анализ структур
Код:
FLT_FILTER
в дампе памяти, но это уже для любителей острых ощущений.
Kernel callback manipulation: нейтрализация защитных механизмов
Ядро Windows предоставляет набор notification callback-механизмов, которые средства защиты используют для мониторинга системных событий. Руткиты манипулируют этими callback-таблицами, чтобы «ослепить» антивирусы и EDR.
Целевые callback-механизмы

CallbackФункция регистрацииНазначениеProcess creationPsSetCreateProcessNotifyRoutine(Ex)Уве омление о создании/завершении процессовThread creationPsSetCreateThreadNotifyRoutineУведом ление о создании потоковImage loadPsSetLoadImageNotifyRoutineУведомлен е о загрузке образов (DLL, EXE)RegistryCmRegisterCallbackExУведомлен ие об операциях с реестромObject accessObRegisterCallbacksФильтрация доступа к объектам (процессам, потокам)

EDR-решения регистрируют свои callback-функции через эти API. Руткит может:
  1. Удалить callback из массива (по аналогии с DKOM - unlinking)
  2. Подменить адрес callback-функции на заглушку, которая тупо ничего не делает
  3. Пропатчить код самой callback-функции (inline hook), заставляя её сразу возвращать управление
Это прямая реализация техники Disable or Modify Tools (T1562.001, Defense Evasion) - атакующий не уничтожает средство защиты, а тихо выключает ему глаза и уши.
Обнаружение callback-манипуляций в WinDbg
Проверяем массив notification routines для процессов:

Код:


Код:
kd> dt nt!_EX_CALLBACK_ROUTINE_BLOCK
Для проверки зарегистрированных Process notification callbacks:

Код:


Код:
kd> x nt!PspCreateProcessNotifyRoutine
kd> dps nt!PspCreateProcessNotifyRoutine L 0x40
Каждый ненулевой элемент - указатель на
Код:
EX_CALLBACK_ROUTINE_BLOCK
. Значения должны резолвиться в известные модули защитных средств. Если слот обнулён или указывает на неизвестный модуль - callback был удалён или подменён. Вот тут-то и начинается самое интересное.

Аналогично для потоков и загрузки образов:

Код:


Код:
kd> dps nt!PspLoadImageNotifyRoutine L 0x40
kd> dps nt!PspCreateThreadNotifyRoutine L 0x40
Для ObRegisterCallbacks проверка сложнее - нужно пройти по списку
Код:
ObTypeInitializer
для объектов типа
Код:
Process
и
Код:
Thread
:

Код:


Код:
kd> !object \ObjectTypes\Process
kd> dt nt!_OBJECT_TYPE  -r1
Обнаружение через Volatility

Bash:


Код:
# Volatility 2
python vol.py -f memory.dmp --profile
=
Win10x64 callbacks
# Volatility 3
python vol.py -f memory.dmp windows.callbacks
Плагин
Код:
callbacks
покажет все зарегистрированные kernel notification callbacks с указанием модуля-владельца. Красные флаги:
  • Callback, принадлежащий неизвестному или неподписанному модулю
  • Отсутствие callbacks от EDR, который точно установлен на системе (EDR есть, а его callbacks нет - значит, кто-то их вычистил)
  • Callback-функция в области памяти без привязки к модулю - это шеллкод
Практический workflow обнаружения руткитов Windows
Ниже - пошаговая методология для реального дампа памяти подозрительной системы. Последовательность выстроена так, чтобы каждый шаг сужал область поиска.
Шаг 1: Снятие дампа памяти
Используем WinPmem или DumpIt для получения raw memory dump. Если подозревается руткит - не доверяйте инструментам, работающим из-под скомпрометированной системы. Идеально - DMA-устройство (PCILeech) или дамп через гипервизор. На практике часто приходится довольствоваться WinPmem с USB-носителя - не идеал, но лучше, чем ничего.

Bash:


Код:
# WinPmem (запуск с USB-носителя)
winpmem_mini_x64.exe output.raw
Шаг 2: Кросс-валидация списков процессов

Bash:


Код:
python vol.py -f output.raw windows.pslist
>
step2_pslist.txt
python vol.py -f output.raw windows.psscan
>
step2_psscan.txt
Сравниваем PID из обоих файлов. Любое расхождение - первый индикатор DKOM.
Шаг 3: Проверка SSDT и драйверов

Bash:


Код:
python vol.py -f output.raw windows.ssdt
>
step3_ssdt.txt
python vol.py -f output.raw windows.modules
>
step3_modules.txt
python vol.py -f output.raw windows.driverscan
>
step3_drivers.txt
В выводе
Код:
ssdt
все записи должны указывать на
Код:
ntoskrnl.exe
или
Код:
win32k.sys
. В
Код:
driverscan
ищем драйверы, отсутствующие в
Код:
modules
(аналог DKOM, только для модулей).
Шаг 4: Анализ callbacks

Bash:


Код:
python vol.py -f output.raw windows.callbacks
>
step4_callbacks.txt
Проверяем наличие callbacks от установленных защитных средств. Если EDR установлен, но его callbacks отсутствуют - руткит их вычистил.
Шаг 5: Углублённый анализ в WinDbg
Если на шагах 2-4 обнаружены аномалии, открываем дамп в WinDbg для детальной процедуры:

Код:


Код:
kd> .sympath srv*c:\symbols*https://msdl.microsoft.com/download/symbols
kd> .reload /f

;// Проверяем подозрительный процесс из psscan
kd> dt nt!_EPROCESS 
kd> !process  7

;// Смотрим потоки скрытого процесса
kd> !process  4
Поле
Код:
ActiveProcessLinks
у скрытого процесса покажет замкнутые на себя указатели. Поле
Код:
ImageFileName
- имя исполняемого файла руткита.
Шаг 6: Восстановление полной картины
Для каждого обнаруженного артефакта фиксируем:
  • PID и имя скрытого процесса
  • Загруженные им модули (
    Код:
    !process  7
    покажет VAD-дерево)
  • Сетевые соединения (
    Код:
    windows.netscan
    в Volatility)
  • Файлы, открытые процессом (
    Код:
    windows.handles
    )
PatchGuard и современные ограничения руткитов
На 64-битных Windows PatchGuard (Kernel Patch Protection) защищает критические структуры ядра: SSDT, GDT, IDT, системные образы, структуры объектов процессов. Периодические проверки целостности вызывают BSOD при обнаружении модификаций.

Классический SSDT hooking на современных 64-битных Windows - техника с высоким риском словить BSOD. Поэтому современные руткиты смещают фокус:
  • Minifilter-драйверы - легитимный механизм, PatchGuard не проверяет
  • Callback-манипуляции - менее заметны, чем прямые модификации SSDT
  • DKOM с осторожным восстановлением после проверок PatchGuard
  • Обход через уязвимости в подписанных драйверах (BYOVD - Bring Your Own Vulnerable Driver)
Руткит FiveSys использовал украденную цифровую подпись Microsoft WHQL, что позволяло ему загружаться как легитимный драйвер и обходить проверки целостности. Это наглядно показывает, что даже PatchGuard и DSE (Driver Signature Enforcement) - не абсолютная защита. На заборе тоже написано «защищено», а на деле..
Что упускают стандартные средства защиты
Большинство антивирусов работают в user-mode или используют ограниченный набор kernel callbacks. Kernel-mode руткит, работающий на том же уровне привилегий, может:
  • Скрыть свой процесс через DKOM - антивирус не увидит его в списке процессов
  • Удалить callbacks антивируса - тот перестанет получать уведомления о событиях
  • Зарегистрировать minifilter с более высоким altitude - обработать запрос к файлу раньше, чем до него доберётся антивирус
Именно поэтому для обнаружения kernel-mode руткитов нужен офлайн-анализ памяти через Volatility или анализ через отладчик ядра (WinDbg) - подходы, которые работают извне скомпрометированного ядра и не зависят от API, которые руткит может контролировать.

Rootkit обнаружение Windows - это всегда комбинация: кросс-валидация (сравнение нескольких источников данных о процессах), проверка целостности критических структур (SSDT, callback-массивы) и анализ загруженных драйверов (minifilter-стек, неподписанные модули). Ни один инструмент не ловит всё - поэтому WinDbg и Volatility работают в паре, компенсируя ограничения друг друга. Попробуйте прогнать свой дамп по workflow из шагов 1-6 - даже на «чистой» системе результаты бывают... познавательными.
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.