HookAPI
Взять можно здесь: http://sources.codenet.ru/download/1205/HookApi_h.html
HookApi - базовый класс для перехвата вызовов функций API из текущего процесса.
Класс позволяет как мониторить вызовы (перехватывать и отдавать управление в реальную функцию API), так и самостоятельно обрабатывать вызовы (возвращать управление вызывающему коду, не передавая управление в реальную функцию API).
ВНИМАНИЕ! Код перехвата изменяет значения регистра ECX.
Для моих целей это было нестрашно, но для ваших может быть серьезной помехой. Так что применяйте обдуманно.
Использовать класс очень просто. Наследуете от него класс для перехвата определенной функции API, переопределеяте в наследнике виртуальный метод handler. Для удобства установки хука можно определить ещё специальный метод hook.
Подробнее о виртуальном методе handler:
Код:
virtual DWORD HookApi::handler(void** stack, PDWORD result);
Аргументы:
stack - указатель на вершину стека при вызове API, т.е. по большому счету указатель на адрес возврата, за которым следуют параметры вызова.
result - указатель на возвращаемое вместо API-функции значение. Если установленный хук сам обрабатывает вызов не передавая управление в реальную функцию API, то в DWORD, на который указывает result, должно быть помещено якобы возвращаемое из API-функции значение.
Возвращаемое значение:
Если меньше нуля, то это значит, что управление из перехватчика будет передано в реальную функцию;
Если больше, либо равно нулю, то это размер аргументов на стеке передаваемых в API-функцию. Т.к. API-функции имеют спецификацию cdecl, т.е. обязаны сами очищать стек, от переданных им параметров, а количество переданных параметров зависит от конкретной функции, то при эмуляции (перехвате с обработкой без вызова реальной API-функции) перехватывающий код должен сам очистить стек от этих параметров, а для этого надо указать сколько они занимали места на стеке.
Пример использования:
Код:
#include <windows.h>
#include <iostream>
using namespace std;
#include "HookApi.h"
//
// Перехватчик API-функции NtOpenFile
//
class HookNtOpenFile :public HookApi
{
public:
bool hook() {
return HookApi::hook("ntdll", "NtOpenFile");
}
private:
virtual DWORD handler(void** stack, PDWORD result) {
wcout << "HookNtOpenFile" << endl;
return -1; // Передаем управление в реальную API-функцию
}
};
//
// Перехватчик API-функции RtlDosSearchPath_U
//
class HookRtlDosSearchPath_U :public HookApi
{
public:
bool hook() {
return HookApi::hook("ntdll", "RtlDosSearchPath_U");
}
private:
virtual DWORD handler(void** stack, PDWORD result) {
// читаем параметры вызова из стека
PWSTR lpPath = (PWSTR)stack[1];
PWSTR lpFileName = (PWSTR)stack[2];
PWSTR lpExtension = (PWSTR)stack[3];
ULONG nBufferLength = (ULONG)stack[4];
PWSTR lpBuffer = (PWSTR)stack[5];
PWSTR* lpFilePart = (PWSTR*)stack[6];
wcout << "HookRtlDosSearchPath_U: " << endl;
wcout << lpPath << endl;
wcout << lpFileName << endl;
// Здесь производим собственную обработку
...................................
*result = 0; // Выставляем возвращаемое в вызывающий код значение
return 6 * sizeof(DWORD); // Возвращаем управление в вызывающий
// код без передачи в реальную API-функцию.
// Шесть параметров занимают на стеке 6 * sizeof(DWORD)
}
};
int main()
{
// Устанавливаем хуки
HookNtOpenFile hookNtOpenFile;
hookNtOpenFile.hook();
HookRtlDosSearchPath_U hookRtlDosSearchPath_U;
hookRtlDosSearchPath_U.hook();
// Код вызывающий прохученные функции
................................
return 0;
#include <iostream>
using namespace std;
#include "HookApi.h"
//
// Перехватчик API-функции NtOpenFile
//
class HookNtOpenFile :public HookApi
{
public:
bool hook() {
return HookApi::hook("ntdll", "NtOpenFile");
}
private:
virtual DWORD handler(void** stack, PDWORD result) {
wcout << "HookNtOpenFile" << endl;
return -1; // Передаем управление в реальную API-функцию
}
};
//
// Перехватчик API-функции RtlDosSearchPath_U
//
class HookRtlDosSearchPath_U :public HookApi
{
public:
bool hook() {
return HookApi::hook("ntdll", "RtlDosSearchPath_U");
}
private:
virtual DWORD handler(void** stack, PDWORD result) {
// читаем параметры вызова из стека
PWSTR lpPath = (PWSTR)stack[1];
PWSTR lpFileName = (PWSTR)stack[2];
PWSTR lpExtension = (PWSTR)stack[3];
ULONG nBufferLength = (ULONG)stack[4];
PWSTR lpBuffer = (PWSTR)stack[5];
PWSTR* lpFilePart = (PWSTR*)stack[6];
wcout << "HookRtlDosSearchPath_U: " << endl;
wcout << lpPath << endl;
wcout << lpFileName << endl;
// Здесь производим собственную обработку
...................................
*result = 0; // Выставляем возвращаемое в вызывающий код значение
return 6 * sizeof(DWORD); // Возвращаем управление в вызывающий
// код без передачи в реальную API-функцию.
// Шесть параметров занимают на стеке 6 * sizeof(DWORD)
}
};
int main()
{
// Устанавливаем хуки
HookNtOpenFile hookNtOpenFile;
hookNtOpenFile.hook();
HookRtlDosSearchPath_U hookRtlDosSearchPath_U;
hookRtlDosSearchPath_U.hook();
// Код вызывающий прохученные функции
................................
return 0;
У меня эта версия работает, а у тебя?
А у меня все версии (скомпиленные в VC 6.0, 8.0, 9.0) падают по access violation.
Я могу предположить, что автогенерируемый в моем классе код не хочет исполняться, т.к. по идее он расположен в секции с аттрибутами чтение/запись, но не исполнение.
Только не понятно, что сообщение говорит не об этом.
Интересно, а программы с WTL у тебя работают? Там используется схожий механизм динамической генерации кода.
hookFindFirstFile.hook();
добавить строку:
FlushInstructionCache(GetCurrentProcess(), &hookFindFirstFile, sizeof(hookFindFirstFile));
WTL у меня работает, все ок.
Попробовал FlushInstructionCache, не помогло.
Соотв. походу тебе надо сменить в настройках компилятора конвенцию вызова по-умолчанию на __cdecl (/Gd).
ЗЫ: Спасибо Green-у за HookApi. :)