• Dll注入技术之远程线程注入



    DLL注入技术之远线程注入

        DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EXE文件中的API),或以被注入EXE的身份去执行一些操作等等。
        远线程注入原理是利用Windows 系统中CreateRemoteThread()这个API,其中第4个参数是准备运行的线程,我们可以将LoadLibrary()填入其中,这样就可以执行远程进程中的LoadLibrary()函数,进而将我们自己准备的DLL加载到远程进程空间中执行。
        当然除了CreateRemoteThread()和LoadLibrary()这个两个主要的API还是远远不够的,我们还需要以下表格所示的API:
    OpenProcess 打开远程进程
    VirtualAllocEx 在远程进程中申请空间
    WriteProcessMemory 在远程进程中写入数据
    WaitForSingleObject 等待信号量
    VirtualFreeEx 释放远程进程中申请空间
    CloseHandle 关闭句柄

        主要代码如下:

    1. int CRemoteThreadInjectDLL::InjectDll(DWORD dwProcessId, PTCHAR szDllName)  
    2. {  
    3.     if (szDllName[0] == NULL)  
    4.         return -1;  
    5.     //提高权限相关操作  
    6.     EnablePrivilege(TRUE);  
    7.     //1. 打开进程  
    8.     HANDLE hProcess = ::OpenProcess(  PROCESS_ALL_ACCESS,   //打开进程权限  
    9.         FALSE,                                              //是否可继承   
    10.         dwProcessId);                                       //进程ID  
    11.   
    12.     if (hProcess == INVALID_HANDLE_VALUE)  
    13.         return -1;  
    14.   
    15.     //2. 在远程进程中申请空间  
    16.     LPVOID pszDllName = ::VirtualAllocEx(hProcess, //远程进程句柄  
    17.         NULL,                                  //建议开始地址  
    18.         4096,                                  //分配空间大小  
    19.         MEM_COMMIT,                            //空间初始化全0  
    20.         PAGE_EXECUTE_READWRITE);               //空间权限  
    21.   
    22.     if (NULL == pszDllName)  
    23.     {  
    24.         return -1;  
    25.     }  
    26.   
    27.     //3. 向远程进程中写入数据  
    28.     BOOL bRet = ::WriteProcessMemory( hProcess, pszDllName,   
    29.         szDllName, MAX_PATH, NULL);  
    30.   
    31.     if (NULL == bRet)  
    32.     {  
    33.         return -1;  
    34.     }  
    35.   
    36.     //4. 在远程进程中创建远程线程  
    37.     m_hInjecthread = ::CreateRemoteThread(hProcess,      //远程进程句柄  
    38.         NULL,                                            //安全属性  
    39.         0,                                               //栈大小  
    40.         (LPTHREAD_START_ROUTINE)LoadLibrary,             //进程处理函数      
    41.         pszDllName,                                      //传入参数  
    42.         NULL,                                            //默认创建后的状态  
    43.         NULL);                                           //线程ID  
    44.   
    45.     if (NULL == m_hInjecthread)  
    46.     {  
    47.         DWORD dwErr = GetLastError();  
    48.         return -1;  
    49.     }  
    50.   
    51.     //5. 等待线程结束返回  
    52.     DWORD dw = WaitForSingleObject(m_hInjecthread, -1);  
    53.     //6. 获取线程退出码,即LoadLibrary的返回值,即dll的首地址  
    54.     DWORD dwExitCode;  
    55.     GetExitCodeThread(m_hInjecthread, &dwExitCode);  
    56.     m_hMod = (HMODULE)dwExitCode;  
    57.   
    58.     //7. 释放空间  
    59.     BOOL bReturn = VirtualFreeEx(hProcess, pszDllName,   
    60.         4096, MEM_DECOMMIT);  
    61.   
    62.     if (NULL == bReturn)  
    63.     {  
    64.         return -1;  
    65.     }  
    66.   
    67.     CloseHandle(hProcess);  
    68.     hProcess = NULL;  
    69.     //恢复权限相关操作  
    70.     EnablePrivilege(FALSE);  
    71.   
    72.     return 0;  
    73. }  

    此外,我们还需要提升进程权限以便于提高注入成功率,所需API如下表所示:
    OpenProcessToken 得到令牌句柄
    LookupPrivilegeValue 得到权限值
    AdjustTokenPrivileges 提升令牌句柄权限
    1. int CRemoteThreadInjectDLL::EnablePrivilege(bool isStart)  
    2. {          
    3.     //1. 得到令牌句柄  
    4.     HANDLE  hToken = NULL;      //令牌句柄    
    5.     if (!OpenProcessToken( GetCurrentProcess(),   
    6.         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ,   
    7.         &hToken))  
    8.     {     
    9.         return FALSE;  
    10.     }  
    11.   
    12.     //2. 得到特权值  
    13.     LUID    luid = {0};         //特权值  
    14.     if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))  
    15.     {  
    16.         return FALSE;  
    17.     }  
    18.     //3. 提升令牌句柄权限  
    19.     TOKEN_PRIVILEGES tp = {0};  //令牌新权限  
    20.     tp.PrivilegeCount = 1;   
    21.     tp.Privileges[0].Luid = luid;  
    22.     tp.Privileges[0].Attributes = isStart ? SE_PRIVILEGE_ENABLED : 0;  
    23.     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))  
    24.     {  
    25.         return FALSE;  
    26.     }  
    27.     //4. 关闭令牌句柄  
    28.     CloseHandle(hToken);  
    29.     return 0;  
    30. }  

    当要在指定的进程中加载DLL时,我们就需要过滤指定名称的进程,这时遍历进程ID并进行对比,得到所指定的进程,所需API如表所示:
    CreateToolhelp32Snapshot   创建进程快照  
    Process32First   第一个进程快照
    Process32Next   循环下一个进程快照  
    1. DWORD CRemoteThreadInjectDLL::GetProcessId(PTCHAR pszProcessName)  
    2. {  
    3.     HANDLE hProcess = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  
    4.   
    5.     if (INVALID_HANDLE_VALUE == hProcess)  
    6.     {  
    7.         return 0;  
    8.     }  
    9.   
    10.     DWORD dwProcessId = 0;  
    11.   
    12.     PROCESSENTRY32 process32 = {0};  
    13.     process32.dwSize = sizeof(PROCESSENTRY32);  
    14.   
    15.     BOOL bRetProcess = FALSE;  
    16.     bRetProcess = ::Process32First(hProcess, &process32);  
    17.   
    18.     do  
    19.     {  
    20.         if (_tcscmp(pszProcessName, process32.szExeFile) == 0)  
    21.         {  
    22.             dwProcessId = process32.th32ProcessID;  
    23.             break;  
    24.         }  
    25.   
    26.         bRetProcess = ::Process32Next(hProcess, &process32);  
    27.     }while (bRetProcess);  
    28.     ::CloseHandle(hProcess);  
    29.   
    30.     return dwProcessId;  
    31. }  

    远线程注入API使用较多,不易实现。但是可以批量注入和卸载,这样对于需要反复调试的注入就非常的方便。
  • 相关阅读:
    服务器监控
    hadoop
    tomcat7 配置
    tomcat
    列表加载
    自适应网页设计(Responsive Web Design)
    Android Native 代码NDK开发学习笔记
    NDK开发历程(一):android native code的调试方法
    Android原生(Native)C开发之一:环境搭建篇
    ajaxfileupload 传参数
  • 原文地址:https://www.cnblogs.com/vcerror/p/4289069.html
Copyright © 2020-2023  润新知