Windows进程DLL注入成功后调用导出函数失败的原因排查
DLL注入后调用导出函数提示不存在的问题排查
我尝试将DLL注入Windows进程(如notepad.exe),注入操作能正常完成,但调用已注入DLL的导出函数时,系统提示该进程中不存在此函数。以下是注入器代码、DLL代码及相关截图,求排查原因。
注入器代码
#include <Windows.h> #include <stdio.h> #include <cassert> #include <TlHelp32.h> // 用于枚举远程进程中的模块 // 获取远程加载模块的句柄 HMODULE GetRemoteModuleHandle(HANDLE hProcess, const wchar_t* moduleName) { HMODULE hModule = nullptr; MODULEENTRY32 me = { sizeof(me) }; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetProcessId(hProcess)); if (hSnapshot == INVALID_HANDLE_VALUE) return nullptr; if (Module32First(hSnapshot, &me)) { do { if (_wcsicmp(me.szModule, moduleName) == 0) { hModule = me.hModule; break; } } while (Module32Next(hSnapshot, &me)); } CloseHandle(hSnapshot); return hModule; } int main(int argc, const char* argv[]) { if (argc < 3) { printf("用法: Inyector <pid> <dllPath>\n"); return 0; } auto pid = atoi(argv[1]); // 打开目标进程 HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD, FALSE, pid); if (!hProcess) { printf("打开进程失败 (%u)\n", GetLastError()); return 1; } // 在目标进程中分配内存 auto p = VirtualAllocEx(hProcess, nullptr, 1 << 12, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); assert(p); // 将DLL路径写入目标进程内存 WriteProcessMemory(hProcess, p, argv[2], strlen(argv[2]) + 1, nullptr); // 创建远程线程调用LoadLibraryA加载DLL auto hThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA"), p, 0, nullptr); assert(hThread); WaitForSingleObject(hThread, INFINITE); // 获取远程进程中加载的模块句柄 HMODULE remoteModule = GetRemoteModuleHandle(hProcess, L"mydll.dll"); if (!remoteModule) { printf("错误: 无法找到远程模块\n"); return 1; } // 获取本地DLL中导出函数的地址 auto funcAddr = (LPVOID)GetProcAddress(GetModuleHandle(L"mydll.dll"), "MyFunc"); if (!funcAddr) { printf("错误: 无法找到函数 'MyFunc'\n"); return 1; } // 计算远程进程中函数的地址 uintptr_t remoteFuncAddr = (uintptr_t)funcAddr - (uintptr_t)GetModuleHandle(L"mydll.dll") + (uintptr_t)remoteModule; // 创建远程线程调用MyFunc auto hFuncThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)remoteFuncAddr, nullptr, 0, nullptr); if (!hFuncThread) { printf("错误: 无法执行远程函数 (%u)\n", GetLastError()); } else { printf("远程函数执行成功.\n"); } // 清理资源 CloseHandle(hFuncThread); CloseHandle(hThread); CloseHandle(hProcess); return 0; }
DLL代码
#include <windows.h> // 导出函数 extern "C" __declspec(dllexport) void MyFunc(long parm1) { for (int i = 1; i <= 10; i++) { // 循环弹出消息框 MessageBox( NULL, // 父窗口(无) L"这是测试消息", // 消息文本 L"MessageBox循环", // 标题 MB_OK | MB_ICONINFORMATION // OK按钮+信息图标 ); } } // DLL入口函数(可选) BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
相关截图


可能的原因及解决方案
函数参数不匹配:
DLL中MyFunc定义需要一个long类型参数,但注入器调用时传入的是nullptr,未提供对应参数。这种参数不匹配可能触发进程异常,导致系统误报“函数不存在”。需确保调用时传入正确参数,比如修改CreateRemoteThread的参数传递部分:// 分配内存存储参数 long param = 123; LPVOID pParam = VirtualAllocEx(hProcess, nullptr, sizeof(long), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); WriteProcessMemory(hProcess, pParam, ¶m, sizeof(long), nullptr); // 创建线程时传入参数地址 auto hFuncThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)remoteFuncAddr, pParam, 0, nullptr);导出函数名称修饰问题:
尽管使用了extern "C",仍可能因编译选项问题导致函数名被修饰。从截图确认导出表中的函数名是否为MyFunc,建议添加.def文件强制指定导出名称:
创建mydll.def文件,内容如下:LIBRARY "mydll" EXPORTS MyFunc @1将该文件加入DLL项目编译,确保函数以纯名称导出。
位数不匹配:
注入器、目标进程、DLL的编译位数必须一致(同为32位或64位)。如果32位注入器操作64位进程,CreateToolhelp32Snapshot无法正确枚举模块,导致远程模块基地址计算错误,进而函数地址无效。DLL版本不一致:
注入器本地加载的DLL与注入到远程进程的DLL如果不是同一版本,会导致函数偏移计算错误。需确保本地和远程使用的是同一个DLL文件。权限或进程保护:
目标进程可能有反注入保护,或注入器未以管理员身份运行,导致远程线程无法执行。尝试提升注入器权限,或更换无保护的测试进程(如notepad.exe)。
内容的提问来源于stack exchange,提问作者Javier
相关产品推荐
相关产品推荐

