zoukankan      html  css  js  c++  java
  • DLL卸载

    @author: dlive

    EjectDll.cpp

    主要看一下EjectDll这个函数

    //dwPID是notepad.exe的PID
    //szDllName是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;
    
        // 使用TH32CS_SNAPMOUDLE参数,获取加载到notepad进程的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;
            }
        }
    
        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");
      	//使用FreeLibrary卸载DLL仅适用于使用CreateRemoteThread注入的DLL文件
      	//PE文件直接导入的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;
    }
    

    MOUDLEENTRY32结构体

    typedef struct tagMODULEENTRY32 {
      DWORD   dwSize;
      DWORD   th32ModuleID;			
      DWORD   th32ProcessID;
      DWORD   GlblcntUsage;
      DWORD   ProccntUsage;
      BYTE    *modBaseAddr;   //DLL被加载的地址(虚拟内存),即dll的句柄
      DWORD   modBaseSize;
      HMODULE hModule;
      TCHAR   szModule[MAX_MODULE_NAME32 + 1]; //DLL的名称
      TCHAR   szExePath[MAX_PATH]; 
    } MODULEENTRY32, *PMODULEENTRY32;
    

    FindProcessID函数

    以后用到类似功能的时候可以直接粘贴过去用XD

    //参数为进程名,如L"notepad.exe"
    DWORD FindProcessID(LPCTSTR szProcessName)
    {
        DWORD dwPID = 0xFFFFFFFF;
        HANDLE hSnapShot = INVALID_HANDLE_VALUE;
        PROCESSENTRY32 pe;
    
        // Get the snapshot of the system
        pe.dwSize = sizeof( PROCESSENTRY32 );
        hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );
    
        // find process
        Process32First(hSnapShot, &pe);
        do
        {	
          	//循环比较进程名是否与指定要寻找的进程名相同
            if(!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile))
            {
                dwPID = pe.th32ProcessID;
                break;
            }
        }
        while(Process32Next(hSnapShot, &pe));
    
        CloseHandle(hSnapShot);
    
        return dwPID;
    }
    

    卸载DLL需要注意的一点:DLL引用计数

    每个Windows内核对象都有一个引用计数(Reference Count),代表对象被使用的次数。

    调用10次LoadLibrary("a.dll"),a.dll的引用计数就变为10,卸载a.dll时同样需要调用10次FreeLibrary,每次调用FreeLibrary引用计数都会减1。

    卸载DLL时需要充分考虑好引用计数这个因素。

  • 相关阅读:
    RTP 协议
    RTSP 协议分析 (一)
    RTSP协议分析(二)
    CreateRemoteThread简单应用
    函数开始处的MOV EDI, EDI的作用
    eax,ebx,ecx,edx,esi,edi,ebp,esp寄存器的作用
    C++函数调用原理理解
    WinDBG常用断点命令
    利用bu命令下延迟断点
    Windbg 查看SSDT表
  • 原文地址:https://www.cnblogs.com/dliv3/p/6349745.html
Copyright © 2011-2022 走看看