#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;
}
Как правильно ставить хук на GetAdatersInfo?
Может кто-то указать на то, что я делаю неправильно при объявлении или использовании данного хука?
Перехват делаю с помощью jmp.
Полный код:
Код:
сам перехватчик - HookedGetAdaptersInfo (см. код)
А это что я получаю в результате
Код:
Сигнатура проблемы:
Имя события проблемы: APPCRASH
Штамп времени приложения: 49b87baa
Имя модуля с ошибкой: StackHash_7c42
Код исключения: c0000005
Смещение исключения: 0a2e10fd
Дополнительные сведения 1: 7c42
Дополнительные сведения 2: 074873ae4f436ef335386852c5e8b196
Дополнительные сведения 3: 7493
Дополнительные сведения 4: 96bea09c09e264a9786c72b1e588c0af
Имя события проблемы: APPCRASH
Штамп времени приложения: 49b87baa
Имя модуля с ошибкой: StackHash_7c42
Код исключения: c0000005
Смещение исключения: 0a2e10fd
Дополнительные сведения 1: 7c42
Дополнительные сведения 2: 074873ae4f436ef335386852c5e8b196
Дополнительные сведения 3: 7493
Дополнительные сведения 4: 96bea09c09e264a9786c72b1e588c0af
в логе появляются две надписи подряд hook executed.
в целевой программе два вызова тоже, если смотреть под дизассемблером.
Может я HookedGetAdaptersInfo неверно объявил или в ней что-то не так делаю?
stdcall ?
Извиняюсь, если комментарий неуместный. А не проще ли это через таблицу импорта сделать?
т.е. здесь: DWORD ret_val = GetAdaptersInfo(pAdapterInfo, pOutBufLen);
PreHook(); и PostHook(); снимают хук с GetAdaptersInfo и восстанавливают его соответственно. Думаю что способ вызова оригинальной функции в перехватчике не влияет на это.
по поводу таблицы импорта - та же картина получается
ваш HookedGetAdaptersInfo stdcall?
все ясно. вопрос решен. Премного благодарен, Phodopus!