Как изменить таблицу на время выполнения загруженной DLL
Я хочу подключить функции, которые вызываются из загруженной DLL во время выполнения, я использовал класс CAPIHook из книги "Windows через C/C++" (DLL-инъекция, сделанная путем установки системного крючка и подключения путем изменения IAT), но этот код работает только в том случае, если имя/символы DLL существуют в IAT в исполняемом файле. (т. е. для неявной ссылки DLL)
это код DLL:
CAPIHook::CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook) {
// Note: the function can be hooked only if the exporting module
// is already loaded. A solution could be to store the function
// name as a member; then, in the hooked LoadLibrary* handlers, parse
// the list of CAPIHook instances, check if pszCalleeModName
// is the name of the loaded module to hook its export table and
// re-hook the import tables of all loaded modules.
m_pNext = sm_pHead; // The next node was at the head
sm_pHead = this; // This node is now at the head
// Save information about this hooked function
m_pszCalleeModName = pszCalleeModName;
m_pszFuncName = pszFuncName;
m_pfnHook = pfnHook;
m_pfnOrig = GetProcAddressRaw(GetModuleHandleA(pszCalleeModName), m_pszFuncName);
// If function does not exit,... bye bye
// This happens when the module is not already loaded
if (m_pfnOrig == NULL)
{
wchar_t szPathname[MAX_PATH];
GetModuleFileNameW(NULL, szPathname, _countof(szPathname));
wchar_t sz[1024];
StringCchPrintfW(sz, _countof(sz),
TEXT("[%4u - %s] impossible to find %Srn"),
GetCurrentProcessId(), szPathname, pszFuncName);
OutputDebugString(sz);
return;
}
// Hook this function in all currently loaded modules
ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook);
}
это функции-ловушки:
HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath) {
HMODULE hmod = ::LoadLibraryA(pszModulePath);
FixupNewlyLoadedModule(hmod, 0);
return(hmod);
}
HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) {
HMODULE hmod = ::LoadLibraryW(pszModulePath);
FixupNewlyLoadedModule(hmod, 0);
return(hmod);
}
HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszModulePath,
HANDLE hFile, DWORD dwFlags) {
HMODULE hmod = ::LoadLibraryExA(pszModulePath, hFile, dwFlags);
FixupNewlyLoadedModule(hmod, dwFlags);
return(hmod);
}
HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszModulePath,
HANDLE hFile, DWORD dwFlags) {
HMODULE hmod = ::LoadLibraryExW(pszModulePath, hFile, dwFlags);
FixupNewlyLoadedModule(hmod, dwFlags);
return(hmod);
}
метод замены IAT:
void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) {
// Get the address of the module's import section
ULONG ulSize;
// An exception was triggered by Explorer (when browsing the content of
// a folder) into imagehlp.dll. It looks like one module was unloaded...
// Maybe some threading problem: the list of modules from Toolhelp might
// not be accurate if FreeLibrary is called during the enumeration.
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
__try {
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
}
__except (InvalidReadExceptionFilter(GetExceptionInformation())) {
// Nothing to do in here, thread continues to run normally
// with NULL for pImportDesc
}
if (pImportDesc == NULL)
return; // This module has no import section or is no longer loaded
// Find the import descriptor containing references to callee's functions
for (; pImportDesc->Name; pImportDesc++) {
PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
if (lstrcmpiA(pszModName, pszCalleeModName) == 0) {
// Get caller's import address table (IAT) for the callee's functions
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
((PBYTE) hmodCaller + pImportDesc->FirstThunk);
// Replace current function address with new function address
for (; pThunk->u1.Function; pThunk++) {
// 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) {
if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) {
DWORD dwOldProtect;
if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY,
&dwOldProtect)) {
WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,
sizeof(pfnNew), NULL);
VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect,
&dwOldProtect);
}
}
return; // We did it, get out
}
}
} // Each import section is parsed until the right entry is found and patched
}
}
автор добавил комментарии, чтобы добавить эту функциональность, но я не уверен, как это сделать
Примечание: функция может быть только если модуль экспорта уже загружен. Решением может быть сохранение функции имя как член; затем в обработчиках крючков LoadLibrary* выполните синтаксический анализ список экземпляров CAPIHook, проверьте, если pszCalleeModName имя загруженного модуля для подключения его экспорта стол и повторно подключите таблицы импорта всех загруженных модулей.
Он также напишет это в книге, но опять же я не знаю, что делать
возможное решение-использовать подключенные функции LoadLibrary* для определить, когда модуль экспортирует функцию unpatched hooked и затем выполните два действия:
снова подключите таблицу импорта уже загруженного модуля, потому что она теперь можно вызвать GetProcAddress и получить указатель на оригинал реализация функции для подключения. Обратите внимание, что название функция должна быть сохранена как член класса и установлена в конструктор.
сразу уточните эту подключенную функцию в таблице адреса экспорта модуль экспорта, как показано в реализации Функция ReplaceEATEntryInOneMod. Таким образом, все новые модули вызова функция hooked вызовет наш обработчик
Я пытаюсь изменить IAT после загрузка DLL, но моя функция подключения не называется
HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) {
HMODULE hmod = ::LoadLibraryW(pszModulePath);
if (StrCmpIW(pszModulePath, myDLLUnicodeName.c_str()) == 0 ) {
PROC proc = GetProcAddressRaw(GetModuleHandleA(myDLLName.c_str()), myFunctionName.c_str());
if ( proc != NULL ) {
for (CAPIHook* p = sm_pHead; p != NULL; p = p->m_pNext) {
if (StrCmpIA(p->m_pszCalleeModName, myDLLName.c_str()) == 0) {
MessageBox(NULL, L"This is the New Dynamic DLL", L"Test!", 0);
ReplaceIATEntryInAllMods(p->m_pszCalleeModName, proc , p->m_pfnHook);
}
}
}
}
FixupNewlyLoadedModule(hmod, 0);
return(hmod);
}
Итак, как изменить этот код для обработки динамического случая загрузки ?
1 ответов
Я делал это раньше. То, что вы хотите, это есть hooking вместо IAT. Кроме того, зацепите сам API ::LoadLibrary, чтобы вы знали, когда загружается DLL, и зацепите запрошенный api из DLL после его загрузки.
в интернете есть несколько примеров того, как это сделать. Вот одна, которую я только что нашел.: http://board.cheat-project.com/showthread.php?t=10633