• DLL注入


         最近的项目涉及了软件破解方面的知识,记录一下。

         将dll注入另一个进程。

    // Inject.cpp : Defines the exported functions for the DLL application.
    //
    
    #include "stdafx.h"
    #include <TlHelp32.h>
    #include <Psapi.h>
    #include <tchar.h>
    
    // LoadLibrary的不同版本
    #if defined _UNICODE    
    #define _LoadLibrary "LoadLibraryW"    //_UNICODE
    #else
    #define _LoadLibrary "LoadLibraryA"    //_MBCS
    #endif
    
    // 根据进程名获取PID
    DWORD GetPID(LPTSTR lpProcess)
    {
        HANDLE hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 获取进程快照句柄
    
        PROCESSENTRY32 pe32;
        pe32.dwSize = sizeof(PROCESSENTRY32);
        BOOL flag = Process32First(hProcSnap, &pe32); // 获取列表的第一个进程
    
        while(flag)
        {
            if(!_tcsicmp(pe32.szExeFile, lpProcess))
            {
                CloseHandle(hProcSnap);
                return pe32.th32ProcessID; //pid
            }
            flag=Process32Next(hProcSnap, &pe32); //获取下一个进程
        }
    
        CloseHandle(hProcSnap);
        return 0;
    }
    
    // 获取适当的Privilege
    // hProcess  当前进程的handle
    // Privilege 需要的Privilege
    // 成功返回TRUE,失败返回FALSE
    BOOL AdjustProcessPrivilege(HANDLE hProcess, TCHAR *Privilege)
    {
        HANDLE hToken=NULL;
        OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);  //打开进程令牌环
    
        if(NULL==hToken) 
            return FALSE;
    
        LUID luid;
        if(!LookupPrivilegeValue(NULL, Privilege, &luid))  // 获得进程本地唯一ID
        {
            CloseHandle(hToken);
            return FALSE;
        }
    
        TOKEN_PRIVILEGES token_privileges;
        token_privileges.PrivilegeCount =1;
        token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        token_privileges.Privileges[0].Luid = luid;
        
        //调整进程权限
        if(!AdjustTokenPrivileges(hToken, FALSE, &token_privileges, NULL, NULL, NULL))
        {
            CloseHandle(hToken);
            return FALSE;
        }
    
        CloseHandle(hToken);
    
        return TRUE;
    }
    
    // 在进程中查找dll
    HMODULE CheckProcessModule(LPTSTR lpRemoteProcess, LPTSTR lpInjectDll)
    {
        DWORD nRemotePID = GetPID(lpRemoteProcess);
        HANDLE hRemoteProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, nRemotePID);
    
        HMODULE hMods[1024];    
        DWORD cbNeeded = 0;     // Get a handle to the process.    
        if( EnumProcessModules(hRemoteProcess, hMods, sizeof(hMods), &cbNeeded))    
        {        
            for (UINT i=0; i<(cbNeeded/sizeof(HMODULE)); i++)    
            {        
                TCHAR szModName[MAX_PATH];    // Get the full path to the module's file.        
                if (GetModuleFileNameEx(hRemoteProcess, hMods[i], szModName, sizeof(szModName)/sizeof(TCHAR)))        
                {        
                    if (!_tcsicmp(lpInjectDll, szModName))
                    {
                        CloseHandle(hRemoteProcess);
                        return hMods[i];
                    }
                }
            }
        }
    
        CloseHandle(hRemoteProcess);
        return NULL;
    }
    
    BOOL InjectDll(LPTSTR lpRemoteProcess, LPTSTR lpInjectDll, BOOL bInject)
    {
        // 获取SeDebugPrivilege权限
        if(FALSE == AdjustProcessPrivilege(GetCurrentProcess(), _T("SeDebugPrivilege"))) 
            return FALSE;    
    
        // 函数准备
        LPTHREAD_START_ROUTINE pfnThread = NULL;
        HINSTANCE hMod = GetModuleHandle(_T("kernel32.dll"));
        if (bInject) 
            pfnThread = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,_LoadLibrary);  // LoadLibrary注入
        else 
            pfnThread = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"FreeLibrary"); // FreeLibrary卸载
        if(NULL == pfnThread) 
            return FALSE;
    
        __try
        {
            // 获取目标进程ID
            DWORD nRemotePID = GetPID(lpRemoteProcess);
            // 打开目标进程
            HANDLE hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, nRemotePID);
            if(hRemoteProcess == NULL)
            {
                return FALSE;
            }
    
            if (bInject) //注入
            {
                // 在远端进程中分配内存
                LPVOID ModName = VirtualAllocEx(hRemoteProcess, NULL, (_tcslen(lpInjectDll)+1)*sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE);
                if(!ModName)  
                    __leave;
    
                // 在远端进程中写入dll的文件名
                if(0 == WriteProcessMemory(hRemoteProcess, ModName, lpInjectDll, (_tcslen(lpInjectDll)+1)*sizeof(TCHAR), NULL)) 
                    __leave;
    
                // 创建远程线程
                HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, pfnThread, ModName, 0, NULL);
                if(NULL == hRemoteThread) 
                    __leave;
                WaitForSingleObject(hRemoteThread,INFINITE);
    
                VirtualFreeEx(hRemoteProcess, ModName, 0, MEM_RELEASE);
                CloseHandle(hRemoteThread);
            }
            else //卸载
            {
                // 在进程中查找需要卸载的dll
                HMODULE hTarget = CheckProcessModule(lpRemoteProcess, lpInjectDll);
                // 创建远程线程
                HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, pfnThread, hTarget, 0, NULL);
                if(NULL == hRemoteThread) 
                    __leave;
                WaitForSingleObject(hRemoteThread,INFINITE);
    
                CloseHandle(hRemoteThread);
            }
    
            CloseHandle(hRemoteProcess);
            return TRUE;
        }
        __finally
        {
        }
    
        return FALSE;
    }

            以上已经将dll成功注入到目标进程,但是怎样让注入的dll执行?可以在dll加载时,执行一段代码。

    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
            Fun();  // 需要执行的代码
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        return TRUE;
    }
  • 相关阅读:
    过河卒(Noip2002)
    暑假学习日记2013/7/18
    暑假学习日记2013/7/16
    iOS中利用CoreTelephony获取用户当前网络状态(判断2G,3G,4G) by徐文棋
    隐藏键盘的N种方法
    cell重用
    关于viewControllers之间的传值方式
    iOS开发之工欲善其事,必先利其器
    NSLog输出格式及随机数
    iOS团队代码规范
  • 原文地址:https://www.cnblogs.com/icooper/p/4823490.html
Copyright © 2020-2023  润新知