动态VXD学习
2007-05-02 09:30:40 来源:WEB开发网完整例子:
下面是一段加载动态VxD并且通过DeviceIoControl API 来调用VxD内部函数的Win32应用程序的源代码。
; VxDLoader.asm
.386
.model flat,stdcall
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.data
AppName db "DeviceIoControl",0
VxDName db "\\.\shellmsg.vxd",0
Success db "The VxD is successfully loaded!",0
Failure db "The VxD is not loaded!",0
Unload db "The VxD is now unloaded!",0
MsgTitle db "DeviceIoControl Example",0
MsgText db "I'm called from a VxD!",0
InBuffer dd offset MsgTitle
dd offset MsgText
.data?
hVxD dd ?
.code
start:
invoke CreateFile,addr VxDName,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0
.if eax!=INVALID_HANDLE_VALUE
mov hVxD,eax
invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION
invoke DeviceIoControl,hVxD,1,addr InBuffer,8,NULL,NULL,NULL,NULL
invoke CloseHandle,hVxD
invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION
.else
invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR
.endif
invoke ExitProcess,NULL
end start
下面这段源代码是由 vxdloader.asm 调用的动态VxD。
; ShellMsg.asm
.386p
include vmm.inc
include vwin32.inc
include shell.inc
DECLARE_VIRTUAL_DEVICE SHELLMSG,1,0, SHELLMSG_Control,\
UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER
Begin_control_dispatch SHELLMSG
Control_Dispatch w32_DeviceIoControl, OnDeviceIoControl
End_control_dispatch SHELLMSG
VxD_PAGEABLE_DATA_SEG
pTitle dd ?
pMessage dd ?
VxD_PAGEABLE_DATA_ENDS
VxD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==DIOC_Open
xor eax,eax
.elseif [esi].dwIoControlCode==1
mov edi,[esi].lpvInBuffer
;-----------------------------------
; copy the message title to buffer
;-----------------------------------
VMMCall _lstrlen, <[edi]>
inc eax
push eax
VMMCall _HeapAllocate,<eax,HEAPZEROINIT>
mov pTitle,eax
pop eax
VMMCall _lstrcpyn,<pTitle,[edi],eax>
;-----------------------------------
; copy the message text to buffer
;-----------------------------------
VMMCall _lstrlen, <[edi+4]>
inc eax
push eax
VMMCall _HeapAllocate,<eax,HEAPZEROINIT>
mov pMessage,eax
pop eax
VMMCall _lstrcpyn,<pMessage,[edi+4],eax>
mov edi,pTitle
mov ecx,pMessage
mov eax,MB_OK
VMMCall Get_Sys_VM_Handle
VxDCall SHELL_sysmodal_Message
VMMCall _HeapFree,pTitle,0
VMMCall _HeapFree,pMessage,0
xor eax,eax
.endif
ret
EndProc OnDeviceIoControl
VxD_PAGEABLE_CODE_ENDS
end
分析:
我们从VxDLoader.asm开始。
Invoke CreateFile,addrVxDName,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0
.if eax!=INVALID_HANDLE_VALUE
mov hVxD,eax
....
.else
invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR
.endif
我们调用CreateFile来加载动态VxD。注意FILE_FLAG_DELETE_ON_CLOSE标记。当从CreateFile返回的VxD句柄被关闭的时候,这个标志通知Windows卸载VxD。如果CreateFile成功,我们把VxD句柄保存起来。
invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION
invoke DeviceIoControl,hVxD,1,addr InBuffer,8,NULL,NULL,NULL,NULL
invoke CloseHandle,hVxD
invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION
当VxD加载/卸载的时候,这个程序会显示一个消息框。它令dwIoControlCode=1然后调用DeviceIoControl。将InBuffer的地址传给lpInBuffer,将InBuffer的大小传给nInBufferSize。InBuffer是一个包括两个元素的数组:每个元素都是一个字符串的地址。
MsgTitle db "DeviceIoControl Example",0
MsgText db "I'm called from a VxD!",0
InBuffer dd offset MsgTitle
dd offset MsgText
现在我们看一下这段VxD。
它只处理w32_deviceIoControl消息。当w32_deviceIoControl消息发送的时候,调用OnDeviceIoControl函数。
BeginProc OnDeviceIoControl
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==DIOC_Open
xor eax,eax
OnDeviceIoControl 处理DIOC_Open,再eas中返回0。
.elseif [esi].dwIoControlCode==1
mov edi,[esi].lpvInBuffer
它也处理control code 等于1。它做的第一件事是取出在lpyInBuffer中的数据。这个数据是传送到DeviceIoControl API 的lpInBuffer中的两个dword值。它把指向dword数组的地址放到edi中。第一个dword是作为消息框标题的字符串地址。第二个dword是作为消息框文本的字符串地址。
;-----------------------------------
; copy the message title to buffer
;-----------------------------------
VMMCall _lstrlen, <[edi]>
inc eax
push eax
VMMCall _HeapAllocate,<eax,HEAPZEROINIT>
mov pTitle,eax
pop eax
VMMCall _lstrcpyn,<pTitle,[edi],eax>
它调用VMM服务lstrlen来计算消息框标题的长度。lstrlen在eax中返回字符串的长度。我们把这个长度加1来包括结束标记NULL。下一步我们通过调用HeapAllocate来分配一块足够大可以容纳字符串和它的结束标记NULL内存。加上HEAPZEROINIT标记使HeapAllocate将这块内存清零。HeapAllocate在eax中返回这块内存的地址。我们然后从win32 app的地址空间把字符串拷贝到我们申请的内存中。我们对要做消息框文本的字符串做同样的操作。
mov edi,pTitle
mov ecx,pMessage
mov eax,MB_OK
VMMCall Get_Sys_VM_Handle
VxDCall SHELL_sysmodal_Message
我们把标题和文本的地址分别存在edi和ecx中。把想要的标记放在eax中,通过调用Get_Sys_VM_handle得到系统VM的VM 句柄。然后调用SHELL_sysbodal_Message 。SHELL_sysModal_Message是系统SHELL_Message的模式版本。它冻结系统直到用户对消息框做出反应。
VMMCall _HeapFree,pTitle,0
VMMCall _HeapFree,pMessage,0
当SHELL_sysmodal_Message返回时,我们用_HeapFree释放内存。
总结:
DeviceIoControl接口使你的win32应用程序使用动态VxD作为一个ring-0 DLL扩展非常理想。
更多精彩
赞助商链接