WIN32汇编语言教程:第13章 进程控制 · 13.4 进程的隐藏(3)
3. 远程线程的具体实现
好了,经过这么长时间的纸上谈兵,现在动真格的(本节中的所有源程序都可以在所附光盘的Chapter13\RemoteThread目录中找到),还记得第04章中的窗口例子吗?我们的目标就是将这个创建窗口的程序整个搬到Windows的文件管理器Explorer.exe进程中去执行。选定文件管理器开刀的原因是,它是Windows的“常任理事”,这个进程任何时刻都在运行,所以不必担心找不到它。
读者可能会问,难道连包含消息循环、窗口过程的代码都可以放到远程线程中去执行吗?当然可以,因为第12章中已经介绍过,每个线程的消息队列是独立的,远程线程的消息循环并不会和Explorer.exe程序原来的消息循环互相混淆。
工作的第一步就是设计远程线程使用的代码,代码中必须包括一个线程函数用做远程线程执行的入口,在线程函数中必须完成所有所需DLL的装入工作和API函数地址的获取工作,然后调用创建窗口的主程序;第二步就是修改所有访问全局变量的代码,以解决重定位问题。
完工后的远程代码存放在RemoteCode.asm文件中:
;####################################################################
REMOTE_CODE_START equ this byte
_lpLoadLibrary dd ? ;导入函数地址表
_lpGetProcAddress dd ?
_lpGetModuleHandle dd ?
_lpDestroyWindow dd ?
_lpPostQuitMessage dd ?
_lpDefWindowProc dd ?
_lpLoadCursor dd ?
_lpRegisterClassEx dd ?
_lpCreateWindowEx dd ?
_lpShowWindow dd ?
_lpUpdateWindow dd ?
_lpGetMessage dd ?
_lpTranslateMessage dd ?
_lpDispatchMessage dd ?
_hInstance dd ?
_hWinMain dd ?
_szClassName db 'RemoteClass',0
_szCaptionMain db 'RemoteWindow',0
_szDestroyWindow db 'DestroyWindow',0
_szPostQuitMessage db 'PostQuitMessage',0
_szDefWindowProc db 'DefWindowProcA',0
_szLoadCursor db 'LoadCursorA',0
_szRegisterClassEx db 'RegisterClassExA',0
_szCreateWindowEx db 'CreateWindowExA',0
_szShowWindow db 'ShowWindow',0
_szUpdateWindow db 'UpdateWindow',0
_szGetMessage db 'GetMessageA',0
_szTranslateMessage db 'TranslateMessage',0
_szDispatchMessage db 'DispatchMessageA',0
_szDllUser db 'User32.dll',0
;####################################################################
_RemoteThread proc uses ebx edi esi lParam
local @hModule
call @F
@@:
pop ebx
sub ebx,offset @B
;********************************************************************
_invoke [ebx + _lpGetModuleHandle],NULL
mov [ebx + _hInstance],eax
lea eax,[ebx + offset _szDllUser]
_invoke [ebx + _lpGetModuleHandle],eax
mov @hModule,eax
lea esi,[ebx + offset _szDestroyWindow]
lea edi,[ebx + offset _lpDestroyWindow]
.while TRUE
_invoke [ebx + _lpGetProcAddress],@hModule,esi
mov [edi],eax
add edi,4
@@:
lodsb
or al,al
jnz @B
.break .if ! byte ptr [esi+1]
.endw
;********************************************************************
call _WinMain
ret
_RemoteThread endp
;####################################################################
_ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParam
call @F
@@:
pop ebx
sub ebx,offset @B
;********************************************************************
mov eax,uMsg
.if eax == WM_CLOSE
_invoke [ebx + _lpDestroyWindow],hWnd
_invoke [ebx + _lpPostQuitMessage],NULL
;********************************************************************
.else
_invoke [ebx + _lpDefWindowProc],hWnd,\
uMsg,wParam,lParam
ret
.endif
;********************************************************************
xor eax,eax
ret
_ProcWinMain endp
;####################################################################
_ZeroMemory proc _lpDest,_dwSize
push edi
mov edi,_lpDest
mov ecx,_dwSize
xor eax,eax
cld
rep stosb
pop edi
ret
_ZeroMemory endp
;####################################################################
_WinMain proc uses ebx esi edi _lParam
local @stWndClass:WNDCLASSEX
local @stMsg:MSG