Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #58, СЕНТЯБРЬ 2005 г.

Stealth patching своими руками

Крис Касперски

Спецвыпуск: Хакер, номер #058, стр. 058-050-6


Модифицировав регистры процессора по своему усмотрению, мы вызываем функцию GetThreadContext и размораживаем поток с помощью ResumeThread. Все! Теперь наш хакерский обработчик восстанавливает IDT в прежний вид и самоликвидируется, выгружая драйвер из памяти. В упрощенном виде это происходит так:

(Установка точки останова с помощью модификации контекста)

// получаем дескриптор потока,

// вызывая недокументированную функцию OpenThread

hThread = OpenThread(Id); if (!hThread) return;

// даем потоку наркоз

SuspendThread(hThread);

// говорим, что нам нужен полный контекст

// со всеми кишками отладочных регистров

Context.ContextFlags = CONTEXT_FULL;

// извлекаем контекст из недр потока

GetThreadContext(hThread, Context);

// модифицируем отладочные регистры семейства Drx,

// устанавливая аппаратную точку останова на хакаемый код

// имплантируем обновленный контекст обратно в поток

SetThreadContext(hThread, Context);

// пробуждаем поток

ResumeThread(hThread);

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

Как известно, KERNEL32.DLL содержит лишь высокоуровневые "обертки" реальных ATP-функций, ведущих к очередной "обертке" в лице NTDLL.DLL. Реальный код сосредоточен в NTOSKRNL.EXE - подлинном ядре операционной системы, которое проживает в верхней половине адресного пространства. Ядерные функции всегда исполняются в чьем-то контексте, который в общем случае является контекстом процесса, вызывавшего ту или иную API-функцию. Процессов, не вызывающих никаких API-функций, в природе не встречается. Даже если процесс состоит из одного лишь return (кстати, Windows 2000 отказывается грузить файлы без импорта KERNEL32.DLL), определенная часть кода системного загрузчика исполняется в контексте загружаемого процесса и вызывает множество ядерных функций. Короче, загрузить процесс, не потревожив ядра, практически нереально (разве что загружать его на виртуальной машине). А это значит, что регистры Drx могут быть установлены прямо из ядра без обращения к API-функциям GetThreadContext и SetThreadContext! Отследить эти махинации практически нереально!

Назад на стр. 058-050-5  Содержание  Вперед на стр. 058-050-7