• 第24章:DLL卸载


    DLL卸载是通过调用 FreeLibrary() API.

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

    使用LoadLibrary() 会 +1, FreeLibrary() 会 -1.FreeLibrary() 仅适用于卸载自己强制注入的DLL文件,PE文件导入的无法在进程运行过程中卸载的.

    // EjectDll.exe
    
    #include "windows.h"
    #include "tlhelp32.h"
    #include "tchar.h"
    
    #define DEF_PROC_NAME    (L"notepad.exe")
    #define DEF_DLL_NAME    (L"myhack.dll")
    
    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;
    }
    
    BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) 
    {
        TOKEN_PRIVILEGES tp;
        HANDLE hToken;
        LUID luid;
    
        if( !OpenProcessToken(GetCurrentProcess(),
                              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
                              &hToken) )
        {
            _tprintf(L"OpenProcessToken error: %u
    ", GetLastError());
            return FALSE;
        }
    
        if( !LookupPrivilegeValue(NULL,           // lookup privilege on local system
                                  lpszPrivilege,  // privilege to lookup 
                                  &luid) )        // receives LUID of privilege
        {
            _tprintf(L"LookupPrivilegeValue error: %u
    ", 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;
    
        // Enable the privilege or disable all privileges.
        if( !AdjustTokenPrivileges(hToken, 
                                   FALSE, 
                                   &tp, 
                                   sizeof(TOKEN_PRIVILEGES), 
                                   (PTOKEN_PRIVILEGES) NULL, 
                                   (PDWORD) NULL) )
        { 
            _tprintf(L"AdjustTokenPrivileges error: %u
    ", GetLastError() ); 
            return FALSE; 
        } 
    
        if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
        {
            _tprintf(L"The token does not have the specified privilege. 
    ");
            return FALSE;
        } 
    
        return TRUE;
    }
    
    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);      //获取加载到进程的模块(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");
        pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
        hThread = CreateRemoteThread(hProcess, NULL, 0, 
                                     pThreadProc, me.modBaseAddr, 
                                     0, NULL);
        WaitForSingleObject(hThread, INFINITE);                               //与前面加载DLL是一样的操作
     
        CloseHandle(hThread);
        CloseHandle(hProcess);
        CloseHandle(hSnapshot);
    
        return TRUE;
    }
    
    int _tmain(int argc, TCHAR* argv[])
    {
        DWORD dwPID = 0xFFFFFFFF;
     
        // find process
        dwPID = FindProcessID(DEF_PROC_NAME);
        if( dwPID == 0xFFFFFFFF )
        {
            _tprintf(L"There is no <%s> process!
    ", DEF_PROC_NAME);
            return 1;
        }
    
        _tprintf(L"PID of "%s" is %d
    ", DEF_PROC_NAME, dwPID);
    
        // change privilege
        if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )
            return 1;
    
        // eject dll
        if( EjectDll(dwPID, DEF_DLL_NAME) )
            _tprintf(L"EjectDll(%d, "%s") success!!!
    ", dwPID, DEF_DLL_NAME);
        else
            _tprintf(L"EjectDll(%d, "%s") failed!!!
    ", dwPID, DEF_DLL_NAME);
    
        return 0;
    }

    大致看看,知道流程就行.

  • 相关阅读:
    ERP类系统设计学习
    人工智能关键词
    系统性能
    连接不同服务器不同数据库
    socket一个例子
    SQLite
    asp.net 页面缓存、数据缓存
    原生js
    Android 网络调试 adb tcpip 开启方法
    C语言中string char int类型转换
  • 原文地址:https://www.cnblogs.com/Rev-omi/p/13375197.html
Copyright © 2020-2023  润新知