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

Враг неведом

Зайцев Олег

Спецвыпуск: Хакер, номер #070, стр. 070-034-2


На схеме показан принцип действия подобного руткита. На стадии загрузки исполняемого файла загрузчик заполняет таблицу импорта правильными адресами. Далее вмешивается руткит и подменяет реальные адреса функций адресам своих перехватчиков. Важным моментом является перехват функций LoadLibrary и GetProcAddress из kernel32.dll – грамотно построенный руткит обязан это сделать для того, чтобы отслеживать загрузку библиотек и подменять адреса перехваченных функций в момент их запроса. Однако анализ многих простейших UserMode-руткитов показывает, что они это не делают и ограничиваются исключительно правкой таблицы импорта. Это, естественно, некорректно, но в простейшем случае работает – например, для маскировки процесса от штатного таск-менеджера. При вызове статически импортируемой функции программа просто передаст управление по адресу из таблицы импорта, а в случае динамического импорта руткит подсунет программе адрес своего перехватчика вместо адреса функции. Следует учитывать, что при таком перехвате все равно остается вероятность того, что программа как-то ухитрится узнать правильный адрес (он может быть определен до установки перехватчиков, получен анализом заголовков библиотек и т.п.). Этого недостатка лишен метод модификации машинного кода.

[руткиты, основанные на модификации машинного кода API-функций]

Данный метод достаточно прост: он основан на модификации машинного кода перехватываемых функций в памяти. В простейшем случае модификация сводится к записи команды JMP в начале функции.

По принципу реализации, подразделяется на три разновидности:

* Метод подмены первых байт. Это самый простой и самый некорректный метод, который состоит в лобовом копировании первых байт (именно байт, а не команд) кода функции и записи на их место собственного кода. Обычно копируются первые 5 байт, а на их место записывается EB xx xx xx xx – код команды JMP. Для вызова перехваченной функции руткит вынужден восстановить ее, вызвать, а затем опять прописать свой код в начало функции. Это медленно, коряво и чревато глюками в многопоточном приложении.

* Метод подмены первых команд. Этот метод аналогичен предыдущему, но намного корректнее. Он состоит в том, что руткит применяет дизассемблер длин команд, что позволяет ему выделить несколько команд и скопировать их в буфер. Скопированные команды дополняются командой JMP на первую неповрежденную команду перехваченной API-функции, а занимаемой буфером памяти выставляются фланги PAGE_EXECUTE_READWRITE, что позволяет исполнять содержащийся там код. В момент вызова API-функции управление передается перехватчику руткита, а он, в свою очередь, может вызвать перехваченную функцию, передав управление буферу. На схеме показано внедрение кода в начало функции, это самый распространенный метод. Кроме того, код можно внедрить в конец функции – такой метод удобен для маскировки перехвата. Корректный руткит должен не просто выделять и копировать команды – он еще должен изучать их и при необходимости корректировать относительные адреса с учетом нового местоположения копируемых команд в памяти.

Назад на стр. 070-034-1  Содержание  Вперед на стр. 070-034-3