DLL卸载

匿名 (未验证) 提交于 2019-12-03 00:33:02

DLL卸载

DLL卸载(DLL Ejection)是将强制插入进程的DLL弹出的一种技术,原理是驱使目标进程调用FreeLibrary() API,即将FreeLibrary() API的地址传递给CreateRemoteThread()的lpStartAddress参数并把要卸载的DLL的句柄传递给lpParameter参数。

注意:使用FreeLibrary() API实现DLL卸载,仅适用于卸载自己强制注入的DLL文件。PE文件直接导入的DLL文件是无法在进程运行过程中卸载的。


编写DLL卸载程序

下面编写针对之前DLL注入编写的InjectDll.exe和myhack.dll的DLL卸载程序EjectDll.exe程序。当然想卸载指定进程的指定DLL文件时只需修改代码中常量定义部分即可。

//EjectDll.cpp  #include "windows.h" #include "tchar.h" #include "tlhelp32.h"  //定义目标进程名和目标DLL文件名常量 #define DEF_PROC_NAME (L"notepad.exe") #define DEF_DLL_NAME (L"myhack.dll")  //查看设置权限 BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege){  	TOKEN_PRIVILEGES tp;     HANDLE hToken;     LUID luid;      //获取进程Token 	if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ){ 		_tprintf(L"[-]OpenProcessToken error: %u\n", GetLastError());         return FALSE; 	}  	//查看本地系统的权限值 	if ( !LookupPrivilegeValue(NULL, lpszPrivilege, &luid) ){ 		_tprintf(L"[-]LookupPrivilegeValue error: %u\n", GetLastError() );          return FALSE;  	}  	tp.PrivilegeCount = 1; 	tp.Privileges[0].Luid = luid; 	if( bEnablePrivilege ){ 		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 	}else{ 		tp.Privileges[0].Attributes = 0; 	}  	//启用特权或禁用所有特权 	if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD)NULL) ){ 		_tprintf(L"[-]AdjustTokenPrivileges error: %u\n", GetLastError() );          return FALSE;  	}  	if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ){ 		_tprintf(L"[-]The token does not have the specified privilege. \n");         return FALSE; 	}  	return TRUE; }  //查找目标进程ID DWORD FindProcessID(LPCTSTR szProcessName){ 	DWORD dwPID = 0xFFFFFFFF; 	HANDLE hSnapShot = INVALID_HANDLE_VALUE; 	PROCESSENTRY32 pe;  	//获取系统快照 	pe.dwSize = sizeof( PROCESSENTRY32 ); 	hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );  	//遍历查找目标进程 	Process32First(hSnapShot, &pe); 	do{ 		if( !_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile) ){ 			dwPID = pe.th32ProcessID; 			break; 		} 	}while( Process32Next(hSnapShot, &pe) );  	CloseHandle(hSnapShot);  	return dwPID; }  //卸载DLL BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName){ 	BOOL bMore = FALSE; 	BOOL bFound = FALSE;     HANDLE hSnapshot; 	HANDLE hProcess; 	HANDLE hThread;     HMODULE hModule = NULL;     MODULEENTRY32 me = { sizeof(me) };     LPTHREAD_START_ROUTINE pThreadProc;      //获取加载到进程的所有模块(DLL)信息 	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);  	//循环遍历所有模块信息,查找是否存在目标DLL文件 	bMore = Module32First(hSnapshot, &me); 	for( ; bMore; bMore = Module32Next(hSnapshot, &me) ){ 		if( !_tcsicmp((LPCTSTR)me.szModule, szDllName) || !_tcsicmp((LPCTSTR)me.szExePath, szDllName) ){ 			bFound = TRUE; 			break; 		} 	}  	//查找不到指定进程中的指定的DLL文件时,退出程序 	if ( !bFound ){ 		CloseHandle(hSnapshot); 		return FALSE; 	}  	//获取目标进程的句柄 	if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ){ 		_tprintf(L"[-]OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());         return FALSE; 	}  	//获取模块句柄,再获取模块中FreeLibrary() API句柄 	hModule = GetModuleHandle(L"kernel32.dll"); 	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");  	//在目标进程中创建远程线程并运行线程函数 	//me.modBaseAddr参数是要卸载的DLL的加载地址 	hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL); 	WaitForSingleObject(hThread, INFINITE);  	//关闭句柄 	CloseHandle(hThread); 	CloseHandle(hProcess); 	CloseHandle(hSnapshot);  	return TRUE; }  int _tmain(int argc, TCHAR* argv[]){ 	DWORD dwPID = 0xFFFFFFFF;  	//寻找目标进程ID 	dwPID = FindProcessID(DEF_PROC_NAME); 	if( dwPID == 0xFFFFFFFF ){ 		_tprintf(L"[-]Can't find the process <%s>.\n", DEF_PROC_NAME);         return 1; 	}  	_tprintf(L"[*]The PID of <\"%s\"> is %d\n", DEF_PROC_NAME, dwPID);  	//设置权限 	if( !SetPrivilege(SE_DEBUG_NAME, TRUE) ){ 		return 1; 	}  	//卸载DLL 	if( EjectDll(dwPID, DEF_DLL_NAME) ){ 		_tprintf(L"[+]Eject DLL(%d, \"%s\") success!!!\n", dwPID, DEF_DLL_NAME); 	}else{ 		_tprintf(L"[-]Eject DLL(%d, \"%s\") failed!!!\n", dwPID, DEF_DLL_NAME); 	}          	return 0; }

先打开notepad.exe程序,打开Process Explorer查看notepad.exe程序的PID,然后运行InjectDll.exe向notepad.exe进程注入myhack.dll:



接着运行EjectDll.exe卸载myhack.dll,再到Process Explorer查看:


可以看到,notepad.exe进程的myhack.dll已经被卸载成功。

文章来源: DLL卸载
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!