Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
Помогли мы вам |
С появлением KPP (Kernel Patch Protection), или сокращенно PatchGuard, в Windows стало сложнее модифицировать ядро без последствий. Если раньше, например, таблицу системных вызовов с целью фильтрации системных вызовов перехватывали даже такие легитимные программы, как антивирусы, то с появлением KPP это стало не так просто. Тем не менее для руткитов PatchGuard не представляет особой угрозы, поскольку техники его обхода можно найти в открытом доступе, они развиваются и актуальны по сей день. В этой статье будет рассматриваться множество техник модификации ядра, включая те, что обнаруживает PatchGuard, на примере нового плагина для DRAKVUF — rootkitmon.
Мы уже несколько лет разрабатываем песочницу для рискориентированной защиты, использующую фреймворк DRAKVUF. DRAKVUF — безагентная песочница, основанная на библиотеке LIBVMI и гипервизоре XEN. Все возможности DRAKVUF реализованы в плагинах. Каждый из двадцати с лишним плагинов выполняет определенную работу: для обнаружения доступа к файлам есть плагин filetracer, для трассировки системных вызовов — плагин syscalls. Rootkitmon — новый плагин, позволяющий отслеживать вредоносную активность в ядре средствами DRAKVUF.
Существует множество определений понятия «руткит», мы же будем опираться на следующее: «компьютерная программа, которая использует недокументированные и (или) запрещенные техники для манипуляции ядром операционной системы в своих целях».
В «джентельменский набор» плагина входят возможности детектировать следующие типы перехватов:
MSR LSTAR
;DRIVER_OBJECT
, стек DEVICE_OBJECT
;EPROCESS
;Поскольку руткитов намного меньше, чем вредоносного ПО в пользовательском пространстве, и время выполнения образца всегда ограниченно, уменьшение нагрузки плагина на работающую систему было приоритетной задачей. Для этого во многих случаях было решено сверять целостность критических структур в начале анализа и в конце, а не выполнять непосредственный перехват на запись страниц памяти.
Рассмотрим самый распространенный тип перехватов и, возможно, самый легко обнаруживаемый — inline-перехваты. Inline-перехваты очень популярны, и даже Microsoft предоставляет возможность перехватить API-библиотеки, добавляя перед функциями двухбайтовый пролог вроде mov edi, edi для быстрого редактирования функциональности уже загруженных и работающих компонентов. Конечно, такие перехваты возможны только в пользовательском режиме, а в ядре караются синим экраном с кодом ошибки 0x109
, если PatchGuard не выключен.
Inline-перехваты обычно состоят из трех частей:
Рассмотрим простой пример вызова CreateFileW
из библиотеки kernel32.
. Пройдя все библиотеки, в итоге код окажется в ядерной функции nt!
. Если бы руткит установил перехват на эту функцию, он бы мог выглядеть следующим образом.
Поскольку код находится в страницах с правами только на чтение и выполнение, для записи в такие страницы необходимо либо выделить новую виртуальную страницу с правами на запись и спроецировать ее на физическую страницу, где находится код, либо отключить бит Write Protect в специальном регистре управления CR0
, что позволит выполнять запись в страницы в обход их прав для текущего ядра.
Обнаружение таких перехватов сводится к подсчету контрольной суммы секций драйвера в момент начала анализа и пересчету, сверке контрольной суммы в конце. В отличие от PatchGuard, который защищает только небольшой список системных драйверов, мы можем проверять абсолютно все загруженные драйверы из списка PsLoadedModules
.
PsLoadedModules
— двусвязный список структур _KLDR_DATA_TABLE_ENTRY
, описывающих загруженный драйвер: его базовый адрес, размер, имя, характеристики и прочее.
Для перечисления загруженных модулей ядра с помощью DRAKVUF API мы реализовали метод drakvuf_enumerate_drivers
. В плагине rootkitmon список PsLoadedModules
проходится два раза: в начале инициализации плагина — для подсчета контрольных сумм секций драйверов — и в конце — для сравнения значений.
В случае расхождения в логе появится строка:
Для отработки в конце анализа мы добавляем перехват часто вызываемой ядерной функции KiDeliverApc
. Поскольку мы заранее не знаем, какой поток вызовет эту функцию и в каком контексте процесса этот поток находился, имя процесса, его PID и PPID, которые DRAKVUF автоматически сохраняет в журнале, не имеют отношения к детекту, в то время как поле Reason и все поля, следующие за ним, имеют. В данном случае поле Reason означает обнаруженную вредоносную технику, а поле Driver — название модифицированного драйвера.
SSDT (System Service Descriptor Table) — массив указателей на обработчики системных вызовов в 32-битных системах или список смещений относительно базового адреса таблицы на 64-битных ОС. Как говорилось ранее, до появления PatchGuard эта таблица активно использовалась легитимными программами, а также руткитами для фильтрации и мониторинга системных вызовов. Перезапись одного указателя в такой таблице равносильна перехвату всех вызовов определенного обработчика, что намного проще inline-перехватов, рассмотренных до этого.
На данный момент в ОС Windows существует два таких массива под символами nt!
и win32k!
для системных вызовов к модулю ntoskrnl.
и графической подсистеме win32k.
соответственно. Количество элементов в этих массивах сохранено в переменных nt!
и win32k!
.
Указатель на SSDT находится в специальной структуре KSYSTEM_SERVICE_TABLE
, или SST
, под именем ServiceTableBase
:
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
В то же время массив этих структур лежит в таблицах nt!
и nt!
. Если в первой хранится только SST для обработчиков системных вызовов NT, то во второй добавляется SST-таблица графической подсистемы win32k.
Можно заметить, что первая SST-структура в обеих таблицах одинакова. При системном вызове ОС Windows использует нижние 12 бит регистра eax
как индекс в одной из SSDT-таблиц, а биты 12–13 указывают, какую SDT-структуру выбрать: nt!
или nt!
.
В первой части статьи уже шла речь о том, что на 64-битных системах SSDT содержит массив смещений, а виртуальный адрес обработчика системного вызова вычисляется по формуле
RoutineAddress = ServiceTableBase + (ServiceTableBase[index] >>4)
Сдвиг на 4 необходим, поскольку первые 4 бита содержат количество параметров, передаваемых через стек.
Если взглянуть на пример с вызовом CreateFileW
, учитывая вышеизложенное, он будет выглядеть следующим образом.
Мониторинг модификации SSDT-таблиц заключается в выставлении ловушек на запись в физические страницы памяти данных таблиц и реализован в плагине ssdtmon.
Перехват nt!
уже был реализован в этом плагине, и мы лишь добавили поддержку таблицы win32k!
. Также в плагине вредоносной считается запись, совершенная на 8 байт ниже начала таблицы. Это связано с тем, что с помощью 16-битных XMM-инструкций можно переписать первые 12 байт таблицы, записывая на 4 байта ниже ее начала. Тем самым можно обойти тривиальную проверку границ. Стоит заметить, что в то время, как таблица nt!
находится в секции данных модуля ntoskrnl.
и доступна из всего ядерного пространства, win32k!
принадлежит модулю win32k.
и для доступа к данному драйверу нужно находиться в контексте какого‑либо графического процесса, например explorer.
.
|
|