现在的位置: 首页 > 综合 > 正文

代码注入之远程线程篇

2011年01月27日 ⁄ 综合 ⁄ 共 4092字 ⁄ 字号 评论关闭

引子

         

前些日子由于项目要求,在网上到处找资料,于无意中发现了 CodeProject 上的一篇很老的文章,文章标题为:

Three Ways to Inject Your Code into Another Process

这篇文章呢,出来很久咯,还是 03 年的文章了,可惜我弄底层弄得时间不久哦,不然应该早就看过这篇大作了,

由于是大作,而且出来的又久了,自然在网上也就到处流传咯,

所以也有人将这篇文章翻译成了中文版的,下面给出这篇大作的两个链接:

中文版:http://www.vckbase.com/document/viewdoc/?id=1886

英文版:http://www.codeproject.com/KB/threads/winspy.aspx

然后呢,这边由于老大给弄了蛮多好书过来了,其中一本就是所谓的骇客之类的东西,

虽然是繁体的,但是知识点都很不错哦,所以也拿过来看了看,就发现其中对这个远程线程的注入有很多的介绍,

而且貌似前些年的很多病毒或者木马就是通过这屁东西来隐藏的,

看着看着就来劲了,而后呢,自己就根据书中的思路,

然后再结合自己的理解,将理解整理出了代码,然后就出了这篇文章咯 !

然后注意一点的是,在 CodeProject 上的那篇文章中介绍了三种注入代码技术,

第一种就是众所周知的 Hook 了;

第二种是直接将所要执行的代码全部拷贝到宿主进程中,即代码远程注入技术;

第三种则是 DLL 的远程注入技术了,其通过在宿主进程加载自己写的另外的一个 DLL 来实现注入;

然后在我的这篇博文中,我也只是总结前人的思想,然后再加入我自己的立即,

同时由于 Hook 太常见了,常见得不行了,所以我并不会介绍 Hook 了,而只介绍后面的两种方式。

          

            

代码远程注入技术

    

Demo 的效果:

创建的项目为 RemoteThreadCode,即远程注入代码,其实现的功能是当运行 RemoteThreadCode.exe 时,

会在 Explorer.exe 进程中创建一个线程,而这个创建的线程功能实现很简单,

就是弹出一个消息框即 OK !

      

Demo 的效果展示:

当双击执行 RemoteThreadCode.exe 时,则会注入一个线程到 Explorer.exe 中

image

             

当点击确定后,注入到 Explorer.exe 中的线程执行完毕,从而 WaitForSingleObject 等待成功 !

image

          

基本思路以及所对应的代码:

1. 提升进程权限,如果权限不够的话,很容易造成 OpenProcess 失败;

   1: //=====================================================================================//

   2: //Name: bool AdjustProcessTokenPrivilege()                                             //

   3: //                                                                                     //

   4: //Descripion: 提升当前进程权限                                                                 //

   5: //=====================================================================================//

   6: bool AdjustProcessTokenPrivilege()

   7: {

   8:     LUID luidTmp;

   9:     HANDLE hToken;

  10:     TOKEN_PRIVILEGES tkp;

  11:  

  12:     if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))

  13:     {

  14:         OutputDebugString("AdjustProcessTokenPrivilege OpenProcessToken Failed ! \n");

  15:  

  16:         return false;

  17:     }

  18:  

  19:     if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidTmp))

  20:     {

  21:         OutputDebugString("AdjustProcessTokenPrivilege LookupPrivilegeValue Failed ! \n");

  22:  

  23:         CloseHandle(hToken);

  24:  

  25:         return FALSE;

  26:     }

  27:  

  28:     tkp.PrivilegeCount = 1;

  29:     tkp.Privileges[0].Luid = luidTmp;

  30:     tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

  31:  

  32:     if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))

  33:     {

  34:         OutputDebugString("AdjustProcessTokenPrivilege AdjustTokenPrivileges Failed ! \n");

  35:  

  36:         CloseHandle(hToken);

  37:  

  38:         return FALSE;

  39:     }

  40:     return true;

  41: }

