如何卸載其他進(jìn)程中的DLL。
要卸載其他進(jìn)程中的DLL一般都要首先提升本進(jìn)程的權(quán)限。相關(guān)的操作也很簡單,我已經(jīng)將其封裝為一個(gè)函數(shù)

/** *//*********************************************************************/
BOOL BDebugProcess2(HANDLE hProcess, LPCTSTR PrivilegeName)


{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;

if (!OpenProcessToken(hProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return( FALSE );
LookupPrivilegeValue(NULL,PrivilegeName,
&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES)NULL, 0);


if(GetLastError()=!ERROR_SUCCESS)


{
::MessageBox(NULL,"所申請(qǐng)的權(quán)限全部成功","成功",MB_OK);
return FALSE;
}
return TRUE;
}
*參數(shù)說明:hProcess為你想要提升權(quán)限的進(jìn)程句柄,如果要提升本進(jìn)程的權(quán)限只要傳遞GetCurrentProcess()函數(shù)即可。
PrivilegeName為你想要申請(qǐng)的權(quán)限,一般傳遞SE_DEBUG_NAME參數(shù),說明你要對(duì)其他進(jìn)程的內(nèi)存空間進(jìn)行操作。

再提升了自己的進(jìn)程權(quán)限之后就要開始我們的主要操作了,操作分這麼幾步:
1.首先要通過調(diào)用 OpenProcess函數(shù)獲得宿主進(jìn)程的句柄,注意給這個(gè)函數(shù)傳遞的第一個(gè)參數(shù)要包括PROCESS_CREATE_THREAD,PROCESS_VM_OPERATION,PROCESS_VM_WRITE
。在這說明一下,因?yàn)槲覀円谄渌M(jìn)程進(jìn)程中創(chuàng)建線程即所謂的遠(yuǎn)程線程,所以我們要申請(qǐng)PROCESS_CREATE_THREAD權(quán)限。再就是我們要對(duì)遠(yuǎn)程進(jìn)程的地址空間進(jìn)行操作
所以我們要申請(qǐng)PROCESS_VM_OPERATION權(quán)限,PROCESS_VM_WRITE申請(qǐng)對(duì)進(jìn)程的地址空間的寫操作權(quán)限。
2.我們要將DLL的路徑名寫到遠(yuǎn)程線程的地址空間中去。首先要先計(jì)算一下DLL路徑名的長路,以確定我們?cè)俚刂房臻g中申請(qǐng)多大的空間,
這步操作用strlen,lstrlen等函數(shù)都行。知道了DLL路徑名長度以后我們就開始申請(qǐng)空間,調(diào)用函數(shù)VirtualAllocEx提交一塊指定大小的空間
,然后調(diào)用WriteProcessMemory函數(shù)將DLL名寫進(jìn)剛才提交的空間中。以上操作完成以后再遠(yuǎn)程線程的地址空間中就存在了DLL名。
3.正式開始創(chuàng)建遠(yuǎn)程線程卸載DLL。卸載DLL可以調(diào)用FreeLibraryAndExitThread或FreeLibrary函數(shù),這兩個(gè)函數(shù)都需要一個(gè)參數(shù)就是DLL模塊的
句柄。而要得到DLL模塊而句柄就需要調(diào)用GetModuleHandle函數(shù),所以首先要確定GetModuleHandle的函數(shù)指針,然后再遠(yuǎn)程進(jìn)程中創(chuàng)建一個(gè)遠(yuǎn)程線程
進(jìn)行GetModuleHandle的調(diào)用得到DLL的句柄。之后我們就可以再次創(chuàng)建一個(gè)遠(yuǎn)程線程調(diào)用FreeLibraryAndExitThread或FreeLibrary將DLL卸載掉
,這樣我們就完工了。

完整的操作代碼如下(注:自己實(shí)在不想寫,偷懶再網(wǎng)上找的,看完絕的還不錯(cuò))

/** *//******************************************************************************/
BOOL UnloadDll(DWORD dwPid, char *strDllName)


{
//獲取宿主進(jìn)程的句柄,注意那幾個(gè)參數(shù),不然會(huì)出錯(cuò)
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
FALSE, dwPid);

if(hProcess == NULL)
{
::MessageBox(NULL, "無法獲取進(jìn)程句柄", "錯(cuò)誤", MB_OK | MB_ICONERROR);
return FALSE;
}

DWORD dwSize = 0;
DWORD dwWritten = 0;
DWORD dwHandle = 0;
dwSize = strlen(strDllName)+ 1;//dll的全路徑名的長度,待會(huì)分配內(nèi)存要用到的

//向宿主進(jìn)程分配內(nèi)存,返回一個(gè)指針
LPVOID lpBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);

//如果在宿主進(jìn)程空間寫失敗就直接報(bào)錯(cuò)閃人

if( !WriteProcessMemory(hProcess, lpBuf, (LPVOID)strDllName.GetBuffer(dwSize), dwSize, &dwWritten))
{
VirtualFreeEx(hProcess, lpBuf, dwSize, MEM_DECOMMIT);
CloseHandle(hProcess);
MessageBox(NULL, "在目標(biāo)進(jìn)程中寫入失敗", "錯(cuò)誤", MB_OK | MB_ICONERROR);
return FALSE;
}

//獲取GetModuleHandleA函數(shù)地址
LPVOID pFun = GetProcAddress(GetModuleHandle("Kernel32"), "GetModuleHandleA");

//在宿主進(jìn)程中創(chuàng)建一個(gè)遠(yuǎn)程線程,線程函數(shù)為上面導(dǎo)出的GetModuleHandleA,參數(shù)為lpBuf指針,還
//記得我們獲取的dll全路徑不
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFun,
lpBuf, 0, NULL);
//如果創(chuàng)建線程失敗,直接報(bào)錯(cuò)退出

if(hThread == NULL)
{
CloseHandle(hProcess);
::MessageBox(NULL, "在目標(biāo)進(jìn)程創(chuàng)建遠(yuǎn)程線程失敗", "錯(cuò)誤", MB_OK | MB_ICONERROR);
return FALSE;
}

// 等待GetModuleHandle運(yùn)行完畢
WaitForSingleObject(hThread, INFINITE);
// 獲得GetModuleHandle的返回值
GetExitCodeThread(hThread, &dwHandle);

// 釋放目標(biāo)進(jìn)程中申請(qǐng)的空間
VirtualFreeEx(hProcess, lpBuf, dwSize, MEM_DECOMMIT);
CloseHandle(hThread);

// 使目標(biāo)進(jìn)程調(diào)用FreeLibraryAndExit,卸載DLL,實(shí)際也可以用FreeLibrary,但是我發(fā)現(xiàn)前者好一點(diǎn)
pFun = GetProcAddress(GetModuleHandle("Kernel32"), "FreeLibraryAndExitThread");
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFun,
(LPVOID)dwHandle, 0, NULL);
// 等待FreeLibraryAndExitThread執(zhí)行完畢
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);

return TRUE; //操作成功

}

/** *//*******************************************************************************************/

再就補(bǔ)充一點(diǎn),上面的那個(gè)函數(shù)要求傳遞的參數(shù)為進(jìn)程的ID號(hào),但大多數(shù)情況下我們只知道進(jìn)程的進(jìn)程名,由進(jìn)程名得到進(jìn)程ID號(hào)我自己寫了一個(gè)
函數(shù)如下(注:使用此函數(shù)需要包含頭文件<Tlhelp32.h>):
DWORD GetProcessIdFromName(LPCTSTR name,PROCESSENTRY32 * BPE)


{
PROCESSENTRY32 pe;
DWORD id = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe.dwSize = sizeof(PROCESSENTRY32);
BOOL PF=FALSE;
for(PF=Process32First(hSnapshot,&pe);PF;PF=Process32Next(hSnapshot,&pe))


{
if(strcmp(pe.szExeFile,name) == 0)

{
id = pe.th32ProcessID;
*BPE=pe;
break;
}
}
CloseHandle(hSnapshot);
return id;
}

好了到這里我們就完全可以使用這些函數(shù)寫出一個(gè)專門卸載其他進(jìn)程DLL的小工具了。


posted on 2008-06-14 09:44
楊彬彬 閱讀(2521)
評(píng)論(2) 編輯 收藏 引用 所屬分類:
Windows編程