Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

HookAPI

3
15 декабря 2006 года
Green
4.8K / / 20.01.2000
Вот в коем разе решил поделиться наработками... :)
Взять можно здесь: 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;
Страницы:
3
30 июня 2008 года
Green
4.8K / / 20.01.2000
У меня эта версия работает, а у тебя?
39K
30 июня 2008 года
vcher
13 / / 30.06.2008
А у меня все версии (скомпиленные в VC 6.0, 8.0, 9.0) падают по access violation.
3
30 июня 2008 года
Green
4.8K / / 20.01.2000
Хм... возможно, это настройки винды...
Я могу предположить, что автогенерируемый в моем классе код не хочет исполняться, т.к. по идее он расположен в секции с аттрибутами чтение/запись, но не исполнение.
Только не понятно, что сообщение говорит не об этом.
Интересно, а программы с WTL у тебя работают? Там используется схожий механизм динамической генерации кода.
3
30 июня 2008 года
Green
4.8K / / 20.01.2000
А попробуй после строки:
hookFindFirstFile.hook();

добавить строку:
FlushInstructionCache(GetCurrentProcess(), &hookFindFirstFile, sizeof(hookFindFirstFile));
39K
30 июня 2008 года
vcher
13 / / 30.06.2008
Ну в общем, непонятно....
WTL у меня работает, все ок.
39K
30 июня 2008 года
vcher
13 / / 30.06.2008
Попробовал FlushInstructionCache, не помогло.
65K
15 ноября 2010 года
Blakkky
1 / / 15.11.2010
2vcher: Сталкнулся с такой же проблемой. Решилась убиранием WINAPI перед handler-ом.
Соотв. походу тебе надо сменить в настройках компилятора конвенцию вызова по-умолчанию на __cdecl (/Gd).

ЗЫ: Спасибо Green-у за HookApi. :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог