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

Ваш аккаунт

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

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

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

Как правильно ставить хук на GetAdatersInfo?

408
26 июня 2011 года
Lei fang
265 / / 01.10.2005
Здравствуйте.
Может кто-то указать на то, что я делаю неправильно при объявлении или использовании данного хука?

Перехват делаю с помощью jmp.
Полный код:
Код:
#include "stdafx.h"

#pragma comment(lib, "IPHLPAPI.lib")

#define SIZE_OF_NT_SIGNATURE (sizeof(DWORD))

#define AH_JUMP 1
#define AH_IMPORT_EXPORT 2

#define JMP_OPER_LEN 4
#define JMP_LEN 5

const BYTE jmp = 0xE9;

#define    AHD_PROCADDRESS        0x0001
#define    AHD_PROCNAME        0x0002
#define    AHD_MODULE            0x0004
#define    AHD_MODULENAME        0x0008
#define    AHD_BASEMODULE        0x0010
#define    AHD_BASENAME        0x0020

typedef struct _tagAPIHOOKDATA
{
    int nMode;
    int nMask;
    union
    {
        DWORD dwProcAddress;
        LPCSTR lpszProcName;
    } u1;

    union
    {
        HMODULE hModule;
        LPCSTR lpszModule;
    } u2;

    union
    {
        HMODULE hBaseModule;
        LPCSTR lpszBaseModule;
    } u3;

    DWORD dwHookAddress;

} APIHOOKDATA, *LPAPIHOOKDATA;

class CAPIHook
{
public:
    CAPIHook() {};
    ~CAPIHook() { UnHook(); };

    BOOL SetHook(LPAPIHOOKDATA pAPIHookData);
    void UnHook();

    BOOL PreHook();
    BOOL PostHook();

    DWORD GetOriginal()
    {
        return m_dwProcAddress;
    }

    BOOL IsHooked()
    {
        return m_dwProcAddress == 0 ? FALSE : TRUE;
    }

protected:
    BOOL _setHook1(DWORD dwProcAddress, DWORD dwHookAddress);
    BOOL _setHook2(HMODULE hModule, DWORD dwProcAddress, DWORD dwHookAddress);

    void _unHook1();
    void _unHook2();

    LPVOID GetDataDirectory(LPVOID lpFile, UINT uIndex);

protected:
    BYTE m_FirsBytes[JMP_LEN];
    BYTE m_JmpCmd[JMP_LEN];
    DWORD m_dwProcAddress;
    DWORD m_dwHookAddress;
    HMODULE m_hModule;
    int m_nMode;
};

void WriteToLog(char* str)
{
    FILE* f = fopen("hook_log.txt", "a+");
    fprintf(f, "%s\n", str);
    fclose(f);
}

BOOL CAPIHook::SetHook(LPAPIHOOKDATA pAPIHookData)
{
    HMODULE hModule = NULL;
    HMODULE hBaseModule = NULL;
    DWORD dwProcAddress = 0;
 
    if (pAPIHookData->nMask & AHD_MODULENAME)
    hModule = GetModuleHandleA(pAPIHookData->u2.lpszModule);
    else if (pAPIHookData->nMask & AHD_MODULE)
        hModule = pAPIHookData->u2.hModule;

    if (hModule && pAPIHookData->nMask & AHD_PROCNAME)
    dwProcAddress = (DWORD)GetProcAddress(hModule, pAPIHookData->u1.lpszProcName);
    else if (pAPIHookData->nMask & AHD_PROCADDRESS)
        dwProcAddress = pAPIHookData->u1.dwProcAddress;

    if (pAPIHookData->nMask & AHD_BASENAME)
        hBaseModule = GetModuleHandleA(pAPIHookData->u3.lpszBaseModule);
    else if (pAPIHookData->nMask & AHD_BASEMODULE)
        hBaseModule = pAPIHookData->u3.hBaseModule;

    if (pAPIHookData->nMode == AH_JUMP && dwProcAddress && pAPIHookData->dwHookAddress)
        return _setHook1(dwProcAddress, pAPIHookData->dwHookAddress);
    else if (pAPIHookData->nMode == AH_IMPORT_EXPORT && hModule && dwProcAddress && pAPIHookData->dwHookAddress)
        return _setHook2(hModule, dwProcAddress, pAPIHookData->dwHookAddress);

    SetLastError(ERROR_INVALID_PARAMETER);

    return FALSE;
}

void CAPIHook::UnHook()
{
    if (m_dwProcAddress)
    {
        if (m_nMode == AH_JUMP)
            _unHook1();
        else if (m_nMode == AH_IMPORT_EXPORT)
            _unHook2();
    }
}

BOOL CAPIHook::_setHook1(DWORD dwProcAddress, DWORD dwHookAddress)
{
    _unHook1();
    m_nMode = AH_JUMP;
    DWORD dwProtect;

    m_JmpCmd[0] = jmp;
    DWORD dwTemp = dwHookAddress - (dwProcAddress + JMP_LEN);
    memmove(&m_JmpCmd[1], &dwTemp, JMP_OPER_LEN);

    if (VirtualProtect((LPVOID)dwProcAddress, JMP_LEN, PAGE_EXECUTE_READWRITE, &dwProtect))
    {
        m_dwProcAddress = dwProcAddress;

        memmove(m_FirsBytes, (LPVOID)dwProcAddress, JMP_LEN);

        memmove((LPVOID)dwProcAddress, m_JmpCmd, JMP_LEN);

        VirtualProtect((LPVOID)dwProcAddress, JMP_LEN, dwProtect, &dwProtect);

        return TRUE;
    }

    return FALSE;
}

BOOL CAPIHook::PreHook()
{
    if (m_nMode != AH_JUMP)
        return TRUE;
    assert(m_dwProcAddress);

    if (m_dwProcAddress)
    {
        DWORD dwProtect;

        if (VirtualProtect((LPVOID)m_dwProcAddress, JMP_LEN, PAGE_EXECUTE_READWRITE, &dwProtect))
        {
            memmove((LPVOID)m_dwProcAddress, m_FirsBytes, JMP_LEN);

            VirtualProtect((LPVOID)m_dwProcAddress, JMP_LEN, dwProtect, &dwProtect);

            return TRUE;
        }

        return FALSE;
    }

    SetLastError(ERROR_INVALID_DATA);

    return FALSE;
}

BOOL CAPIHook::PostHook()
{
    if (m_nMode != AH_JUMP)
        return TRUE;

    assert(m_dwProcAddress);

    if (m_dwProcAddress)
    {
        DWORD dwProtect;

        if (VirtualProtect((LPVOID)m_dwProcAddress, JMP_LEN, PAGE_EXECUTE_READWRITE, &dwProtect))
        {
            memmove((LPVOID)m_dwProcAddress, m_JmpCmd, JMP_LEN);

            VirtualProtect((LPVOID)m_dwProcAddress, JMP_LEN, dwProtect, &dwProtect);

            return TRUE;
        }

        return FALSE;
    }

    SetLastError(ERROR_INVALID_DATA);

    return FALSE;
}

void CAPIHook::_unHook1()
{
    if (m_dwProcAddress)
    {
        PreHook();
        m_dwProcAddress = 0;
    }
}

LPVOID CAPIHook::GetDataDirectory(LPVOID lpFile, UINT uIndex)
{
    int ImageHdrOffset = 0;

    if (*((USHORT*)lpFile) == IMAGE_DOS_SIGNATURE)
    {
        ImageHdrOffset = (int)(((PIMAGE_DOS_HEADER)lpFile)->e_lfanew + SIZE_OF_NT_SIGNATURE);

        if (*((ULONG*)((LPBYTE)lpFile + ImageHdrOffset - SIZE_OF_NT_SIGNATURE)) != IMAGE_NT_SIGNATURE)
        {
            return NULL;
        }
    }
    else
    {
        return NULL;
    }

    PIMAGE_FILE_HEADER ph = (PIMAGE_FILE_HEADER)((LPBYTE)lpFile + ImageHdrOffset);

    PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)((LPBYTE)lpFile + ImageHdrOffset + sizeof(IMAGE_FILE_HEADER));

    return (LPVOID)(poh->DataDirectory[uIndex].VirtualAddress + (DWORD)lpFile);
}

BOOL CAPIHook::_setHook2(HMODULE hModule, DWORD dwProcAddress, DWORD dwHookAddress)
{
    _unHook2();
    m_nMode = AH_IMPORT_EXPORT;

    LPVOID lpFile = (LPVOID)hModule;

    PIMAGE_EXPORT_DIRECTORY pied = (PIMAGE_EXPORT_DIRECTORY)GetDataDirectory(lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT);

    if (!pied)
    {
        SetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }

    for (DWORD i = 0; i < pied->NumberOfFunctions; i++)
    {
        if (((LPDWORD)((DWORD)pied->AddressOfFunctions + (DWORD)lpFile)) == dwProcAddress - (DWORD)lpFile)
        {
            DWORD dwProtect, dwAddress = (DWORD)&((LPDWORD)((DWORD)pied->AddressOfFunctions + (DWORD)lpFile));

            if (VirtualProtect((LPVOID)dwAddress, sizeof(DWORD), PAGE_READWRITE, &dwProtect))
    {
                m_dwProcAddress = ((LPDWORD)((DWORD)pied->AddressOfFunctions + (DWORD)lpFile)) + (DWORD)lpFile;
                m_dwHookAddress = dwHookAddress;
                m_hModule = hModule;

                ((LPDWORD)((DWORD)pied->AddressOfFunctions + (DWORD)lpFile)) = (dwHookAddress - (DWORD)hModule);

                VirtualProtect((LPVOID)dwAddress, sizeof(DWORD), dwProtect, &dwProtect);

                return TRUE;
            }

            return FALSE;
        }
    }

    SetLastError(ERROR_INVALID_FUNCTION);

    return FALSE;
}

void CAPIHook::_unHook2()
{
    if (m_dwProcAddress)
    {
        DWORD dwProcAddress = m_dwProcAddress;
        m_dwProcAddress = 0;
        _setHook2(m_hModule, m_dwHookAddress, dwProcAddress);
    }
}

static CAPIHook h_GetAdaptersInfo;
APIHOOKDATA ahd;

DWORD HookedGetAdaptersInfo(__out PIP_ADAPTER_INFO pAdapterInfo, __inout PULONG pOutBufLen)
{
    h_GetAdaptersInfo.PreHook();

    DWORD ret_val = GetAdaptersInfo(pAdapterInfo, pOutBufLen);

    WriteToLog("hook executed");

    h_GetAdaptersInfo.PostHook();

    return ret_val;
}

void SetupHooks()
{
    ahd.nMask = AHD_PROCNAME|AHD_MODULENAME;
    ahd.nMode = AH_JUMP;
    ahd.dwHookAddress = (DWORD)HookedGetAdaptersInfo;
    ahd.u1.lpszProcName = ("GetAdaptersInfo");
    ahd.u2.lpszModule = ("Iphlpapi.dll");

    h_GetAdaptersInfo.SetHook(&ahd);
}

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        SetupHooks();
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


сам перехватчик - HookedGetAdaptersInfo (см. код)

А это что я получаю в результате
 
Код:
Сигнатура проблемы:
  Имя события проблемы:   APPCRASH
  Штамп времени приложения:   49b87baa
  Имя модуля с ошибкой:    StackHash_7c42
  Код исключения:  c0000005
  Смещение исключения:    0a2e10fd
  Дополнительные сведения 1:  7c42
  Дополнительные сведения 2:  074873ae4f436ef335386852c5e8b196
  Дополнительные сведения 3:  7493
  Дополнительные сведения 4:  96bea09c09e264a9786c72b1e588c0af


в логе появляются две надписи подряд hook executed.
в целевой программе два вызова тоже, если смотреть под дизассемблером.
Может я HookedGetAdaptersInfo неверно объявил или в ней что-то не так делаю?
14
28 июня 2011 года
Phodopus
3.3K / / 19.06.2008
stdcall ?
288
28 июня 2011 года
nikitozz
1.2K / / 09.03.2007
Извиняюсь, если комментарий неуместный. А не проще ли это через таблицу импорта сделать?
408
28 июня 2011 года
Lei fang
265 / / 01.10.2005
По поводу stdcall, вы имеете ввиду что в функции перехватчике надо вызывать оригинальный GetAdaptersInfo по указателю, а не по имени функции?
т.е. здесь: DWORD ret_val = GetAdaptersInfo(pAdapterInfo, pOutBufLen);
PreHook(); и PostHook(); снимают хук с GetAdaptersInfo и восстанавливают его соответственно. Думаю что способ вызова оригинальной функции в перехватчике не влияет на это.

по поводу таблицы импорта - та же картина получается
14
29 июня 2011 года
Phodopus
3.3K / / 19.06.2008
ваш HookedGetAdaptersInfo stdcall?
408
29 июня 2011 года
Lei fang
265 / / 01.10.2005
все ясно. вопрос решен. Премного благодарен, Phodopus!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог