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

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

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

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


}

Хотя... На нулевом кольце (наш драйвер исполняется именно там) можно творить все что угодно. Сотворить Адама вряд ли получится (с искусственным интеллектом прогресс застрял на уровне дождевого червя), но отключить защиту мы сможем. Правда, это будет слишком заметное, уродливое и к тому же небезопасное решение. Защита установлена на верхнюю половину памяти не даром. Она не позволяет приложениям входить в разнос, и хотя операционная система спокойно проживет и без нее, это будет сплошное варварство.

Проведем простой эксперимент - напишем программу, которая передает управление куда-то в глубину ядра, и посмотрим, что происходит при этом.

(Попытка передачи управления на память ядра)

#include <stdio.h>

main()

{

char *p;

// произвольный адрес в верхней половине адресного пространства

p = (char *)0xBE0FAC69;

// передача управления на p

// (конечно, это можно было сделать и на С, но на асме круче)

__asm{

mov ebx,[p]

jmp ebx

}

}

Как и следовало ожидать, мы получаем исключение типа "ошибка доступа", и управление передается не на ядро, а на обработчик структурного исключения, он же SEH – Structured exception handling (поиск по одноименному ключевому слову в MSDN или интернете выдает очень много интересного). У каждого процесса имеется как минимум один структурный обработчик, устанавливаемый операционной системой. Он выводит пресловутое сообщение о критической ошибке на экран и завершает приложение. Программист может устанавливать и свои обработчики, перехватывающие исключения и тем или иным образом обрабатывающие критическую ситуацию. К сожалению, все они выполняются в контексте данного процесса, про сложности внедрения в адресное пространство которого мы только что говорили. Тупик?

Вовсе нет! На самом деле SEH получает управление в последнюю очередь, когда бал окончен, закуска съедена, а девушки вытворяют весь SEH, на который только способно наше воображение. При возникновении исключения процессор автоматически переходит в режим ядра и передает управление операционной системе, точнее, тому самому коду, на который указывает соответствующий элемент таблицы прерываний (IDT - Interrupt Description Table). Любой драйвер может беззастенчиво модифицировать содержимое IDT по своему усмотрению, перехватывая все прерывания, которые ему нужны. Техника перехвата подробно описана в любой книге, посвященной программированию в защищенном режиме. К примеру в учебнике Юрова, который так и называется - "Ассемблер - учебник". Еще есть Зубков, Гук и известная рассылка Калашникова.

Главное, что решить нашу задачу все-таки возможно. Несмотря на то, что верхняя половина адресного пространства недоступна прикладным процессам, аппаратная точка останова все-таки передает управление обработчику, причем на прикладном уровне это протекает незаметно и до SEH'а дело просто не доходит. Вот такие превратности таят в себе метаморфозы программирования в защищенном режиме.

Идем дальше. Линейный адрес точки останова хранится в регистрах Dr0-Dr3. Об этом рассказывает "фирменная" документация от Intel и AMD, а моя "Техника и философия хакерских атак" содержит исходный код перехватчика со всеми комментариями. Кстати, электронную версию можно бесплатно утянуть с моего персонального ftp-сервера (подробности во врезке).

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