In the previous tutorial, we talked about how to write a VxD program. Now we have to apply what we have learned. In this section, we write a static VxD that pops up a message box when a virtual machine is created or destroyed.
Download the example here.
Capturing virtual machine creation and end events
When a virtual machine is created, VMM sends CREATE_VM control messages to all the VxD programs. When a virtual machine exits, it also sends Vm_terminate and VM_TERMINATE2 messages to all the VxD programs. Our work is simple: process CREATE_VM and VM_TERMINATE2 messages in device control procedures. When our VXD program receives both control messages, it pops up a message box on the screen.
When the VXD program receives a CREATE_VM or VM_TERMINATE2 message, the handle of the virtual machine is stored in the EBX. A virtual-memory handle can be considered its unique ID. Each virtual machine has its own unique ID (the virtual machine handle). You can use the virtual machine ID just as you would with a process ID: when calling a function, pass it as a parameter.
Further, a virtual machine handle is actually a 32-bit linear address that points to a virtual machine control block (VMCB).
A virtual machine control block is a structure that includes a lot of important attributes about the virtual machine. It is defined as follows:
cb_s Struc
Cb_vm_status DD?
Cb_high_linear DD?
Cb_client_pointer DD?
Cb_vmid DD?
Cb_signature DD?
cb_s ENDS
Cb_vm_status contains some flag bits that reflect the state of the virtual machine.
Cb_high_linear is a linear address that points to a virtual machine image in the system share (about 3GB). This concept needs to be explained. Under Window95, a VxD cannot directly access the V86 area, in place of which the VMM maps the V86 area of each virtual machine to the system share. When a VxD program accesses or modifies the V86 area in a virtual machine, it operates in a high linear area of the virtual machine. For example, if the memory address is 0b8000h, and your VxD program accesses the area. It's going to 0b8000h the value in the Cb_high_linear and then visit that area. The changes you make in the high linear mirror region are saved to the virtual machine because the two areas share a page directory entry. Using high linear mirroring is very effective in most cases because you can even modify a virtual machine that is not the current virtual machine.
Cb_client_pointer contains the address of the client register structure. A client register structure contains the values of all registers of V86 or protected mode programs that are interrupted in a virtual machine. If your VxD program reads/alters the state of the V86 or PM program, it can change the value in the client register structure, and when VMM returns to execute the program, the changes are saved to the program.
Cb_vmid the virtual machine's authentication number. When VMM creates a virtual machine, it assigns a number to the VM. The vmid of the system virtual machine is 1.
Cb_signature contains the string "VMCB". This element is used to detect whether the virtual machine handle is valid.
Display a dialog box
A VxD program can communicate with users through virtual Shell device services. In this example we are going to use one of these: Shell_message.
Shell_message is a service function of a register method that transmits parameters through registers:
EBX the handle of the virtual machine that displays this message.
The flag bit of the EAX message box. You can look up their details in shell.inc, and they all start with mb_.
ECX the 32-bit linear address of the message to display.
32-bit linear address of the title of the EDI message box.
ESI If you want to know how the user reacts to your message box, fill in the 32-bit linear address of the return function here. If you don't want to know, use NULL.
EdX the parameters needed to transmit your return function (if you fill out the address of this function in ESI).
After return, if the call succeeds, the return flag is cleared, otherwise, the return flag is placed.
Example:
.386p
Include Vmm.inc
Include Shell.inc
Declare_virtual_device message,1,0, Message_control, undefined_device_id, Undefined_init_order
Begin_control_dispatch message
Control_dispatch CREATE_VM, Onvmcreate
Control_dispatch Vm_terminate2, Onvmclose
End_control_dispatch message
Vxd_pageable_data_seg
Msgtitle db "VxD MessageBox", 0
vmcreated db "A VM is created", 0
vmdestroyed db "A VM is destroyed", 0
Vxd_pageable_data_ends
Vxd_pageable_code_seg
Beginproc onvmcreate
mov ecx, OFFSET32 vmcreated
Commoncode:
Vmmcall Get_sys_vm_handle
MOV eax,mb_ok+mb_iconexclamation
mov edi, OFFSET32 msgtitle
XOR Esi,esi
XOR Edx,edx
Vxdcall Shell_message
Ret
Endproc onvmcreate
Beginproc Onvmclose
MOV Ecx,offset32 vmdestroyed
JMP Commoncode
Endproc Onvmclose
Vxd_pageable_code_ends
End