APIHook.h
//--------------------------------------------------------------------------- #ifndef APIHookH #define APIHookH //--------------------------------------------------------------------------- //#include "APIdef.h" #include <Windows.h> #ifdef __cplusplus extern "C" { #endif void InstallHook(void* HookAPI, void** ToAPI, char* dllName, char* ApiName, BOOL Resume); void InstallHookFromAddr(void* HookAPI, void** ToAPI, void* API, BOOL Resume); void SuspendHook(void* ToAPI, char* dllName, char* ApiName); void SuspendHookFromAddr(void* ToAPI, void* API); void ResumeHook(void* HookFunc, char* dllName, char* ApiName); void ResumeHookFromAddr(void* HookFunc, void* API); void UnInstallHook(void** pToAPI, char* dllName, char* ApiName); void UnInstallHookFromAddr(void** pToAPI, void* API); DWORD Transfer(BYTE* Source, BYTE* Dest); #ifdef __cplusplus } #endif /--------------------------------------------------------------------------- #endif
APIHook.c
#pragma hdrstop #include "APIHook.h" //--------------------------------------------------------------------------- #pragma hdrstop #include "APIHook.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "ldasm.obj" #ifdef __cplusplus extern "C" { #endif unsigned long SizeOfCode(unsigned char *code); unsigned long x_code_flags(unsigned char *code); #ifdef __cplusplus } #endif #define OP_REL32 0x40 #define OP_REL8 0x80 int GetOverloadBytes(BYTE* pB); int ASMmemcpy(BYTE* Dest, BYTE* Source, DWORD NBytes); //////////////////////////////////////////////////////////////////////////////// // Instalación general de API_Hooks // HookAPI: API Hookeada // ToAPI: Salta a la API original // ddlName: Nombre de la DLL donde se encuentra la API // ApiName: Nombre de la API que vamos a Hookear //////////////////////////////////////////////////////////////////////////////// void InstallHook(void* HookAPI, void** pToAPI, char* dllName, char* ApiName, BOOL Resume) { HMODULE hLib = GetModuleHandle(dllName); if(!hLib) hLib = LoadLibrary(dllName); if(hLib){ BYTE* API = (BYTE*)GetProcAddress(hLib, ApiName); InstallHookFromAddr(HookAPI, pToAPI, API, Resume); } } void InstallHookFromAddr(void* HookAPI, void** pToAPI, void* API, BOOL Resume) { int NBytes; PBYTE HookFunc, ToAPI; DWORD OldProtect; NBytes = GetOverloadBytes((BYTE*)API); // Bytes a sobreescribir de la API *pToAPI = VirtualAlloc(0, NBytes+5, MEM_COMMIT, PAGE_EXECUTE_READWRITE); HookFunc = (BYTE*)HookAPI; ToAPI = (BYTE*)*pToAPI; // Preparar la función ToAPI // Autorizo escribir en ToAPI VirtualProtectEx((void*)-1, ToAPI, NBytes+5, PAGE_EXECUTE_READWRITE, &OldProtect); ASMmemcpy((BYTE*)ToAPI, (BYTE*)API, NBytes); // Copio los primeros bytes de la api ToAPI[NBytes] = 0xE9 ; //jmp *(DWORD*)(ToAPI + NBytes+1) = ((BYTE*)API + NBytes) - (ToAPI + NBytes+5); VirtualProtectEx((void*)-1, ToAPI, NBytes+5, OldProtect, 0); // Preparar la API a Hookear if(Resume) ResumeHookFromAddr(HookFunc, API); FlushInstructionCache(GetCurrentProcess(), NULL, 0); } void UnInstallHook(void** pToAPI, char* dllName, char* ApiName) { HMODULE hLib = GetModuleHandle(dllName); if(!hLib) hLib = LoadLibrary(dllName); if(hLib){ void* API = GetProcAddress(hLib, ApiName); if(API) UnInstallHookFromAddr(pToAPI, API); } } void UnInstallHookFromAddr(void** pToAPI, void* API) { if(*pToAPI==0 || API==0) return; SuspendHookFromAddr(*pToAPI, API); VirtualFree(*pToAPI, 0, MEM_RELEASE); *pToAPI = 0; } //////////////////////////////////////////////////////////////////////////////// // Calcula los Bytes que se pueden modificar en la API Original //////////////////////////////////////////////////////////////////////////////// int GetOverloadBytes(BYTE* pB) { int Result = 0; for(; Result < 5;) Result += SizeOfCode(pB+Result); return Result; } // Transfiere una instrucción asm completa desde fuente a destino // Si es un salto relativo lo recalcula. // Devuelve el nº de Bytes transferidos en destino. DWORD Transfer(BYTE* Source, BYTE* Dest) { int Offset; DWORD Size = SizeOfCode(Source); DWORD Flag = x_code_flags(Source); CopyMemory(Dest, Source, Size); // Si es un salto relativo if(Flag & (OP_REL8 | OP_REL32)){ // Salto relativo lejano: if(Flag & OP_REL32){ Offset = *(int*)&Source[Size-4]; *(int*)&Dest[Size-4] = Offset - (Dest - Source); } // Salto relativo cercano else if(Flag & OP_REL8){ Offset = *(signed char*)&Source[1]; Dest[0] = 0xE9; *(int*)&Dest[1] = Offset - (Dest - Source); Size = 5; } } return Size; } //////////////////////////////////////////////////////////////////////////////// // Escribe los Bytes a modificar ajustando saltos condicionales //////////////////////////////////////////////////////////////////////////////// int ASMmemcpy(BYTE* Dest, BYTE* Source, DWORD NBytes) { DWORD Result = 0; for(; Result < NBytes;){ Transfer(Source + Result, Dest + Result); Result += SizeOfCode(Source + Result); } return Result; } //////////////////////////////////////////////////////////////////////////////// // Suspende momentaneamente el Hook sin desinatalar ToHook //////////////////////////////////////////////////////////////////////////////// void SuspendHookFromAddr(void* ToAPI, void* API) { int n; DWORD OldProtect; if(ToAPI==0 || API ==0) return; // Autorizo escribir en la API Hookeada VirtualProtectEx((void*)-1, API, 5, PAGE_EXECUTE_READWRITE, &OldProtect); for(n=0; n<5; n++) ((BYTE*)API)[n] = ((BYTE*)ToAPI)[n]; //memcpy(API, ToAPI, 5); VirtualProtectEx((void*)-1, API, 5, OldProtect, 0); } void SuspendHook(void* ToAPI, char* dllName, char* ApiName) { void* API = 0; HMODULE hLib = 0; if(ToAPI==0 || dllName==0 || ApiName==0) return; hLib = GetModuleHandle(dllName); if(!hLib) hLib = LoadLibrary(dllName); if(!hLib) return; API = GetProcAddress(hLib, ApiName); if(API) SuspendHookFromAddr(ToAPI, API); } //////////////////////////////////////////////////////////////////////////////// // Resume o reinicia el Hook //////////////////////////////////////////////////////////////////////////////// void ResumeHookFromAddr(void* HookFunc, void* API) { DWORD OldProtect; BYTE* Api; if(HookFunc==0 || API==0) return; // Autorizo escribir en la API a Hookear VirtualProtectEx((void*)-1, API, 5, PAGE_EXECUTE_READWRITE, &OldProtect); Api = (BYTE*)API; *Api = 0xE9 ; //jmp *(DWORD*)(Api+1) = (BYTE*)HookFunc - (Api+5); VirtualProtectEx((void*)-1, API, 5, OldProtect, 0); } void ResumeHook(void* HookFunc, char* dllName, char* ApiName) { void* API; if(HookFunc==0) return; API = GetProcAddress(GetModuleHandle(dllName), ApiName); if(API) ResumeHookFromAddr(HookFunc, API); }
Dado que las explicaciones a dicho código están expuestas más arriba, no creo que merezca la pena repetir.
Saludos.