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! Отследить эти махинации практически нереально! |