随笔 - 8  文章 - 26  trackbacks - 0
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用链接

留言簿(4)

随笔档案

文章分类

文章档案

相册

C++语言

搜索

  •  

最新评论

阅读排行榜

评论排行榜

如何卸载其他进程中的DLL。
要卸载其他进程中的DLL一般都要首先提升本进程的权限。相关的操作也很简单,我已经将其封装为一个函数
/*********************************************************************/
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,
"所申请的权限全部成功","成功",MB_OK);
 
return FALSE;
}
 
return TRUE;
}

*参数说明:hProcess为你想要提升权限的进程句柄,如果要提升本进程的权限只要传递GetCurrentProcess()函数即可。
           PrivilegeName为你想要申请的权限,一般传递SE_DEBUG_NAME参数,说明你要对其他进程的内存空间进行操作。

再提升了自己的进程权限之后就要开始我们的主要操作了,操作分这麽几步:
1.首先要通过调用 OpenProcess函数获得宿主进程的句柄,注意给这个函数传递的第一个参数要包括PROCESS_CREATE_THREAD,PROCESS_VM_OPERATION,PROCESS_VM_WRITE
。在这说明一下,因为我们要在其他进程进程中创建线程即所谓的远程线程,所以我们要申请PROCESS_CREATE_THREAD权限。再就是我们要对远程进程的地址空间进行操作
所以我们要申请PROCESS_VM_OPERATION权限,PROCESS_VM_WRITE申请对进程的地址空间的写操作权限。
2.我们要将DLL的路径名写到远程线程的地址空间中去。首先要先计算一下DLL路径名的长路,以确定我们再地址空间中申请多大的空间,
这步操作用strlen,lstrlen等函数都行。知道了DLL路径名长度以后我们就开始申请空间,调用函数VirtualAllocEx提交一块指定大小的空间
,然后调用WriteProcessMemory函数将DLL名写进刚才提交的空间中。以上操作完成以后再远程线程的地址空间中就存在了DLL名。
3.正式开始创建远程线程卸载DLL。卸载DLL可以调用FreeLibraryAndExitThread或FreeLibrary函数,这两个函数都需要一个参数就是DLL模块的
句柄。而要得到DLL模块而句柄就需要调用GetModuleHandle函数,所以首先要确定GetModuleHandle的函数指针,然后再远程进程中创建一个远程线程
进行GetModuleHandle的调用得到DLL的句柄。之后我们就可以再次创建一个远程线程调用FreeLibraryAndExitThread或FreeLibrary将DLL卸载掉
,这样我们就完工了。

完整的操作代码如下(注:自己实在不想写,偷懒再网上找的,看完绝的还不错)
/******************************************************************************/
BOOL UnloadDll(DWORD dwPid, 
char *strDllName)
{
//获取宿主进程的句柄,注意那几个参数,不然会出错
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
            FALSE, dwPid);
if(hProcess == NULL){
    ::MessageBox(NULL, 
"无法获取进程句柄""错误", MB_OK | MB_ICONERROR);
    
return FALSE;
}


DWORD     dwSize 
= 0;
DWORD     dwWritten 
= 0;
DWORD     dwHandle 
= 0
          
dwSize 
= strlen(strDllName)+ 1;//dll的全路径名的长度,待会分配内存要用到的

//向宿主进程分配内存,返回一个指针
LPVOID lpBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);

//如果在宿主进程空间写失败就直接报错闪人
if!WriteProcessMemory(hProcess, lpBuf, (LPVOID)strDllName.GetBuffer(dwSize), dwSize, &dwWritten)){   
    VirtualFreeEx(hProcess, lpBuf, dwSize, MEM_DECOMMIT);
    CloseHandle(hProcess);
    MessageBox(NULL, 
"在目标进程中写入失败""错误", MB_OK | MB_ICONERROR);
    
return FALSE;
}


//获取GetModuleHandleA函数地址
LPVOID pFun = GetProcAddress(GetModuleHandle("Kernel32"), "GetModuleHandleA");

//在宿主进程中创建一个远程线程,线程函数为上面导出的GetModuleHandleA,参数为lpBuf指针,还
//记得我们获取的dll全路径不
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFun,
                                          lpBuf, 
0, NULL);
    
//如果创建线程失败,直接报错退出
if(hThread == NULL){
    CloseHandle(hProcess);
    ::MessageBox(NULL, 
"在目标进程创建远程线程失败""错误", MB_OK | MB_ICONERROR);
          
return FALSE;
}


//     等待GetModuleHandle运行完毕   
WaitForSingleObject(hThread, INFINITE); 
//     获得GetModuleHandle的返回值   
GetExitCodeThread(hThread, &dwHandle);

//     释放目标进程中申请的空间   
VirtualFreeEx(hProcess, lpBuf, dwSize, MEM_DECOMMIT);
CloseHandle(hThread);

//     使目标进程调用FreeLibraryAndExit,卸载DLL,实际也可以用FreeLibrary,但是我发现前者好一点
pFun = GetProcAddress(GetModuleHandle("Kernel32"), "FreeLibraryAndExitThread");
hThread 
= CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFun,
                             (LPVOID)dwHandle, 
0, NULL);   
//     等待FreeLibraryAndExitThread执行完毕   
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);

return TRUE;    //操作成功

}

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

再就补充一点,上面的那个函数要求传递的参数为进程的ID号,但大多数情况下我们只知道进程的进程名,由进程名得到进程ID号我自己写了一个
函数如下(注:使用此函数需要包含头文件
<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;
}


好了到这里我们就完全可以使用这些函数写出一个专门卸载其他进程DLL的小工具了。

posted on 2008-06-14 09:44 杨彬彬 阅读(2364) 评论(2)  编辑 收藏 引用 所属分类: Windows编程

FeedBack:
# re: 卸载远程线程中的DLL 2012-08-11 08:27 疑问
兄弟,你确定执行

pFun = GetProcAddress(GetModuleHandle("Kernel32"), "FreeLibraryAndExitThread");
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFun,
(LPVOID)dwHandle, 0, NULL);

时没发生访问违规?FreeLibraryAndExitThread需要2个参数呢  回复  更多评论
  
# re: 卸载远程线程中的DLL 2015-03-17 18:10 王小亮
水平很高,学习了。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理