Реферат: Методы перехвата API-вызовов в Win32

DetourRemoveTrampoline(DynamicTrampoline); //Аздесьснимается

}

При перехвате функция DetourFunction динамически создаёт трамплин и возвращает его адрес. В качестве функции SomeFunction, которая в данном примере возвращает адрес целевой функции, можно использовать DetourFindFunction, которая пытается найти нужную функцию в нужном модуле. Сначала она пытается сделать это через LoadLibrary и GetProcAddress, а в случае неудачи – использует библиотеку ImageHlp для поиска отладочных символов.

Макрос DETOUR_TRAMPOLINE и функция DetourFunction включают в себя встроенный табличный дизассемблер, который определяет, какое количество байт из заголовка целевой функции должно быть скопировано в функцию-трамплин (не менее 5 байт (размер команды jmp), составляющих целое число команд процессора). Если целевая функция занимает менее 5 байт, то перехват оканчивается неудачей.

К достоинствам данного метода следует отнести простоту и надёжность. В отличие от метода с использованием раздела импорта, не нужно учитывать все возможные методы, которыми может быть получен реальный адрес функции. Недостаток – не удастся перехватить функцию с размером менее 5 байт или функцию со следующим заголовком:

push ecx ;в функцию передаётся количество итераций цикла

begin_loop:

;...

;здесь какой-то код

;...

loop begin_loop

ret

Вышеприведённый пример Galen Hunt, один из авторов Detours, прокомментировал следующим образом: «Существует множество теоретических примеров кода, где пролог функции меньше 5 байт, требуемых для команды jmp. Однако никто не сообщал о реальных примерах функции с такими проблемами».

ПРЕДУПРЕЖДЕНИЕ

На момент установки/снятия перехвата нужно останавливать все остальные потоки процесса, в котором происходит перехват (или удостовериться, что они не могут вызывать перехватываемую функцию).

Существует другой способ реализации данного метода. Вместо команды jmp в начало функции помещается команда INT 3, а управление функции-перехватчику передаётся косвенно в обработчике необработанных исключений (её адрес заносится в pExceptionInfo->ContextRecord->Eip и обработчик возвращает EXCEPTION_CONTINUE_EXECUTION). Так как команда INT 3 занимает 1 байт, то вышеописанная ситуация в этом случае даже теоретически невозможна.

ПРЕДУПРЕЖДЕНИЕ

Основным недостатком данного способа является его крайне малое быстродействие (обработка исключения в Windows занимает довольно продолжительное время). Кроме того, наличие обработчика исключений в перехватываемом процессе приведёт к тому, что данный метод работать не будет. Также данный способ не будет работать под отладчиком.

Глобальный перехват

Глобальный перехват может быть реализован различными способами. Первый способ – применение локального перехвата ко всем приложениям в системе (запущенным в момент перехвата или позже). Второй способ – «взлом системы» – подразумевает подмену кода перехватываемой функции непосредственно в DLL-файле или его образе в памяти.

Глобальный перехват методом тотального локального перехвата

Данный метод основан на следующем: если можно перехватить функцию из текущего процесса, то нужно выполнить код перехвата во всех процессах в системе. Существует несколько методов заставить чужой процесс выполнить код перехвата. Самый простой – внести этот код в DllMain некоторой библиотеки, а затем внедрить её в чужой процесс. Методов внедрения DLL также существует несколько (см. Джеффри Рихтер). Самый простой, работающий и в Win9X, и в WinNT – внедрение DLL при помощи ловушек. Реализуется он так: в системе устанавливается ловушка (при помощи функции SetWindowsHookEx) типа WH_GETMESSAGE (эта ловушка служит для перехвата Windows-сообщений). В этом случае модуль, в котором находится ловушка, автоматически подключается к потоку, указанному в последнем аргументе SetWindowsHookEx (если указан 0, то производится подключение ко всем потокам в системе). Однако подключение происходит не сразу, а перед тем, как в очередь сообщений потока будет послано какое-нибудь сообщение. Поэтому перехват осуществляется не сразу после запуска приложения, а перед обработкой процессом первого сообщения. Так что все вызовы перехватываемой функции до обработки процессом первого сообщения перехватываться не будут. А в приложениях без очереди сообщений (например, консольных) этот способ внедрения вообще не работает.

Я написал пример, реализующий глобальный перехват функции GetDriveTypeA с использованием внедрения DLL при помощи ловушек и перехвата с использованием секции импорта.

Функция GetDriveTypeA из библиотеки kernel32.dll используется программами Windows для определения типа диска (локальный, CD-ROM, сетевой, виртуальный и т. д.). Она имеет следующий прототип:

UINT GetDriveType(LPCTSTR lpRootPathName);

lpRootPathName – путь до диска (А:\, В:\ и т.д.)

GetDriveTypeA возвращает одно из следующих значений:

#define DRIVE_UNKNOWN 0

#define DRIVE_NO_ROOT_DIR 1

#define DRIVE_REMOVABLE 2

К-во Просмотров: 354
Бесплатно скачать Реферат: Методы перехвата API-вызовов в Win32