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. }

作者: DLL注入技术之远线程注入
来源: 黑客反病毒 (http://bbs.hackav.com)

还没有评论,快来抢沙发!

发表评论

  • 😉
  • 😐
  • 😡
  • 😈
  • 😯
  • 😛
  • 😳
  • 😮
  • 😆
  • 💡
  • 😀
  • 👿
  • 😥
  • 😎
  • 😕