WIN32汇编语言教程:第13章 进程控制 · 13.4 进程的隐藏(1)

进程隐藏技术用得最多的地方就是在病毒和木马中,因为这些不适合出现在阳光下的程序,越隐蔽生存率就越高。在当今Windows环境下,病毒和木马流传得越来越广泛,让读者适当了解这方面的技术可以在防治方面起到积极的作用,技术这种东西就是这样,大家都知道的“秘技”也就不再是“秘技”了,所以,大家都知道了进程隐藏是怎么一回事,进程隐藏起来也就不那么隐蔽了。

13.4.1 在Windows 9x中隐藏进程

在Windows 9x系列操作系统中,可以通过Kernel32.dll中的一个未公开函数来完成隐藏功能,这个函数就是RegisterServiceProcess,该函数的功能是将一个进程注册为系统服务进程,由于Windows的任务管理器并不列出系统服务进程,所以可以用它来隐藏进程,不过该函数在Windows NT系列中并不存在。

RegisterServiceProcess函数的使用方法是:

   invoke RegisterServiceProcess,dwProcessID,dwFlag

dwProcessID指明目标进程的进程ID,参数dwFlag指定是注册还是撤销,指定TRUE的话,进程被注册为系统服务进程,如果指定为FALSE,则进程的属性恢复为普通进程属性。

Kernel32.lib导入库中并没有这个函数的导入信息,如果要使用这个函数,程序需要自己装入库文件并使用GetProcAddress函数获取入口地址后使用(方法请复习第11章)。所附光盘的Chapter13\HideProcess9x目录中的例子程序演示了该函数的使用方法。汇编源代码HideProcess9x.asm的内容如下:

                 .386

                 .model flat,stdcall

                 option casemap:none

;####################################################################

; Include 文件定义

;####################################################################

include        windows.inc

include        user32.inc

includelib     user32.lib

include        kernel32.inc

includelib     kernel32.lib

;####################################################################

; 数据段

;####################################################################

                 .const

szFunction     db     'RegisterServiceProcess',0

szDllKernel    db     'Kernel32.dll',0

szText        db    '现在请按下Ctrl+Alt+Del调出任务管理器查看是否存在本进程',0

szCaption     db    '在Windows 9x中隐藏进程',0

szErr         db    '本功能只在Windows 9x中提供',0

;####################################################################

; 代码段

;####################################################################

                 .code

start:

                 invoke GetModuleHandle,offset szDllKernel

                 .if    eax

                         invoke GetProcAddress,eax,offset szFunction

                         .if    eax

                                 mov    ebx,eax

                                 push   TRUE

                                 invoke GetCurrentProcessId

                                 push       eax

                                 call       ebx

                                 invoke MessageBox,NULL,offset szText,\

                                         offset szCaption,MB_OK

                                 jmp    @F

                         .endif

                 .endif

                 invoke MessageBox,NULL,offset szErr,NULL,\

                         MB_OK or MB_ICONWARNING

                 @@:

                 invoke ExitProcess,NULL

;####################################################################

                 end    start

由于可以确认Kernel32.dll库已经被装载到进程的地址空间中(GetProcAddress等函数就包括在这个库中,因此这个库肯定已经被装入),所以例子中使用GetModuleHandle函数而不是使用LoadLibrary函数来获取库句柄,这样就可以省去一个FreeLibrary的调用。接下来,程序使用GetProcAddress函数获取RegisterServiceProcess函数的入口地址,如果获取成功,则使用GetCurrentProcessId函数获取当前进程的ID并将这个ID注册为系统服务进程。

RegisterServiceProcess的缺点就是只能“欺骗”Windows的任务管理器,使用快照函数还是可以将全部进程枚举出来,即使是13.3.1节中的ProcessList.exe例子,也可以发现用RegisterServiceProcess隐藏的进程。所以使用这个函数只能实现简单的进程隐藏功能。相比之下,Windows NT下远程线程的功能就要强大得多了。

13.4.2 Windows NT中的远程线程

在Windows 9x中将进程注册为系统服务进程就能够从任务管理器中隐形,但在NT下就不同了。首先,NT下不存在RegisterServiceProcess函数;其次,NT的任务管理器会列出所有的进程(包括系统进程),即使一个进程将自己的可执行文件放在很隐蔽的目录中,文件名还是会被任务管理器列出来,所以想让别人看不见进程是不可能的。

当然,如果不用进程也能运行程序的话,那是最好不过的办法了,但是不用进程是无法执行文件的。

再从另一个角度考虑,如果进程显示的不是正确的名称呢,这也可以起到掩护作用,如果在DLL中执行我们的代码,系统报告的进程名称是装入DLL的进程的名称,而不是DLL本身的名称。

在Windows NT中还有另一种办法,那就是使用远程线程,使用它可以在其他进程中创建一个线程,由于线程是被所属进程拥有的,所以任务管理器中列出来的还是所属进程的名称。

1. Windows NT的远程操作函数

有两个函数可以用来实现上述功能:VirtualAllocEx和CreateRemoteThread。这两个函数都只能在Windows NT下使用。

VirtualAllocEx函数可以用来在其他进程的地址空间内申请内存,当然申请到的内存也是位于目标进程的地址空间内的,将这个函数和WriteProcessMemory函数配合就可以在目标进程的地址空间中“造”出任何东西来。

VirtualAllocEx函数的用法是:

   invoke VirtualAllocEx,hProcess,lpAddress,dwSize,\

          flAllocationType,flProtect

   .if    eax

          mov    lpMemory,eax

   .endif

在10.1.5节中已经介绍过虚拟内存管理函数VirtualAlloc,VirtualAllocEx函数就是这个函数的扩充,相比之下,VirtualAllocEx函数多了一个参数hProcess,其他参数定义和使用的方法都和VirtualAlloc函数相同,读者可以回过头去查看这些参数的用法。新增的hProcess参数用来指定要申请内存的进程句柄,如果需要在目标进程中使用VirtualAllocEx函数,那么必须对进程拥有PROCESS_VM_OPERATION权限。

如果内存申请成功,函数返回一个指针,指向申请到的内存块,当然这个指针是针对目标进程的地址空间的。如果内存申请失败,函数返回NULL。

CreateRemoteThread函数用来在其他进程内创建一个线程,当然创建的线程是运行于目标进程的地址空间内的,它和目标进程自己创建的线程并没有什么区别。函数的用法是:

   invoke CreateRemoteThread,hProcess,lpThreadAttributes,dwStackSize,\

          lpStartAddress,lpParameter,dwCreationFlags,lpThreadId

上页:第13章 进程控制 · 13.3 进程调试(8) 下页:第13章 进程控制 · 13.4 进程的隐藏(2)

第13章 进程控制

版权所有 © 云南伯恩科技 证书:粤ICP备09170368号