Client Register Structure
.
Some THEORY
VxDs are very different from normal win32 / win16 / DOS applications. VxDs are, most of the time, dormant while other normal apps do their businesses. They act like supervisors which look over other ring-3 apps and correct them when they did something wrong Typical Situation IS FOLLOWS:
...............................
The interesting thing about the above process is that, the only way VMM can affect the interrupted app is by modifying the saved register image. For example, if the VMM deems the interrupted program should resume at a different address, it can alter the value of CS: IP in the saved register image and then when the program is redispatched, it will resume execution at the new CS:. IP The VMM saves the values of the registers at the interrupted point in the client register structure.
Client_reg_struc struc
Client_EDI DD? Client_ESI DD? Client_EBP DD? Client_res0 DD? Client_EBX DD? Client_EDX DD? Client_ECX DD? Client_EAX DD? Client_Error DD? Client_EIP DD? Client_CS DW? Client_res1 DW? Client_EFlags DD? Client_ESP DD? Client_SS DW? Client_res2 DW? Client_ES DW ? Client_res3 DW? Client_DS DW? Client_res4 DW? Client_FS DW? Client_res5 DW? Client_GS DW? Client_res6 DW? Client_Alt_EIP DD? Client_Alt_CS DW? Client_res7 DW? Client_Alt_EFlags DD? Client_Alt_ESP DD? Client_Alt_SS DW? Client_res8 DW? Client_Alt_ES DW? Client_res9 DW? Client_Alt_DS DW? Client_res10 dw? Client_alt_fs dw? Client_res11 dw? Client_alt_gs dw? Client_res12 dw? Client_reg_struc ends
You can see that there are two sets of members in this structure: Client_xxx and Client_Alt_xxx This requires a little explanation In a given VM, there can be two threads of execution:... V86 and protected-mode If an interrupt occurs when a V86 program is active, the Client_xxx will contain the images of the registers of the V86 program, the Client_Alt_xxx will contain those of the PM program. Alternately, if an interrupt occurs when the PM program is active, the Client_xxx will contain the values of the PM program's registers while the Client_Alt_xxx will contain the values of the V86 program's registers The Client_resX are reserved and not used You may have a question after examining the structure:.. what if I want to alter only a byte in a register, say al The? above structure only describes word-and dword-sized registers Have no fear Take a look inside vmm.inc There are additional two structures for just this purpose:... Client_Word_Reg_Struc and Client_Byte_Reg_Struc If you wan. . T to access word-or byte-sized registers, typecast the Client_Reg_Struc into Client_Word_Reg_Struc or Client_Byte_Reg_Struc according to your need You can alsoThe next question: How can we obtain the pointer to the client register structure?
It's actually easy: most of the time, the VMM puts the address of the client register structure in ebp when it calls our VxD The client register structure in this case is the current VM's Alternatively, you can obtain this pointer from the VM handle.. . Remember That a VM Handle IS Actually The Linear Address of The VM Control Block.
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_Client_Pointer contains the pointer to the client register structure of that VM For example, you can obtain the pointer to the client register structure of the current VM by the following code:. VMMCall Get_Cur_VM_Handle; return the current VM handle in ebx assume ebx: ptr cb_s MOV EBP, [EBX CB_CLIENT_POINTER]; Pointer to Client Reg Struct
Now that we understand the client register structure, we can proceed to using it. We will use the client register structure to pass values in registers to an MS-DOS interrupt, namely, int 21h, service 2h, Display Character service. This MS- DOS service takes the character to be displayed in dl. If we pass the bell character (07h) to this service, it will play the bell through the PC speaker. Remember that int 21h is an MS-DOS service thus it's available under V86 mode , how can we call a V86 interrupt from a VxD? One way is to use Exec_Int service. This VMM service takes the interrupt number to be called in eax. It simulates the specified interrupt and resumes the execution of the VM. However, it must be called within a nested execution block. A nested execution block is bracketed by Begin_Nest_V86_Exec (or Begin_Nest_Exec) and End_Nest_Exec. So if we want to call int 21h, service 2, we need to alter the Client_ah and Client_Dl of the Client_Byte_Reg_Struc structure within the nested EX Ecution Block and the Store The Value 21h INTO EAX. When Everything is Ready, Call Exec_int.
The Example
.................
.386P include /masm/include/vmm.inc include /masm/include/vwin32.inc include /masm/include/v86mmgr.inc
VxDName TextEqu
Vxd_locked_code_seg; ------------------------------------------------ ----------------------------; Remember: The name of the vxd must be uppercase else it Won't work / unload; -------------------------------------------------- ----------------------- Declare_virtual_device% vxdname,% vxdmajorversion,% vxdminorversion,% controlname, undefined_device_id, undefined_init_order
Begin_control_dispatch% vxdname control_dispatch w32_deviceiocontrol, ONDEVICEIOCONTROL END_CONTROL_DISPATCH% VxDName
VXD_LOCKED_CODE_ENDS
VXD_PAGEABLE_CODE_SEG BeginProc OnDeviceIoControl assume esi: ptr DIOCParams .if [esi] .dwIoControlCode == 1 Push_Client_State VMMCall Begin_Nest_V86_Exec assume ebp: ptr Client_Byte_Reg_Struc mov [ebp] .Client_dl, 7 mov [ebp] .Client_ah, 2 mov eax, 21h VMMCall Exec_Int VMMCall End_Nest_Exec POP_CLIENT_STATE ENDI: .endif xor Eax, EAX RET EndProc ONDEVICEIOCONTROL VXD_PAGEABLE_CODE_ENDS
end
Analysis
Push_client_state
There is not much to analyze. When the VxD receives DeviceIoControl message, ebp already points to the current VM's client register structure. We call Push_Client_State macro to save the current state of the client registers on the stack. We later restore the client registers with Pop_Client_State .
VMMCALL BEGIN_NEST_V86_EXEC
Begin The Nested Execution Block by Calling Begin_nest_v86_exec.
Assume EBP: Ptruc Mov [EBP] .client_dl, 7 MOV [EBP] .client_ah, 2
Alter the images of dl and ah registers in The Client Register Structure. This Altered Values Will BE Used by The Interrupt.mov Eax, 21h VMMCALL EXEC_INT
EXEC_INT EXPECTS The Interrupt Number in Eax. Want to Issue Int 21h. Then We call EXEC_INT TO Simulate The Interrupt.
VMMCALL END_NEST_EXEC POP_CLIENT_STATE
.
[ICZelion's Win32 Assembly HomePage]