我编写了这个函数来将DLL注入到运行的进程中:
DLL_Results CDLL_Loader::InjectDll()
{
DWORD ThreadTeminationStatus;
LPVOID VirtualMem;
HANDLE hProcess, hRemoteThread;
HMODULE hModule;
if (!isInit())
return NOT_INIT;
if (isInjected())
return DLL_ALREADY_HOOKED;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
if (hProcess == NULL)
return PROCESS_ERROR_OPEN;
VirtualMem = VirtualAllocEx (hProcess, NULL, strlen(DllFilePath), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (VirtualMem == NULL)
return PROCESS_ERRORR_VALLOC;
if (WriteProcessMemory(hProcess, (LPVOID)VirtualMem, DllFilePath, strlen(DllFilePath), NULL) == 0)
{
VirtualFreeEx(hProcess, NULL, (size_t)strlen(DllFilePath), MEM_RESERVE|MEM_COMMIT);
CloseHandle(hProcess);
return PROCESS_ERROR_WRITE;
}
hModule = GetModuleHandle(L"kernel32.dll");
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA"),
(LPVOID)VirtualMem, 0, NULL);
if (hRemoteThread == NULL)
{
FreeLibrary(hModule);
VirtualFreeEx(hProcess, NULL, (size_t)strlen(DllFilePath), MEM_RESERVE | MEM_COMMIT);
CloseHandle(hProcess);
return PROCESS_ERROR_CREATE_RTHREAD;
}
WaitForSingleObject(hRemoteThread, INFINITE);
GetExitCodeThread(hRemoteThread, &ThreadTeminationStatus);
FreeLibrary(hModule);
VirtualFreeEx(hProcess, NULL, (size_t)strlen(DllFilePath), MEM_RESERVE | MEM_COMMIT);
CloseHandle(hRemoteThread);
CloseHandle(hProcess);
injected = true;
return DLLHOOK_OK;
}
它工作得很好,但是当我试图弹出dll时,我无法找到有关解钩的信息。我试着建立一些函数来做这个,我想我已经很接近了这是我目前得到的:
是正确的方式吗?如果是这样,我应该在createRemoteThread中传递什么参数而不是VirtualMem(在注入函数中使用)…
DLL_Results CDLL_Loader::EjectDll()
{
DWORD ThreadTeminationStatus;
HANDLE hProcess, hRemoteThread;
HMODULE hModule;
if (isInjected())
return DLLEJECT_OK;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
if (hProcess == NULL)
return PROCESS_ERROR_OPEN;
hModule = GetModuleHandle(L"kernel32.dll");
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary"),
/*(LPVOID)VirtualMem <- What do i need to send here?*/, 0, NULL);
if (hRemoteThread != NULL)
{
WaitForSingleObject(hRemoteThread, INFINITE);
GetExitCodeThread(hRemoteThread, &ThreadTeminationStatus);
}
CloseHandle(hRemoteThread);
CloseHandle(hProcess);
injected = false;
return DLLEJECT_OK;
}
在32位系统上,GetExitCodeThread
后面的ThreadTeminationStatus
的值包含远程进程中LoadLibraryA
的返回值。这是新加载的dll的模块句柄。您可以将其用作远程线程中FreeLibrary
的参数。
如果您想在64位Windows上使用该代码,线程退出代码将被截断为32位DWORD
,因此它不可用。您必须在远程进程中创建一个可调用的例程(如Necrolis所建议的),或者通过psapi或Toolhelp API (CreateToolhelp32Snapshot
, Module32First
, Module32Next
)查找DLL的模块基。
你需要把你注入的dll的HANDLE
传递给它,否则你可以把VirtualMem
传递给它,但是你的远程线程例程需要是:
DWORD WINAPI UnloadDll(void* pMem)
{
FreeLibrary(GetModuleHandleA((const char*)pMem));
return 0;
}
然而,通常你注入的dll应该卸载自己(参见DllMain
如何工作),手动或自动当主机关闭