2. 确定你的宿主进程,即你所要注入代码的进程,这个其实很好办,你要是不想你的木马或者病毒被别个一下子就结束了的话,

   最好是选择系统要想运行,则必须开启的那种进程,比如资源管理器进程 Explorer.exe,

   Windows 子系统进程 csrss.exe 等等,但是这里注意的是,我注入 System 进程的时候造成了失败哦,

   所以最好还是别拿 System 做实验,而且如果你注入失败了的话,是会造成宿主进程崩溃的,

   等下一不小心把 System 进程给弄崩溃了就不好了;

   1: //=====================================================================================//

   2: //Name: bool ProcessIsExplorer(DWORD dwProcessId)                                      //

   3: //                                                                                     //

   4: //Descripion: 判定一个进程是否为 Explorer 进程                                                 //

   5: //=====================================================================================//

   6: bool ProcessIsExplorer(DWORD dwProcessId)

   7: {

   8:     HANDLE hProcess;

   9:  

  10:     hProcess = NULL;

  11:  

  12:     hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);

  13:     if(NULL == hProcess)

  14:     {

  15:         OutputErrorMessage("ProcessIsExplorer - OpenProcess Failed , Error Code Is %d , Error Message Is %s !");

  16:  

  17:         return FALSE;

  18:     }

  19:  

  20:     DWORD dwNameLen;

  21:     TCHAR pathArray[MAX_PATH];

  22:     ZeroMemory(pathArray, MAX_PATH);

  23:  

  24:     dwNameLen = 0;

  25:     dwNameLen = GetModuleFileNameEx(hProcess, NULL, pathArray, MAX_PATH);

  26:     if(dwNameLen == 0)

  27:     {

  29:         CloseHandle(hProcess);

  30:  

  31:         return FALSE;

  32:     }

  33:  

  34:     TCHAR exeNameArray[MAX_PATH];

  35:     ZeroMemory(exeNameArray, MAX_PATH);

  36:     _tsplitpath(pathArray, NULL, NULL, exeNameArray, NULL);

  37:  

  38:     string str1 = exeNameArray;

  39:     if((str1.compare("Explorer") == 0) || (str1.compare("explorer") == 0))

  40:     {

  41:         CloseHandle(hProcess);

  42:  

  43:         return TRUE;

  44:     }

  45:  

  46:     return FALSE;

  47: }

3. 打开宿主进程了(我这里打开的是 Explorer.exe 进程),思路是首先变量当前系统下运行的所有的进程,

   然后遍历获取到得所有的进程的 PID,再调用 ProcessIsExplorer 函数来判断这个进程是否为 Explorer.exe 进程,

   如果是则记录下这个进程的 PID 就可以了,这样就获得了 Explorer.exe 进程的 PID 了,

   再通过 OpenProcess 来打开这个 Explorer.exe 进程就 OK 了;

   1: //提升当前进程的权限

   2: AdjustProcessTokenPrivilege();

   3:  

   4: //第一个参数为用来保存所有的进程 ID

   5: //第二个参数则是第一个参数的字节数

   6: //第三个参数则是写入 dwProcess 数组的字节数

   7: EnumProcesses(dwProcess, sizeof(dwProcess), &dwNeeded);

   8:  

   9: //找到 explorer.exe 进程的 ID

  10: dwExplorerId = 0;

  11: for(int i = 0; i < dwNeeded / sizeof(DWORD); i++)

  12: {

  13:     if(0 != dwProcess[i])

  14:     {

  15:         if(ProcessIsExplorer(dwProcess[i]))

  16:         {

  17:             dwExplorerId = dwProcess[i];

  18:             break;

  19:         }

  20:     }

抱歉!评论已关闭.