.386p;--------------------------------------------------------------------------------------------------------------------------------
include vmm.inc
include vwin32.incDECLARE_VIRTUAL_DEVICE DYNAVXD,1,0, DYNAVXD_Control,\
UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDERBegin_control_dispatch DYNAVXD
Control_Dispatch w32_DeviceIoControl, OnDeviceIoControl
End_control_dispatch DYNAVXDVxD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==DIOC_Open
xor eax,eax
.endif
ret
EndProc OnDeviceIoControl
VxD_PAGEABLE_CODE_ENDSend
VXD DYNAVXD DYNAMICSEGMENTS
_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' NONDISCARDABLE 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
; VxDLoader.asm
.386Voici ci-dessous le code source du VxD dynamique qui est appelé par vxdloader.asm
.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
.386p
include vmm.inc
include vwin32.inc
include shell.incDECLARE_VIRTUAL_DEVICE SHELLMSG,1,0, SHELLMSG_Control,\
UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDERBegin_control_dispatch SHELLMSG
Control_Dispatch w32_DeviceIoControl, OnDeviceIoControl
End_control_dispatch SHELLMSGVxD_PAGEABLE_DATA_SEG
pTitle dd ?
pMessage dd ?
VxD_PAGEABLE_DATA_ENDSVxD_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
;-----------------------------------
; Copie le titre du message dans le buffer
;-----------------------------------
VMMCall _lstrlen, <[edi]>
inc eax
push eax
VMMCall _HeapAllocate,<eax,HEAPZEROINIT>
mov pTitle,eax
pop eax
VMMCall _lstrcpyn,<pTitle,[edi],eax>
;-----------------------------------
; Copie le texte du message dans le 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_ENDSend
invoke CreateFile,addr VxDName,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0Nous appelons CreateFile pour charger le VxD dynamique. Notez le flag FILE_flag_DELETE_ON_CLOSE. Ce flag charge Windows de décharger le VxD quand CreateFile renvoie l'handle du VxD fermé. Si CreateFile est couronné de succès, nous stockons l'handle du VxD pour une future utilisation.
.if eax!=INVALID_HANDLE_VALUE
mov hVxD,eax
....
.else
invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR
.endif
invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATIONLe programme affiche une MessageBox lorsque le VxD est chargé ou déchargé. Il appelle DeviceIoControl avec dwIoControlCode 1 et passe l'adresse de InBuffer au paramètre lpInBuffer et la taille de InBuffer (8) à nInBufferSize. InBuffer est un tableau dword de deux éléments : chaque élément représente l'adresse d'une chaîne de caractères.
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
MsgTitle db "DeviceIoControl Example",0Passons au VxD maintenant.
MsgText db "I'm called from a VxD!",0
InBuffer dd offset MsgTitle
dd offset MsgText
BeginProc OnDeviceIoControlOnDeviceIoControl traite le code de DIOC_OPEN en rentournant 0 dans eax.
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==DIOC_Open
xor eax,eax
.elseif [esi].dwIoControlCode==1Il traite aussi le contrôle code 1. La première chose c'est de l'extraire des données de lpvInBuffer qui sont deux dwords a passer au membre lpInBuffer de l'API DeviceIoControl. Il met l'adresse du tableau dword dans edi pour l'extraction. Le premier dword est l'adresse du texte qui doit être utilisé comme titre de la MessageBox. Le second dword est l'adresse du texte qui doit être utilisé comme texte de cette même MessageBox.
mov edi,[esi].lpvInBuffer
;-----------------------------------Il calcule la longueur du titre de la MessageBox en appelant le service _lstrlen du VMM (Manager de Machines Virtuelles). La valeur dans eax rendu par _lstrlen est la longueur de la chaîne de caractères. Nous augmentons la longueur de 1 pour tenir compte du caratère NULL de terminaison. Ensuite nous réservons un bloc de mémoire assez grand pour contenir la chaîne de caractères avec en plus le NULL en appelant _HeapAllocate. Le flag HEAPZEROINIT fait débuter _HeapAllocate au bloc mémoire zéro. _HeapAllocate renvoie l'adresse du bloc mémoire dans eax. Nous recopions alors la chaîne de caractères de de l'application win32 dans le bloc mémoire que nous avons réservé. Nous faisons la même opération sur la chaîne de caractères que nous emploierons en tant que texte (contenu) de la MessageBox.
; Copie le titre du message dans le buffer
;-----------------------------------
VMMCall _lstrlen, <[edi]>
inc eax
push eax
VMMCall _HeapAllocate,<eax,HEAPZEROINIT>
mov pTitle,eax
pop eax
VMMCall _lstrcpyn,<pTitle,[edi],eax>
mov edi,pTitleNous stockons les adresses du titre et du contenu respectivement dans edi et ecx. Mettez le flag désirable dans eax, obtenez l'handle de la VM 'système VM' (Machine Virtuelle principale) en appelant Get_Sys_VM_handle et appelez ensuite SHELL_Sysmodal_Message. SHELL_SysModal_Message est le système de la version modale de SHELL_Message. Il gèle le système avant que l'utilisateur ne réponde à la MessageBox. On est stoppé sur le Call de la MessageBox tant qu'on a pas cliqué sur un de ses boutons.
mov ecx,pMessage
mov eax,MB_OK
VMMCall Get_Sys_VM_Handle
VxDCall SHELL_sysmodal_Message
VMMCall _HeapFree,pTitle,0Quand SHELL_Sysmodal_Message retourne, nous pouvons libérer les blocs mémoires en appelant _HeapFree.
VMMCall _HeapFree,pMessage,0