卸载DLL

BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName)
{
	BOOL bMore = FALSE, bFound = FALSE;
	HANDLE hSnapshot, hProcess, hThread;
	HMODULE hModule = NULL;
	MODULEENTRY32 me = { sizeof(me) };
	LPTHREAD_START_ROUTINE pThreadProc;

	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
	bMore = Module32First(hSnapshot, &me);
	for (; bMore; bMore = Module32Next(hSnapshot, &me))
	{
		if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) || !_tcsicmp((LPCTSTR)me.szExePath, szDllName))
		{
			bFound = TRUE;
			break;
		}
	}
	if (!bFound)
	{
		CloseHandle(hSnapshot);
		return FALSE;
	}
	if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
	{
		_tprintf(L"OpenProcess(%d) failed!!! [%d]
", dwPID, GetLastError());
		return FALSE;
	}

	hModule = GetModuleHandle(L"kernel32.dll");
	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
	hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL);
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);
	CloseHandle(hProcess);
	CloseHandle(hSnapshot);

	return TRUE;
}

  直接看核心代码。

CreateToolhelp32Snapshot函数为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程[THREAD])建立一个快照[snapshot]。
  HANDLE WINAPI CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
  );
  参数:
  dwFlags
  [输入]指定快照中包含的系统内容,这个参数能够使用下列数值(变量)中的一个。
  TH32CS_INHERIT - 声明快照句柄是可继承的。
  TH32CS_SNAPALL - 在快照中包含系统中所有的进程和线程。
  TH32CS_SNAPHEAPLIST - 在快照中包含在th32ProcessID中指定的进程的所有的堆。
  TH32CS_SNAPMODULE - 在快照中包含在th32ProcessID中指定的进程的所有的模块。
  TH32CS_SNAPPROCESS - 在快照中包含系统中所有的进程。
  TH32CS_SNAPTHREAD - 在快照中包含系统中所有的线程。
  Const TH32CS_SNAPHEAPLIST = &H1
  Const TH32CS_SNAPPROCESS = &H2
  Const TH32CS_SNAPTHREAD = &H4
  Const TH32CS_SNAPMODULE = &H8
  Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)
  Const TH32CS_INHERIT = &H80000000
  th32ProcessID
  [输入]指定将要快照的进程ID。如果该参数为0表示快照当前进程。该参数只有在设置了TH32CS_SNAPHEAPLIST或TH32CS_SNAPMOUDLE后才有效,在其他情况下该参数被忽略,所有的进程都会被快照。
  返回值:
  调用成功,返回快照的句柄,调用失败,返回INVAID_HANDLE_VALUE。
  备注:
  使用GetLastError函数查找该函数产生的错误状态码。
  要删除快照,使用CloseHandle函数

Module32First函数返回第一个模块,并将信息给了me。

Module32Next函数返回下一个模块,并将信息给了me。

BOOL
WINAPI
Module32FirstW(
HANDLE hSnapshot,
LPMODULEENTRY32W lpme
);

BOOL
WINAPI
Module32NextW(
HANDLE hSnapshot,
LPMODULEENTRY32W lpme
);

LPMODULEENTRY32W 结构体如下。

typedef struct tagMODULEENTRY32W
{
DWORD dwSize;
DWORD th32ModuleID; // This module
DWORD th32ProcessID; // owning process
DWORD GlblcntUsage; // Global usage count on the module
DWORD ProccntUsage; // Module usage count in th32ProcessID's context
BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
HMODULE hModule; // The hModule of this module in th32ProcessID's context
WCHAR szModule[MAX_MODULE_NAME32 + 1];
WCHAR szExePath[MAX_PATH];
} MODULEENTRY32W;
typedef MODULEENTRY32W * PMODULEENTRY32W;
typedef MODULEENTRY32W * LPMODULEENTRY32W;

接下来就很容易了,加载用FreeLibrary 卸载DLL。

原文地址:https://www.cnblogs.com/whitehawk/p/11168709.html