关于利用进程间通信实现程序自我保护(2)
作者:佚名; 更新时间:2014-12-05

  线程是属于进程的,它没有自己的独立的数据地址空间,线程运行在进程空间内,因此线程的切换速度比较快。同一进程所产生的线程共享同一内存空间,而这些线程的执行由系统调度程序控制,调度程序决定哪个线程可执行以及什么时候执行线程。线程有优先级别,优先权较低的线程必须等到优先权较高的线程执行完后再执行。当进程退出时该进程所产生的线程都会被强制退出并清除。线程可与属于同一进程的其他线程共享虚地址空间、全局变量,以及该进程所拥有的全部资源,包括打开的文件、信号标志及动态分配的内存等。但是其本身基本上不拥有系统资源,只拥有一点在运行中必不可少的信息(如程序计数器、一组寄存器和栈)。
  线程有点像进程身体内的细胞,我们通常听过多进程多线程,单进程多线程。这就是说,一个系统内有几个进程,如果进程是多个,就是多进程的,如果进程内有多个线程,那就是多线程的,多进程多线程的系统比单进程多线程的系统速度慢,但是可靠性高。

  5.程序的设计与实现

  程序的自我保护是一个大的概念,其中有多种方式和手段来实现自身的保护。比如隐藏、自我复制、注册为服务,等等。我们实现的程序自我保护实际上是一个相互监督的过程。其中包括了程序之间的监督和报警,监听程序的隐藏与保护。

  5.1监督
  所谓监督,是利用进程枚举的方法,让所有程序在运行同时不停地对进程列表进行快照,并检查目标进程是否存在的过程。
  在Windows环境下可以通过调用ToolHelp API函数来达到枚举系统进程的目的。微软的Windows NT开发小组因为不喜欢ToolHelp函数,所以没有将这些函数添加给Windows NT,所以开发了自己的Process Status函数,就是PSAPI。但是后来微软已经将ToolHelp函数添加给了Windows 2000。ToolHelp32库函数在KERNEL32.dll中,它们都是标准的API函数。
  ToolHelp32库中有各种各样的函数可以用来枚举系统中的进程、线程,以及获取内存和模块信息。其中枚举进程只需用如下三个的函数:CreateToolhelp32Snapshot()、Process32First()和Process32Next()。
  使用ToolHelp32函数的第一步是用CreateToolhelp32Snapshot()函数创建系统信息“快照”。这个函数可让你选择存储在快照中的信息类型。如果你只是对进程信息感兴趣,那么只要包含TH32CS_SNAPPROCESS标志即可。CreateToolhelp32Snapshot()函数返回一个HANDLE,完成调用之后,必须将此HANDLE传给CloseHandle()。
  接下来是调用一次Process32First函数,从快照中获取进程列表,然后重复调用Process32Next,直到函数返回FALSE为止。这样将遍历快照中进程列表。这两个函数都带两个参数,它们分别是快照句柄和一个PROCESSENTRY32结构。
  调用完Process32First或Process32Next之后,PROCESSENTRY32中将包含系统中某个进程的关键信息。它的具体内容如下:
  typedef struct tagPROCESSENTRY32{
  DWORD dwSize;
  DWORD cntUsage;
  DWORD th32ProcessID;
  DWORD th32DefaultHeapID;
  DWORD th32ModuleID;
  DWORD cntThreads;
  DWORD th32ParentProcessID;
  LONG pcPriClassBase;
  DWORD dwFlags;
  TCHAR szExeFile;
  DWORD th32MemoryBase;
  DWORD th32AccessKey;
  }PROCESSENTRY32;
  其中进程ID就存储在此结构的th32ProcessID。此ID可以被传给OpenProcess()API以获得该进程的句柄。对应的可执行文件名及其存放路径存放在szExeFile结构成员中。在该结构中还可以找到其他一些有用的信息。

  5.2报警
  这里的报警就涉及了进程间通信的概念。本文中涉及的进程间通信是用剪贴板的方法,剪贴板在我们实际应用中是用得比较多的,它实际上是系统维护管理的一个内存区域,当我们在一个程序中复制数据的时候,实际上是将这些数据放入了内存,相反,当我们在另一个程序中粘贴数据时实际上是从内存取出数据。下面介绍一下使用剪贴板时的主要函数:打开剪贴板OpenClipboard(),不管是对剪贴板的读还是写,都要首先调用此函数,以判断是否可以对剪贴板进行操作。此函数是BOOL型的,如果调用成功就返回非零,否则返回零。清空剪贴板EmptyClipborad(),每次对剪贴板的写入操作之前,都应该调用此函数,这个函数的作用不仅是清空剪贴板,而且起到获得剪贴板的使用权的作用。同样,这个函数也是BOOL型的,如果调用成功就返回非零,否则返回零。对剪贴板写入SetClipboardData(UINT uFormat,HANDLE hMem),这个函数有两个参数,第一个参数用来表示写入剪贴板数据的格式,第二个参数接收一个句柄值,在这里它接收一个指向内存对象的句柄,这个内存对象中存放着准备写入剪贴板的数据内容。在调用SetClipboardData(UINT uFormat,HANDLE hMem)之前还需要调用GlobalAlloc(UINT uFlags,SIZE_T dwSytes)这样一个函数,它专门用来为将要写入的数据分配一块内存空间。这个函数接收两个参数,第一个参数表示如何来分配内存空间,这里我们将它设置为GMEM_MOVEABLE,表示动态分配内存。第二个参数是表示分配内存空间的大小。GlobalAlloc(UINT uFlags,SIZE_T dwSytes)返回一个句柄,我们无法使用句柄来间接的将数据放入内存,这时就需要调用另一个函数GlobalLock(HGLOBAL hMem),这个函数获得一个内存对象的句柄,将这块内存加锁,返回一个指针,这时我们就可以给指针所指向的这块内存写入数据了。这个函数使用一个内存计数,计数器基数为零,每调用一次计数器加一,所以每调用一次的同时还需要调用另外一个函数GlobalUnlock(HGLOBAL hMem)来给计数器减一,相当于取消对这块内存的锁定。本文设计的程序实现报警功能就是在枚举进程之后发现目标进程被终止,从而在剪贴板中写入信息的过程。

  5.3监听
  所谓监听,就是报警的反方向,即从剪贴板中读出信息。从剪贴板读取数据的函数GetClipboardData(UINT uFormat)。这个函数只接收一个参数,参数指定读取的格式。读取信息之后,我们还要对信息进行if判断,如果信息是我们预留的某个进程被结束的话,我们就启动保护措施。

  5.4保护和隐藏
  这里的保护是指监听程序对其他程序的保护,方法非常简单,只需要利用WinExec函数来实现目标进程的启动就可以。而隐藏是指监听程序自身的隐藏,只要在OnPaint()函数里调用ShowWindow(SW_HIDE)函数就可以了,信捷职称论文写作发表网,同时将监听程序命名为smss,就可以避免其被强行终止。

  6.结语

  本文中程序的设计是模仿病毒的一些特性而做成的。它实现了程序的隐藏,并且利用了系统的漏洞实现了不被终止。对我们了解病毒的特征提供了良好平台,同时对一般程序自我保护的设计有很好的现实意义。
核心期刊快速发表
Copyright@2000-2030 论文期刊网 Corporation All Rights Reserved.
《中华人民共和国信息产业部》备案号:ICP备07016076号;《公安部》备案号:33010402003207
本网站专业、正规提供职称论文发表和写作指导服务,并收录了海量免费论文和数百个经国家新闻出版总署审批过的具有国内统一CN刊号与国际标准ISSN刊号的合作期刊,供诸位正确选择和阅读参考,免费论文版权归原作者所有,谨防侵权。联系邮箱:256081@163.com