我想在一个进程中卸载一些模块。
我使用这个功能:
bool UnInjectDll(const TCHAR* ptszDllFile, DWORD dwProcessId)
{
if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile))
{
return false;
}
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if (INVALID_HANDLE_VALUE == hModuleSnap)
{
return false;
}
MODULEENTRY32 me32;
memset(&me32, 0, sizeof(MODULEENTRY32));
me32.dwSize = sizeof(MODULEENTRY32);
if(FALSE == ::Module32First(hModuleSnap, &me32))
{
::CloseHandle(hModuleSnap);
return false;
}
bool isFound = false;
do
{
isFound = (0 == ::_tcsicmp(me32.szModule, ptszDllFile) || 0 == ::_tcsicmp(me32.szExePath, ptszDllFile));
if (isFound)
{
break;
}
} while (TRUE == ::Module32Next(hModuleSnap, &me32));
::CloseHandle(hModuleSnap);
if (false == isFound)
{
return false;
}
hProcess = ::OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION, FALSE, dwProcessId);
if (NULL == hProcess)
{
return false;
}
LPTHREAD_START_ROUTINE lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "FreeLibrary");
if (NULL == lpThreadFun)
{
::CloseHandle(hProcess);
return false;
}
hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, me32.modBaseAddr , 0, NULL);
if (NULL == hThread)
{
::CloseHandle(hProcess);
return false;
}
::WaitForSingleObject(hThread, INFINITE);
::CloseHandle(hThread);
::CloseHandle(hProcess);
return true;
}
但是当我使用这个代码时,它不能从我想从项目中卸载的特殊模块。
我也使用"过程侦探"这样做的工具,但这个工具也不能这样做。
现在我想要一个可以确保从我想要的进程中卸载特殊模块的函数。例如,你创建一个只显示消息框的简单程序,现在如果你看到它的模块的进程,它有一个模块ntdll.dll和一些其他模块,现在你不能删除ntdll.dll模块或一些来自它的其他模块。我想要一个函数来强制进程从我想要的进程中删除任何模块。
答案 0 :(得分:1)
你想做的事情是完全危险的(据我所知,幸运的是,不可能)。
您的程序或库与某些其他DLL链接。这些库反过来也引用其他库,依此类推,等等。当您的程序或DLL由Windows加载程序加载到内存空间时,这些“依赖项”也将被加载,您的导入地址表将被修补,以便您的调用知道在执行它们时将跳转到哪里。所有代码都将作为原子实体硬连接在一起。
卸载以这种方式静态链接的DLL(.dll文件也可以静态链接,不要与静态.lib文件混淆)基本上强制你的应用程序崩溃第二次任何调用依赖于libarary - 尤其是ntdll.dll
,它将成为您链接的所有lib的大部分根。这些电话将被抛入虚空。这些库无法卸载,因为它们在程序中属于某种意义。
如果您在运行时动态加载了库,则可以随时卸载它。由于您可能无论如何都使用GetProcAddress
通过动态地址工作,因此您需要确保您的函数指针具有有效目标。
你可以随心所欲地戴上帽子,但你不能(也不应该)撕掉你的心脏;)
虽然我知道,它并没有完全回答你的问题,但是这只是一个警告,你不应该在没有非常好的理由(我不知道你真的有)的情况下这样做,我是相当积极的你不能做你所要求的 - 但我很高兴让其他人在这里纠正我。
如果你想对加载的库做一些事情,并且你已经在这个破坏性的过程中,只需直接覆盖内存中的库或IAT。当然,你可以用撬棍进去,但我认为你不会想要找到你想要的东西......