Deviceiocontrol Interface
WE WILL Learn About Dynamic vxd in this Tutorial. Specification, We Will Learn How To create, load and use them.
Vxd Interfaces
There Are A Total of 4 Interfaces That Vxd Provides.
VXD Services V86 Interface Protected-Mode (PM) Interface Win32 DeviceioControl Interface
We already know about VxD services. V86 and PM interfaces are functions that are callable from V86 and PM applications respectively. Since V86 and PM applications are 16-bit, we can not use those two interfaces from a win32 application. With Windows 95, Microsoft adds AN Another Interface for Win32 Applications So The CAN Call on The Services of VxDs: DeviceIocontrol Interface.
Deviceiocontrol Interface
To put it simply, the DeviceIoControl interface is a way for win32 applications to call functions inside VxDs Do not confuse functions called via DeviceIoControl with VxD services:.. They are not the same For example, DeviceIoControl function 1 may not be the same as Vxd Service 1. You Should Think of Deviceiocontrol Functions as a Separate Group of functions, provided for use by win32 Applications ONLY.
Since It's An Interface, There Are Two Side:
On the win32 application side:
IT Has To CREATEFILE TO OPEN / LOAD THE VXD FIRST. IF The Call is successful, The Vxd Will Be in Memory and Createfile Returns The Handle To The Vxd in Eax.
Next You Call Deviceiocontrol API Function TO SELECT The Function To Execute. Deviceiocontrol Has The Following Syntax:
Deviceiocontrol Proto Hdevice: DWORD, /
DWIOCONTROLCODE: DWORD, /
Lpinbuffer: DWORD, /
Ninbuffersize: DWORD, /
LPOUTBUFFER: DWORD, /
NOUTBUFFERSIZE: DWORD, /
LPBYTESRETURNED: DWORD, /
Lpoverlapped: dword
hDevice is the handle of the VxD returned from CreateFile dwIoControlCode is the value that specifies the operation the VxD should perform. You must somehow obtain the list of possible dwIoControlCode values for a VxD before you know what operation you should select. But most of the time , you're the one who codes the VxD so you know the list of all possible dwIoControlCode values. lpInBuffer is the address of the buffer that contains the data the VxD needs to use to perform the operation specified in dwIoControlCode. If the operation doesn ' t need data, you can pass NULL. nInBufferSize is the size, in bytes, of the data in the buffer pointed to by lpInBuffer. lpOutBuffer is the address of the buffer that the VxD will fill with the output data when the operation is successful. If the operation does not have any data to return, this field can be NULL. nOutBufferSize is the size, in bytes, of the buffer pointed to by lpOutBuffer lpBytesReturned is the address of a dword variable that will r eceive the size of data the VxD filled into lpOutBuffer lpOverlapped is the address of the OVERLAPPED structure if you want the operation to be asynchronous If you want to wait until the operation is finished, put NULL in this field.On the VxD side..:
IT Must Process W32_DeviceioControl Message .hen The Vxd Receives W32_Deviceiocontrols W32_Deviceiocontrols W32_Deviceiocontrols, ITS Registers Have The Following Values:
EBX Contains The VM Handle. ESI Is The Pointer To Diocparams Structure Which Contains Information Passed from The win32 application.
Diocparams is defined as Follows:
Diocparams Struc
INTERNAL1 DD?
VMHANDLE DD?
INTERNAL2 DD?
DWIOCONTROLCODE DD?
LPVINBUFFER DD?
CBINBUFFER DD?
LPVOUTBUFFER DD? CBOUTBUFFER DD?
LPCBBYTESRETURNED DD?
LPOOVERLAPPED DD?
HDEVICE DD?
TagProcess DD?
Diocparams Ends
Internal1 is the pointer to the client register structure of the win32 application VMHandle no explanation needed Internal2 is the pointer to device descriptor block (DDB) dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped are the parameters that were passed to DeviceIoControl API Call. hdevice is the ring-3 device handle tagproces is the process tag
From Diocparams Structure, you have all the information the win32 application passed to your vxd.
Your VxD must at least process DIOC_Open (a value passed in dwIoControlCode) which VWIN32 will send to your VxD when a win32 application calls CreateFile to open your VxD. If your VxD is ready, it must return 0 in eax and CreateFile call will be successful . If your VxD is not ready, it must return a nonzero value in eax and CreateFile will fail. Other than DIOC_Open, your VxD will receive DIOC_Closehandle code from VWIN32 when the win32 application closes the device handle.
Minimum Dynamic Vxd Skeleton That Is Loadable by Createfile
.386P
Include vmm.inc
INCLUDE VWIN32.INC
Declare_virtual_device dynavxd, 1,0, dynavxd_control, / undefined_Device_id, undefined_init_order
Begin_Control_Dispatch Dynavxd Control_Dispatch W32_DeviceioControl, ONDEVICEIOCONTROL END_CONTROL_DISPATCH DYNAVXD
VxD_PAGEABLE_CODE_SEG BeginProc OnDeviceIoControl assume esi: ptr DIOCParams .if [esi] .dwIoControlCode == DIOC_Open xor eax, eax .endif ret EndProc OnDeviceIoControl VxD_PAGEABLE_CODE_ENDS
end
; ------------------------------------------------- -------------------------------------------------- ----------------------------; Module Definition File
; ------------------------------------------------- -------------------------------------------------- ------------------------------
Vxd Dynavxd Dynamic
SEGMENTS _LPTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE _LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE _LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE _TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE _DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE _TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE _BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE _LMGTABLE CLASS 'MCODE' PRELOAD NONDISCARDABLE IOPL _LMSGDATA CLASS 'MCODE' PRELOAD NONDISCARDABLE IOPL _IMSGTABLE CLASS 'MCODE' PRELOAD DISCARDABLE IOPL _IMSGDATA CLASS 'MCODE' PRELOAD DISCARDABLE IOPL _ITEXT CLASS 'ICODE' DISCARDABLE _IDATA CLASS 'ICODE' Discardable _ptext class 'pcode' Nondiscardable _pmsgtable class 'mcode' Nondiscardable Iopl _pmsgdata class 'mcode' Nondiscardable Iopl _pdata class 'pdata' Nondiscard ABLE SHARED _STEXT CLASS 'SCODE' RESIDENT _SDATA CLASS 'SCODE' RESIDENT _DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING _DBOCODE CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING _DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING _16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE _RCODE CLASS 'RCODE' EXPORTS DYNAVXD_DDB @ 1
Full EXAMPLE
BELOW Are The Source Code of the Win32 Application That Loads a Dynamic Vxd and Calls A Function In The VXD VIA Deviceiocontrol API .; 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
Below is the source code of the dynamic vxd That Is Called by vxdloader.asm
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 PTIL 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,
end
Analysis:
We Start from vxdloader.asm.
Invoke Createfile, AddR VxDName, 0, 0, 0, 0, File_Flag_Delete_on_close, 0
.IF EAX! = INVALID_HANDLE_VALUE
MOV HVXD, EAX
....
.lse
Invoke Messagebox, NULL, AddR Failure, Null, MB_OK MB_ICONERROR
.endif
We call CreateFile to load the dynamic VxD. Note FILE_FLAG_DELETE_ON_CLOSE flag. This flag instructs Windows to unload the VxD when the VxD handle returned from CreateFile is closed. If CreateFile is successful, we store the VxD handle for future use.
Invoke Messagebox, Null, Addr Success, Addr Appname, MB_OK MB_ICONITION
Invoke DeviceioControl, HVXD, 1, Addr Inbuffer, 8, NULL, NULL, NULL, NULL
Invoke Closehandle, HVXD
Invoke Messagebox, Null, Addr Unload, Addr Appname, MB_OK MB_ICONITIONFORMATION
.. The program displays a message box when the VxD is loaded / unloaded It calls DeviceIoControl with dwIoControlCode 1 and passes the address of InBuffer in lpInBuffer parameter, and the size of InBuffer (8) in nInBufferSize InBuffer is a dword array of two elements: Each Element is the address of a text string.
Msgtitle DB "Deviceiocontrol Example", 0
MsgText DB "I'm Called From A VXD!", 0
Inbuffer DD Offset Msgtitle
DD Offset Msgtext
Now We Turn Our Attention To The VXD.
IT Processes Only W32_DeviceioControl Message. When W32_Deviceiocontrol message is sample, ONDEVICEIOCONTROL Procedure Is Called.
Beginproc ONDEviceIOCONTROL
Assume ESI: PTR Diocparams
.IF [ESI] .dwioControlcode == Dioc_open
XOR EAX, EAX
ONDEVICEIOCONTROL Processes Dioc_Open Code by Returning 0 in Eax.
.ELSEIF [ESI] .dwiocontrolcode == 1
Mov EDI, [ESI] .lpvinbuffer
It also processes control code 1. The first thing it does is to extract the data in lpvInBuffer which are the two dwords passed in lpInBuffer of DeviceIoControl API. It puts the address to the dword array into edi for extraction. The first dword is the address Of the text to be used as the message box title. The second to be used as the message box text.
; -----------------------------------
Copy The Message Title To Buffer
; -----------------------------------
Vmmcall_lstrlen, <[EDI]>
INC EAX
Push EAX
Vmmcall_heapallocate,
Mov PTITLE, EAX
Pop Eaxvmmcall_LSTRCPYN,
It calculates the length of the message box title by calling VMM service _lstrlen. The value in eax returned by _lstrlen is the length of the string. We increase the length by 1 to take into account the terminating NULL. Next we allocate a block of memory large enough to hold the string with its terminating NULL by calling _HeapAllocate. HEAPZEROINIT flag instructs _HeapAllocate to zero out the memory block. _HeapAllocate returns the address of the memory block in eax. We then copy the string from the address space of the win32 app into The Memory Block We Allocated. We do the Same Operation on The Text String That We will use as the message box text.
Mov Edi, Ptitle
Mov ECX, PMessage
Mov Eax, MB_OK
VMMCALL GET_SYS_VM_HANDLE
Vxdcall shell_sysmodal_message
We store the addresses of the title and message into edi and ecx, respectively. Put the desired flag into eax, obtain the VM handle of the system VM by calling Get_Sys_VM_handle and then call SHELL_Sysmodal_Message. SHELL_SysModal_Message is the system modal version of SHELL_Message. It freezes The System Until The User Responds To The Message Box.
Vmmcall _heapfree, ptitle, 0
VMMCall_HeapFree, PMessage, 0
When shell_sysmodal_message returns, we can free the memory.
Conclusion
Deviceiocontrol Interface Makes It Ideal To Use A Dynamic VXD AS A Ring-0 DLL EXTENSION TO YOR WIN32 Application.
[ICZelion's Win32 Assembly HomePage]