DLL注入后拦截目标进程LoadLibrary调用及Detour失效排查
问题描述
通过CreateRemoteThread将DLL注入目标进程后,希望该DLL拦截目标进程发起的LoadLibraryA/W调用,仅获取待加载DLL的完整路径及名称,不修改原调用行为。尝试用Detour库拦截LoadLibraryW后弹窗始终未触发,观察Procmon记录到的操作是CreateFile而非LoadLibrary,拦截CreateFileA也无效,求原因。
附上相关代码:
// dllmain.cpp : Defines the entry point for the DLL application. #include "pch.h" #include <stdio.h> #include <windows.h> #include "detours.h" // Target pointer for the uninstrumented LoadLibraryW API. // static HMODULE(WINAPI* TrueLoadLibrary)(LPCWSTR lpLibFileName) = LoadLibraryW; // Detour function that replaces the LoadLibrary API. // HMODULE WINAPI DetouredLoadLibrary(LPCWSTR lpLibFileName) { HMODULE res = TrueLoadLibrary(lpLibFileName); MessageBoxW(NULL, lpLibFileName, L"Detoured!", MB_OK | MB_ICONEXCLAMATION); return res; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { if (DetourIsHelperProcess()) { return TRUE; } if (ul_reason_for_call == DLL_PROCESS_ATTACH) { DetourRestoreAfterWith(); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)TrueLoadLibrary, DetouredLoadLibrary); DetourTransactionCommit(); } else if (ul_reason_for_call == DLL_PROCESS_DETACH) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)TrueLoadLibrary, DetouredLoadLibrary); DetourTransactionCommit(); } return TRUE; }
问题原因与解决方案
核心原因分析
- 拦截API范围不全:你只拦截了
LoadLibraryW,但目标进程可能实际调用的是LoadLibraryA、LoadLibraryExA/W,甚至底层的LdrLoadDll(ntdll.dll中负责DLL加载的核心函数)。Procmon记录的CreateFile是LoadLibrary内部的文件操作步骤,直接拦截CreateFile会因调用层级过多、参数无法对应而失效。 - DllMain中执行Detour的局限性:
DLL_PROCESS_ATTACH时仅对当前线程执行DetourUpdateThread,无法覆盖进程中所有线程;且DllMain属于加载临界区,执行Hook操作容易引发死锁或加载顺序问题。 - 弹窗的兼容性问题:若目标进程是无窗口服务、控制台进程,或当前线程处于非UI环境,
MessageBoxW可能无法正常显示,导致你误以为拦截未生效。
修正方案与代码示例
- 扩展拦截API集合:覆盖所有常见的DLL加载API,包括
LoadLibraryA/W、LoadLibraryExA/W;必要时可追加拦截LdrLoadDll。 - 在独立线程中初始化Detour:避免在DllMain中执行Hook操作,创建单独线程完成初始化,降低死锁风险。
- 替换弹窗为文件日志:用日志文件记录加载路径,规避UI环境限制导致的误判。
修正后的代码:
// dllmain.cpp : Defines the entry point for the DLL application. #include "pch.h" #include <stdio.h> #include <windows.h> #include "detours.h" // 原始函数指针 static HMODULE(WINAPI* TrueLoadLibraryA)(LPCSTR lpLibFileName) = LoadLibraryA; static HMODULE(WINAPI* TrueLoadLibraryW)(LPCWSTR lpLibFileName) = LoadLibraryW; static HMODULE(WINAPI* TrueLoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) = LoadLibraryExA; static HMODULE(WINAPI* TrueLoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) = LoadLibraryExW; // 日志写入函数 void LogDllLoad(const wchar_t* dllPath) { FILE* fp = _wfopen(L"dll_load_log.txt", L"a"); if (fp) { fwprintf(fp, L"Loaded DLL: %s\n", dllPath); fclose(fp); } } void LogDllLoadA(const char* dllPath) { wchar_t wPath[MAX_PATH] = {0}; MultiByteToWideChar(CP_ACP, 0, dllPath, -1, wPath, MAX_PATH); LogDllLoad(wPath); } // Hook函数实现 HMODULE WINAPI DetouredLoadLibraryA(LPCSTR lpLibFileName) { LogDllLoadA(lpLibFileName); return TrueLoadLibraryA(lpLibFileName); } HMODULE WINAPI DetouredLoadLibraryW(LPCWSTR lpLibFileName) { LogDllLoad(lpLibFileName); return TrueLoadLibraryW(lpLibFileName); } HMODULE WINAPI DetouredLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { LogDllLoadA(lpLibFileName); return TrueLoadLibraryExA(lpLibFileName, hFile, dwFlags); } HMODULE WINAPI DetouredLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { LogDllLoad(lpLibFileName); return TrueLoadLibraryExW(lpLibFileName, hFile, dwFlags); } // 初始化Hook的线程函数 DWORD WINAPI InitDetours(LPVOID param) { DetourRestoreAfterWith(); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); // 附加所有需要拦截的函数 DetourAttach(&(PVOID&)TrueLoadLibraryA, DetouredLoadLibraryA); DetourAttach(&(PVOID&)TrueLoadLibraryW, DetouredLoadLibraryW); DetourAttach(&(PVOID&)TrueLoadLibraryExA, DetouredLoadLibraryExA); DetourAttach(&(PVOID&)TrueLoadLibraryExW, DetouredLoadLibraryExW); LONG error = DetourTransactionCommit(); if (error != NO_ERROR) { FILE* fp = _wfopen(L"detour_error.txt", L"w"); if (fp) { fwprintf(fp, L"Detour commit failed: %ld\n", error); fclose(fp); } } return 0; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { if (DetourIsHelperProcess()) { return TRUE; } switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // 创建独立线程执行Hook初始化 CreateThread(NULL, 0, InitDetours, NULL, 0, NULL); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: // 卸载Hook DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)TrueLoadLibraryA, DetouredLoadLibraryA); DetourDetach(&(PVOID&)TrueLoadLibraryW, DetouredLoadLibraryW); DetourDetach(&(PVOID&)TrueLoadLibraryExA, DetouredLoadLibraryExA); DetourDetach(&(PVOID&)TrueLoadLibraryExW, DetouredLoadLibraryExW); DetourTransactionCommit(); break; } return TRUE; }
内容的提问来源于stack exchange,提问作者Dlionis
相关产品推荐
相关产品推荐

