void patchDescriptor(HMODULE hModule, const char *szModule, T pImportDescriptor) { const char* szDescriptorName = getDescriptorName(hModule, pImportDescriptor); ModulesMap::const_iterator modIt = modulesMap.find(szDescriptorName); if (modIt != modulesMap.end()) { const char *szMatchModule = modIt->first; // same as szDescriptorName const Module & module = modIt->second; const FunctionMap & functionMap = module.functionMap; FunctionMap::const_iterator fnIt; for (fnIt = functionMap.begin(); fnIt != functionMap.end(); ++fnIt) { const char *szFunctionName = fnIt->first; LPVOID lpNewAddress = fnIt->second; BOOL bHooked; bHooked = patchFunction(hModule, szModule, szMatchModule, pImportDescriptor, szFunctionName, lpNewAddress); if (bHooked && !module.bInternal && pSharedMem) { pSharedMem->bReplaced = TRUE; } } } }
// See // http://www.microsoft.com/msj/1298/hood/hood1298.aspx // http://msdn.microsoft.com/en-us/library/16b2dyk5.aspx static LPVOID * getOldFunctionAddress(HMODULE hModule, PImgDelayDescr pDelayDescriptor, const char* pszFunctionName) { assert(pDelayDescriptor->rvaDLLName != 0); return getOldFunctionAddress(hModule, getDescriptorName(hModule, pDelayDescriptor), pDelayDescriptor->rvaINT, pDelayDescriptor->rvaIAT, pszFunctionName); }
static LPVOID * getOldFunctionAddress(HMODULE hModule, PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor, const char* pszFunctionName) { assert(pImportDescriptor->TimeDateStamp != 0 || pImportDescriptor->Name != 0); return getOldFunctionAddress(hModule, getDescriptorName(hModule, pImportDescriptor), pImportDescriptor->OriginalFirstThunk, pImportDescriptor->FirstThunk, pszFunctionName); }
void patchDescriptor(HMODULE hModule, const char *szModule, T pImportDescriptor, Action action) { const char* szDescriptorName = getDescriptorName(hModule, pImportDescriptor); ModulesMap::const_iterator modIt = modulesMap.find(szDescriptorName); if (modIt != modulesMap.end()) { const char *szMatchModule = modIt->first; // same as szDescriptorName const Module & module = modIt->second; const FunctionMap & functionMap = module.functionMap; FunctionMap::const_iterator fnIt; for (fnIt = functionMap.begin(); fnIt != functionMap.end(); ++fnIt) { const char *szFunctionName = fnIt->first; LPVOID lpHookAddress = fnIt->second; // Knowning the real address is useful when patching imports by ordinal LPVOID lpRealAddress = NULL; HMODULE hRealModule = GetModuleHandleA(szDescriptorName); if (hRealModule) { // FIXME: this assertion can fail when the wrapper name is the same as the original DLL //assert(hRealModule != g_hHookModule); if (hRealModule != g_hHookModule) { lpRealAddress = (LPVOID)GetProcAddress(hRealModule, szFunctionName); } } LPVOID lpOldAddress = lpRealAddress; LPVOID lpNewAddress = lpHookAddress; if (action == ACTION_UNHOOK) { std::swap(lpOldAddress, lpNewAddress); } BOOL bPatched; bPatched = patchFunction(hModule, szModule, szMatchModule, pImportDescriptor, szFunctionName, lpOldAddress, lpNewAddress); if (action == ACTION_HOOK && bPatched && !module.bInternal && pSharedMem) { pSharedMem->bReplaced = TRUE; } } } }
static void patchModule(HMODULE hModule, const char *szModule, Action action) { /* Never patch this module */ if (hModule == g_hThisModule) { return; } /* Never patch our hook module */ if (hModule == g_hHookModule) { return; } /* Hook modules only once */ if (action == ACTION_HOOK) { std::pair< std::set<HMODULE>::iterator, bool > ret; EnterCriticalSection(&Mutex); ret = g_hHookedModules.insert(hModule); LeaveCriticalSection(&Mutex); if (!ret.second) { return; } } const char *szBaseName = getBaseName(szModule); /* Don't hook our replacement modules to avoid tracing internal APIs */ /* XXX: is this really a good idea? */ if (isMatchModuleName(szBaseName)) { return; } /* Leave these modules alone */ if (stricmp(szBaseName, "kernel32.dll") == 0 || stricmp(szBaseName, "ConEmuHk.dll") == 0) { return; } if (VERBOSITY > 0) { debugPrintf("inject: found module %s\n", szModule); } PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = getFirstImportDescriptor(hModule, szModule); if (pImportDescriptor) { while (pImportDescriptor->FirstThunk) { patchDescriptor(hModule, szModule, pImportDescriptor, action); ++pImportDescriptor; } } PImgDelayDescr pDelayDescriptor = getDelayImportDescriptor(hModule, szModule); if (pDelayDescriptor) { while (pDelayDescriptor->rvaDLLName) { if (VERBOSITY > 1) { const char* szName = getDescriptorName(hModule, pDelayDescriptor); debugPrintf("inject: found %sdelay-load import entry for module %s\n", pDelayDescriptor->grAttrs & dlattrRva ? "" : "old-style ", szName); } patchDescriptor(hModule, szModule, pDelayDescriptor, action); ++pDelayDescriptor; } } }
static void patchModule(HMODULE hModule, const char *szModule, Action action) { /* Never patch this module */ if (hModule == g_hThisModule) { return; } /* Never patch our hook module */ if (hModule == g_hHookModule) { return; } /* Hook modules only once */ if (action == ACTION_HOOK) { std::pair< std::set<HMODULE>::iterator, bool > ret; EnterCriticalSection(&g_Mutex); ret = g_hHookedModules.insert(hModule); LeaveCriticalSection(&g_Mutex); if (!ret.second) { return; } } const char *szBaseName = getBaseName(szModule); /* Don't hook our replacement modules to avoid tracing internal APIs */ /* XXX: is this really a good idea? */ if (isMatchModuleName(szBaseName)) { return; } /* Leave these modules alone. * * Hooking other injection DLLs easily leads to infinite recursion (and * stack overflow), especially when those libraries use techniques like * modifying the hooked functions prolog (instead of patching IAT like we * do). * * See also: * - http://www.nynaeve.net/?p=62 */ if (stricmp(szBaseName, "kernel32.dll") == 0 || stricmp(szBaseName, "AcLayers.dll") == 0 || stricmp(szBaseName, "ConEmuHk.dll") == 0 || stricmp(szBaseName, "gameoverlayrenderer.dll") == 0 || stricmp(szBaseName, "gameoverlayrenderer64.dll") == 0) { return; } if (VERBOSITY > 0) { debugPrintf("inject: found module %s\n", szModule); } PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = getFirstImportDescriptor(hModule, szModule); if (pImportDescriptor) { while (pImportDescriptor->FirstThunk) { patchDescriptor(hModule, szModule, pImportDescriptor, action); ++pImportDescriptor; } } PImgDelayDescr pDelayDescriptor = getDelayImportDescriptor(hModule, szModule); if (pDelayDescriptor) { while (pDelayDescriptor->rvaDLLName) { if (VERBOSITY > 1) { const char* szName = getDescriptorName(hModule, pDelayDescriptor); debugPrintf("inject: found %sdelay-load import entry for module %s\n", pDelayDescriptor->grAttrs & dlattrRva ? "" : "old-style ", szName); } patchDescriptor(hModule, szModule, pDelayDescriptor, action); ++pDelayDescriptor; } } }