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

Операция "Перехват"

A.M.D.F. (grunge@amdf.pp.ru)

Хакер, номер #070, стр. 070-082-1


Внедрение DLL и замена API-вызовов в Windows

Тебе никогда не хотелось изменить работу чужой программы? Исправить досадную ошибку, не дожидаясь выхода новой версии, отучить игрушку от CD, не залезая в инет за патчем? Да это же проще простого! Сегодня я научу тебя управлять работой чужих программ, причем для этого тебе не потребуется глубокого знания какого-либо языка программирования!

Программы и DLL

Любая программа для Windows использует в работе определенный набор функций. Часть из них находится в ней самой, часть располагается в динамически подключаемых библиотеках. Если приложение состоит из единственного файла и не устанавливает вместе с собой набор DLL, это не значит, что библиотеки совсем не используются. Программа наверняка использует функции Windows API, расположенные во множестве библиотек в каталоге system32. Даже если в ней нет явных вызовов API, они все равно используются. Любое приложение при запуске вызывает из библиотеки kernel32 функции для работы с памятью, определения командной строки, параметров запуска, значений переменных окружения. Когда программа закрывается, вызывается функция ExitProcess. Многие методы классов MFC или VCL содержат вызовы Windows API в своих алгоритмах.

Для многих задач существуют свои API-функции, например, для запуска программы используется CreateProcess, а для записи в файл - WriteFile. Зная, что делает программа, мы можем узнать, какие API она для этого использует. Достаточно посмотреть раздел импорта программы в какой-нибудь специальной утилите, например PE Tools.

Раздел импорта - это специальный раздел в exe-файле, где находится список загружаемых программой библиотек и импортируемых функций. Когда программа запускается, загрузчик операционной системы проецирует в адресное пространство процесса все перечисленные в нем DLL и настраивает виртуальные адреса всех требуемых функций.

Переадресация вызовов

Вызывая импортируемую функцию, процесс получает ее адрес из раздела импорта. Поэтому чтобы перехватить определенную функцию, надо лишь изменить ее адрес в этом разделе. Тем самым ты сможешь влиять на алгоритм программы: подделывать возвращаемый функцией результат и менять значения переданных параметров. О том, как это сделать, рассказывается в книге Джеффри Рихтера "Создание эффективных WIN32-приложений". Суть алгоритма в следующем: тебе необходимо внедриться в адресное пространство подопытного процесса и выполнить в нем специальный код, который изменит раздел импорта так, что когда программа вызовет функцию API, на самом деле вызовется твоя собственная функция. Код функции ReplaceIATEntryInOneMod, выполняющий эту операцию, ты найдешь на диске - он слишком большой, чтобы печатать его в журнале.

Как принудить подопытный процесс выполнить твою функцию? Для начала процесс должен загрузить в свое адресное пространство библиотеку, которая и выполнит соответствующий код.

Копаемся в Блокноте

Я продемонстрирую, как это делается, на тривиальном примере замены функции MessageBox в стандартной утилите Windows - Блокноте. Когда пишешь в нем что-нибудь, а затем пытаешься выйти, не сохранив, Блокнот выдает тебе маленькое окошко с сообщением "Текст в файле blablabla.txt был изменен. Сохранить изменения?". Неплохо было бы изменить содержание этого сообщения на что-то поинтереснее.

Содержание  Вперед на стр. 070-082-2