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

 

                  .const

szErrOpen          db     '无法打开远程线程!',0

szDesktopClass    db    'Progman',0

szDesktopWindow    db    'Program Manager',0

szDllKernel        db    'Kernel32.dll',0

szLoadLibrary     db    'LoadLibraryA',0

szGetProcAddress   db    'GetProcAddress',0

szGetModuleHandle  db    'GetModuleHandleA',0

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

                 .code

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

include       RemoteCode.asm

start:

invoke GetModuleHandle,addr szDllKernel

mov    ebx,eax

invoke GetProcAddress,ebx,offset szLoadLibrary

mov    lpLoadLibrary,eax

invoke GetProcAddress,ebx,offset szGetProcAddress

mov    lpGetProcAddress,eax

invoke GetProcAddress,ebx,offset szGetModuleHandle

mov    lpGetModuleHandle,eax

;********************************************************************

; 查找文件管理器窗口并获取进程ID,然后打开进程

;********************************************************************

invoke FindWindow,addr szDesktopClass,addr szDesktopWindow

invoke GetWindowThreadProcessId,eax,offset dwProcessID

mov    dwThreadID,eax

invoke OpenProcess,PROCESS_CREATE_THREAD or PROCESS_VM_WRITE\

          PROCESS_VM_OPERATION,FALSE,dwProcessID

.if    eax

          mov    hProcess,eax

;********************************************************************

; 在进程中分配空间并将执行代码拷贝过去,然后创建一个远程线程

;********************************************************************

      invoke VirtualAllocEx,hProcess,NULL,REMOTE_CODE_LENGTH,MEM_COMMIT,\

             PAGE_EXECUTE_READWRITE

      .if    eax

             mov    lpRemoteCode,eax

             invoke WriteProcessMemory,hProcess,lpRemoteCode,\

                     offset REMOTE_CODE_START,REMOTE_CODE_LENGTH,\

                     offset dwTemp

             invoke WriteProcessMemory,hProcess,lpRemoteCode,\

                     offset lpLoadLibrary,sizeof dword * 3,offset dwTemp

             mov    eax,lpRemoteCode

             add    eax,offset _RemoteThread - offset REMOTE_CODE_START

             invoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULL

             invoke CloseHandle,eax

      .endif

      invoke  CloseHandle,hProcess

.else

      invoke MessageBox,NULL,addr szErrOpen,NULL,MB_OK or MB_ICONWARNING

.endif

invoke ExitProcess,NULL

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

end    start

在程序开始,首先获取LoadLibrary,GetProcAddress和GetModuleHandle函数的入口地址,这些地址将在远程线程中被用来获取其他API的入口地址。

接下来就是打开Explorer.exe进程的操作,程序通过GetWindowThreadProcessId和OpenProcess函数来完成,函数中使用的窗口句柄是桌面的窗口句柄,因为桌面就是由文件管理器进程创建的,桌面的窗口类是“Progman”,窗口名称是“Program Manager”,使用FindWindow函数就可以很方便地找到它。在打开进程的时候必须包括对应的权限,PROCESS_CREATE_THREAD权限将允许创建远程线程,PROCESS_VM_OPERATION权限将允许在目标进程中分配内存并将远程代码写到里面。

程序使用VirtualAllocEx函数在目标进程中分配内存,在分配内存的时候,内存属性必须指定为PAGE_EXECUTE_READWRITE,这样分配到的内存可以有执行和读写的权限,分配方式必须指定为MEM_COMMIT,这样内存才会被提交到物理内存中去。

在分配到内存以后,程序使用WriteProcessMemory将远程代码写入,然后再一次将LoadLibrary,GetProcAddress和GetModuleHandle函数的地址写入到远程代码的数据段中。并不将这3个函数的地址存放到远程代码中一次性写入的原因在于:远程代码(包括远程代码使用的数据)是定义在本地的代码段中的,而本地的代码段是只读的,我们无法在本地对它们进行写入初始化数据的操作,所以只好采用远程写入的方式。

最后,用CreateRemoteThread函数创建远程线程后就万事大吉了。编译链接以后运行可执行文件可看到,窗口正常出现了,一眼看上去,这个窗口和别的窗口没有任何不同!但是在任务管理器中却没有多出任何新的进程。

假如远程线程不是这样“招摇过市”地创建了一个窗口,而是在后台偷偷地运行的话,大家能不能从各种蛛丝马迹来发现它的存在呢?反正笔者是找不到它的,因为它仅存在于目标进程的内存中,并不对应任何磁盘文件,当远程线程被执行的时候,惟一可以发现的就是Explorer.exe进程中的活动线程多了一个,使用的内存多了一点而已,但是活动线程用工具软件查看也只能看到一个线程ID,又怎么知道这个线程不是Explorer.exe进程自己的呢?

 以上代码用在不合适的地方可能产生危害,笔者第一次公开这段代码,其目的就是希望能对有害代码的防治起到积极的作用,请读者负责任地使用这段代码。

上页:第13章 进程控制 · 13.4 进程的隐藏(4) 下页:第14章 异常处理 · 14.1 异常处理的用途

第13章 进程控制

版权所有 © 中山市飞娥软件工作室 证书:粤ICP备09170368号