//================================== // HOOKAPI - Matt Pietrek 1994 // FILE: HOOKAPI.C //================================== #include #include #include "hookapi.h" // Macro for adding pointers/DWORDs without C arithmetic interfering #define MakePtr(cast,ptr,addValue)(cast)((DWORD)(ptr)+(DWORD)(addValue)) DWORD GetModuleBaseFromWin32sHMod(HMODULE hMod); // Prototype PROC WINAPI HookImportedFunction( HMODULE hFromModule, // Module to intercept calls from PSTR pszFunctionModule, // Module to intercept calls to PSTR pszFunctionName, // Function to intercept calls to PROC pfnNewProc) // New function (replaces original) { PROC pfnOriginalProc; PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNTHeader; PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PIMAGE_THUNK_DATA pThunk; if ( IsBadCodePtr(pfnNewProc) ) // Verify that a valid pfn was passed return 0; // Verify the the module and function names passed to us are valid pfnOriginalProc = GetProcAddress(GetModuleHandle(pszFunctionModule), pszFunctionName ); if ( !pfnOriginalProc ) return 0; if ( (GetVersion() & 0xC0000000) == 0x80000000 ) pDosHeader = // Win32s (PIMAGE_DOS_HEADER)GetModuleBaseFromWin32sHMod(hFromModule); else pDosHeader = (PIMAGE_DOS_HEADER)hFromModule; // other // Tests to ensure we have a module image (the 'MZ' header) if ( IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) ) return 0; if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ) return 0; // The MZ header has a pointer to the PE header pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew); // More tests to make sure we're looking at a "PE" image if ( IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) ) return 0; if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE ) return 0; // We know have a valid pointer to the module's PE header. Now // go get a pointer to its imports section (.idata) pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDosHeader, pNTHeader->OptionalHeader. DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]. VirtualAddress); // Bail out if the RVA of the imports section is 0 (doesn't exist) if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader ) return FALSE; // Iterate through the array of imported module descriptors, looking // for the module whose name matches the pszFunctionModule parameter while ( pImportDesc->Name ) { PSTR pszModName = MakePtr(PSTR, pDosHeader, pImportDesc->Name); if ( stricmp(pszModName, pszFunctionModule) == 0 ) break; pImportDesc++; // Advance to next imported module descriptor } // Bail out if we didn't find the import module descriptor for the // specified module. pImportDesc->Name will be non-zero if found. if ( pImportDesc->Name == 0 ) return 0; // Get a pointer to the found module's import address table (IAT) pThunk = MakePtr(PIMAGE_THUNK_DATA, pDosHeader, pImportDesc->FirstThunk); // Blast through the table of import addresses, looking for the one // that matches the address we got back from GetProcAddress above. while ( pThunk->u1.Function ) { if ( pThunk->u1.Function == (PDWORD)pfnOriginalProc ) { // We found it! Overwrite the original address with the // address of the interception function. Return the original // address to the caller so that they can chain on to it. pThunk->u1.Function = (PDWORD)pfnNewProc; return pfnOriginalProc; } pThunk++; // Advance to next imported function address } return 0; // Function not found } typedef DWORD (__stdcall *XPROC)(DWORD); // Converts an HMODULE under Win32s to a base address in memory DWORD GetModuleBaseFromWin32sHMod(HMODULE hMod) { XPROC ImteFromHModule, BaseAddrFromImte; HMODULE hModule; DWORD imte; hModule = GetModuleHandle("W32SKRNL.DLL"); if( !hModule ) return 0; ImteFromHModule=(XPROC)GetProcAddress(hModule,"_ImteFromHModule@4"); if ( !ImteFromHModule ) return 0; BaseAddrFromImte=(XPROC)GetProcAddress(hModule,"_BaseAddrFromImte@4"); if ( !BaseAddrFromImte ) return 0; imte = ImteFromHModule( (DWORD)hMod); if ( !imte ) return 0; return BaseAddrFromImte(imte); }