Frage zu Api Hooking
-
Hallo,
ich versuche seit einiger Zeit eine Funktion zu hooken indem ich die IAT überschreibe. Das klappt auch ganz gut wenn ich es wie folgt mache.
Wenn ich allerdings vor dem Aufruf von set_hook die Funktion strncpy aufrufe oder nur die Adresse ausgeben lasse, funktioniert set_hook nicht mehr und die Adresse in der IAT wird nicht überschrieben.
Dabei werden aber keine Fehler ausgegeben und GetLastError() enthält auch keine Fehler.Woran liegt das?
#include "stdafx.h" #include <windows.h> #include <imagehlp.h> #include <stdio.h> #include <stdlib.h> #include <string.h> HANDLE hModule = INVALID_HANDLE_VALUE; PROC orig_strncpy = 0; typedef char * __cdecl strncpy_t(char *, char const *, size_t); char * __cdecl my_strncpy(char * dest, char const * src, size_t len) { char * ReturnValue; strncpy_t * fn = (strncpy_t *) orig_strncpy; ReturnValue = (*fn)(dest, "Hallo Geld", len); return ReturnValue; } BOOL set_hook(HMODULE hModuleOfCaller, LPSTR LibraryName, PROC OldFunctionPointer, PROC NewFunctionPointer); int main(int argc, char **argv) { char src[] = "Hallo Welt"; char dest[11]; HMODULE mod = GetModuleHandle("Application.exe"); HMODULE lib = LoadLibrary("MSVCR80.DLL"); PROC old_fun = GetProcAddress(lib, "strncpy"); set_hook(mod, "MSVCR80.DLL", old_fun, (PROC) my_strncpy); strncpy(dest, src, 11); printf("src: %s\n", src); printf("dest: %s\n", dest); fgetc(stdin); return 0; }BOOL set_hook(HMODULE hModuleOfCaller, LPSTR LibraryName, PROC OldFunctionPointer, PROC NewFunctionPointer) { if(hModuleOfCaller == hModule) return FALSE; if(hModuleOfCaller == 0) return FALSE; ULONG ulSize; // Get the address of the module’s import section PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(hModuleOfCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize); // Does this module have an import section ? if (pImportDesc == NULL) return FALSE; // Loop through all descriptors and find the // import descriptor containing references to callee’s functions while(pImportDesc->Name) { PSTR pszModName = (PSTR)((PBYTE) hModuleOfCaller + pImportDesc->Name); if(_stricmp(pszModName, LibraryName) == 0) break; // Found pImportDesc++; } // while if (pImportDesc->Name == 0) return FALSE; //Get caller’s IAT PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)( (PBYTE) hModuleOfCaller + pImportDesc->FirstThunk ); PROC pfnCurrent = OldFunctionPointer; // Replace current function address with new one while(pThunk->u1.Function) { // Get the address of the function address PROC* ppfn = (PROC*) &pThunk->u1.Function; // Is this the function we’re looking for? BOOL bFound = (*ppfn == pfnCurrent); if(bFound) { MEMORY_BASIC_INFORMATION mbi; ::VirtualQuery(ppfn, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); // In order to provide writable access to this part of the // memory we need to change the memory protection if (FALSE == ::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect)) return FALSE; if(orig_strncpy == 0) orig_strncpy = *ppfn; *ppfn = *NewFunctionPointer; BOOL bResult = TRUE; // Restore the protection back DWORD dwOldProtect; ::VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect); break; } pThunk++; } return TRUE; }
-
Konrad schrieb:
Wenn ich allerdings vor dem Aufruf von set_hook die Funktion strncpy aufrufe oder nur die Adresse ausgeben lasse,
funktioniert set_hook nicht mehr und die Adresse in der IAT wird nicht überschrieben.Poste mal was "VirtualQuery ()" in "set_hook ()" in beiden Fällen liefert. Könnte ev. ein Kompiler / Linker - Problem sein.
-
In beiden Fällen 28.
-
Offenbar kann "VirtualProtect ()" "PAGE_READWRITE" nicht setzen, wenn vorher lesend auf die IAT zugegriffen wurde (warum auch immer).
Was steht denn in beiden Fällen in "mbi.Protect" ?
-
In beiden Fällen wird aus PAGE_READONLY PAGE_READWRITE
-
Wenn in beiden Fällen PAGE_READWRITE gesetzt werden konnte, dann wird in beiden Fällen auch die Adresse in der IAT überschrieben.
Wie testest Du, ob die Adresse überschrieben wurde ?
-
Testen tue ich das wie folgt:
strncpy(dest, src, 11); printf("src: %s\n", src); printf("dest: %s\n", dest);Wenn die Adresse überschrieben worden wäre, müsste im 2. String "Hallo Geld" anstatt "Hallo Welt" stehen.
Wenn es geklappt hat ist &strncpy und &my_strncpy == 00401080.
Wenn es wegen dem vorherigen Zugriff nicht geklappt hat ist die Adresse von &strncpy 781803F0.Die Protect Werte habe ich über mbi.Protect und über dwOldProtect ausgelesen..
-
Eigentlich alles ok soweit. Tritt der Fehler auch im "Release-Mode" auf ?
-
Jo, hab die ganze Zeit im Release Mode kompiliert.
-
Hallo,
wäre vielleicht jemand so nett und würde das Programm mal bei sich testen? Das ganze ist ein Standard Konsolen Programm und dbghelp.lib wird dazugelinkt.
Output müsste folgendes sein:
src: Hallo Welt
dest: Hallo GeldEinmal zusätzlich mit folgendem Code _vor_ dem set_hook.
strncpy(dest, src, 11); printf("src: %s\n", src); printf("dest: %s\n", dest);Danke
