前段时间做了一个东西,在所有进程中都挂接了自己的DLL,结果每次要重新编译DLL让其运行都需要重启计算机,这下可有点郁闷, 得想想办法手动卸载了这些DLL,因此变有了这个程序
原理:
通过在指定的进程中创建远程线程,然后在线程中调用FreeLibrary把相应的模块卸载就OK了,就这么简单,废话就不多说了,代码中我已经给出详尽的注释了
//
FreeModule.cpp : Defines the entry point for the application.
//
#include
"
stdafx.h
"

#define
MAX_MODULE_NAME_LEN 16

//
传入到远程线程中的参数结构定义
typedef
struct
tagThreadParam 
...
{
DWORD dwFreeLibrary; // FreeLibrary 地址
DWORD dwGetModuleHandle; // GetModuleHandle 地址
TCHAR szModuleName[MAX_MODULE_NAME_LEN];// 需要卸载的模块的名称
}
ThreadParam,
*
PThreadParam;


/**/
/*
远程线程函数
*/
void
RemoteThreadFun(PThreadParam PParam)
...
{
DWORD dwFreeLibrary;
DWORD dwGetModuleHandle;
DWORD dwModuleName;
dwFreeLibrary = PParam->dwFreeLibrary;
dwGetModuleHandle = PParam->dwGetModuleHandle;
dwModuleName = (DWORD)PParam->szModuleName;
// 释放的最高次数
DWORD dwCount = 100;
// 循环寻找指定模块的句柄,如果找到,那么调用FreeLibrary释放,
// 直到该模块被释放
__asm
...{
START:
push dwModuleName; // 模块名称压栈
call dwGetModuleHandle; // 调用GetModuleHandle
test eax,eax; //
jz OVER; // 没有找到模块返回
dec dwCount;
jz OVER; // 达到最高次数
push eax; // 模块句柄压栈
call dwFreeLibrary; // 调用FreeLibrary
test eax,eax;
jnz START;
OVER:
}
return;
}


/**/
/*
调整权限
*/
bool
AdjustPurview()
...
{
TOKEN_PRIVILEGES TokenPrivileges;
bool bRet;
HANDLE hToken;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &TokenPrivileges.Privileges[0].Luid);
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bRet = !!AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, 0, NULL, NULL);
CloseHandle(hToken);
return bRet ;
}

BOOL FreeModuleByPid(TCHAR
*
szModuleName,DWORD dwPid)
...
{
// 参数构造
ThreadParam Param = ...{0};
Param.dwFreeLibrary = (DWORD)FreeLibrary;
Param.dwGetModuleHandle = (DWORD)GetModuleHandleA;
MoveMemory(Param.szModuleName,szModuleName,MAX_MODULE_NAME_LEN);
// 打开指定的进程
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPid);
if(hProcess==NULL)
...{
OutputDebugString(_T("OpenProcess failed!!"));
return FALSE;
}
// 参数写入
LPVOID lpParam = NULL;
lpParam = VirtualAllocEx(hProcess,NULL,sizeof(Param),MEM_COMMIT,PAGE_READWRITE);
if (lpParam == NULL)
...{
return FALSE;
}
if (!WriteProcessMemory(hProcess,lpParam,&Param,sizeof(Param),0))
...{
VirtualFreeEx(hProcess,lpParam,0,MEM_RELEASE);
return FALSE;
}
// 函数写入
LPVOID lpThread = NULL;
lpThread = VirtualAllocEx(hProcess,NULL,0x100,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (lpThread == NULL)
...{
return FALSE;
}
if (!WriteProcessMemory(hProcess,lpThread,RemoteThreadFun,0x100,0))
...{
VirtualFreeEx(hProcess,lpThread,0,MEM_RELEASE);
return FALSE;
}
// 创建线程
HANDLE hThread = NULL;
hThread = CreateRemoteThread(hProcess,0,0,(LPTHREAD_START_ROUTINE)lpThread,lpParam,0,NULL);
if(hThread == NULL)
...{
return FALSE;
}
// 等待线程结束
WaitForSingleObject(hThread,INFINITE);
// 清理工作
VirtualFreeEx(hProcess,lpThread,0,MEM_RELEASE);
VirtualFreeEx(hProcess,lpParam,0,MEM_RELEASE);
CloseHandle(hProcess);
return TRUE;
}

int
APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int
nCmdShow)
...
{
AdjustPurview();
TCHAR * szModuleName = _T("AcroIEHelper.dll");
DWORD dwPid = 1128;
FreeModuleByPid(szModuleName,dwPid);
return 0;
}
本文介绍了一种在不重启计算机的情况下从指定进程中卸载DLL的方法。通过创建远程线程并调用FreeLibrary来实现,避免了因挂接DLL而频繁重启的问题。

3961

被折叠的 条评论
为什么被折叠?



