加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 服务器 > 安全 > 正文

网络安全知识点:远程线程编程

发布时间:2021-05-23 14:02:11 所属栏目:安全 来源:互联网
导读:Windows操作系统下,为了避免各个进程相互影响,每个进程地址空间都是被隔离的。所谓 远程线程,并不是跨计算机的,而是跨进程的。简单来说,就是进程A要在进程B中创建一个线程,这就叫远程线程。 远程线程被木马、外挂等程序广泛使用,反病毒软件中也离不开

Windows操作系统下,为了避免各个进程相互影响,每个进程地址空间都是被隔离的。所谓 “远程线程”,并不是跨计算机的,而是跨进程的。简单来说,就是进程A要在进程B中创建一个线程,这就叫远程线程。

远程线程被木马、外挂等程序广泛使用,反病毒软件中也离不开远程线程的技术。技术应用的两面性取决于自己的个人行为意识,良性的技术学习对自己的人生发展是非常有好处的,就算谈不上好处,至少不会给自己带来不必要的麻烦。

关于远程线程的知识,本文介绍3个例子,分别是DLL的注入、卸载远程DLL和不依赖DLL进行代码注入。

1. DLL远程注入

木马或病毒编写的好坏取决于其隐藏的程度,而不在于其功能的多少。无论是木马还是病毒,都是可执行程序。如果它们是EXE文件的话,那么在运行时必定会产生一个进程,就很容易被发现。为了不被发现,在编写木马或病毒时可以选择将其编写为DLL文件。DLL文件的运行不会单独创建一个进程,它的运行被加载到进程的地址空间中,因此其隐蔽性相对较好。DLL文件如果不被进程加载又如何在进程的地址空间中运行呢?方式是强制让某进程加载DLL文件到其地址空间中去,这个强制的手段就是现在要介绍的远程线程。

创建远程线程的函数CreateRemoteThread()的定义如下:


  1. HANDLE CreateRemoteThread(  
  2.  HANDLE hProcess,  
  3.  LPSECURITY_ATTRIBUTES lpThreadAttributes,  
  4.  DWORD dwStackSize,  
  5.  LPTHREAD_START_ROUTINE lpStartAddress,  
  6.  LPVOID lpParameter,  
  7.  DWORD dwCreationFlags,  
  8.  LPDWORD lpThreadId  
  9. ); 

该函数的功能是创建一个远程的线程。我们把CreateThread()函数和CreateRemoteThread()函数进行比较。对于CreateThread()函数来说,CreateRem oteThread()函数比其多了一个hProcess参数,该参数是指定要创建线程的进程句柄。其实CreateThread()函数的内容实现就是依赖于CreateRemoteThread()函数来完成的。CreateThread()函数的代码实现如下:


  1. /*  
  2.   * @implemented  
  3. */  
  4. HANDLE 
  5. WINAPI  
  6. CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,  
  7.   DWORD dwStackSize, 
  8.   LPTHREAD_START_ROUTINE lpStartAddress,  
  9.   LPVOID lpParameter,  
  10.   DWORD dwCreationFlags,  
  11.   LPDWORD lpThreadId)  
  12.  
  13.   /* 创建远程线程  
  14.   return CreateRemoteThread(NtCurrentProcess(), 
  15.     lpThreadAttributes,  
  16.     dwStackSize,  
  17.     lpStartAddress, 
  18.     lpParameter,  
  19.     dwCreationFlags,  
  20.     lpThreadId);  

在上面的代码中,NtGetCurrentProcess()函数的功能是获得当前进程的句柄。

CreateRemoteThread()函数是给其他进程创建线程使用的,其第一个参数是指定某进程的句柄,获取进程的句柄使用API函数OpenProcess(),该函数需要提供PID作为参数。

除了hProcess参数以外,剩余的关键参数就只有lpStartAddress和lpParameter两个了。lpStartAddress指定线程函数的地址,lpParameter指定传递给线程函数的参数。前面提到,每个进程的地址空间是隔离的,那么新创建的线程函数的地址也应该在目标进程中,而不应该在调用CreateRemoteThread()函数的进程中。同样,传递给线程函数的参数也应该在目标进程中。

如何让线程函数的地址在目标进程中呢?如何让线程函数的参数也可以传递到目标进程中呢?在讨论这个问题以前,先来考虑线程函数要完成的功能。这里主要完成的功能是注入一个DLL文件到目标进程中,那么线程函数的功能就是加载DLL文件。加载DLL文件使用的是LoadLibrary()函数。LoadLibrary()函数的定义:


  1. HMODULE LoadLibrary(  
  2.  LPCTSTR lpFileName  
  3. );  
  4. 看一下线程函数的定义格式,具体如下: 
  5. DWORD WINAPI ThreadProc(  
  6.  LPVOID lpParameter  
  7. ); 

比较两个函数可以发现,除了函数的返回值类型和参数类型以外,其函数格式是相同的。这里只考虑其相同的部分。因为其函数的格式相同,首先调用约定相同,都是WINAPI(也就是__stdcall方式);其次函数个数相同,都只有一个。那么,可以直接把LoadLibrary()函数作为线程函数创建到指定的进程中。LoadLibrary()的参数是欲加载的DLL文件的完整路径,只要在CreateRemoteThread()函数中赋值一个指向DLL文件完整路径的指针给LoadLibrary()函数即可。这样使用CreateRemoteThread()函数就可以创建一个远程线程了。不过,还有两个问题没有解决,首先是如何将LoadLibrary()函数的地址放到目标进程空间中让CreateRemoteThread()调用,其次是传递给LoadLibrary()函数的参数也需要在目标进程空间中,并且要通过CreateRemoteThread()函数指定给LoadLibrary()函数。

首先解决第1个问题,即如何将LoadLibrary()函数的地址放到目标进程空间中。LoadLibrary()函数是系统中的Kernel32.dll的导出函数,Kernel32.dll这个DLL文件在任何进程中的加载位置都是相同的,也就是说,LoadLibrary()函数的地址在任何进程中的地址都是相同的。因此,只要在进程中获得LoadLibrary()函数的地址,那么该地址在目标进程中也可以使用。CreateRemoteThread()函数的线程地址参数直接传递LoadLibrary()函数的地址即可。

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读