ICZelion's Win32ASM VXD compilation tutorial (8)

zhaozj2021-02-11  209

Customer register structure

We will learn another important structure in this tutorial called the customer register structure. In this article, V86 refers to virtual 8086 mode.

theory

VxDs is very different from normal Win32 / Win16 / DOS app. In most cases, they are sleeping when other applications work normally. They work as a regulator, and their role is to monitor Ring-3 applications and correct them when it is wrong. Here is a typical situation in its work:

1

Interested in the above process is that VMM can only affect the interrupted application, that is, modify the stored register image. For example, the VMM believes that the interrupted program should return to another address, which modifies the value of the CS: IP in the stored register image. When this program is reprecated, it will start executing at the new CS: IP.

VMM stores the register value at the interrupt point in the client register structure.

Client_Reg_Struc STRUCClient_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_res12 dw? Client_reg_struc ends

You can see this structure is divided into two parts: client_xxx and client_alt_xxx. In this slight explanation, in a given VM, there may be two running threads: V86 and protection mode. When the V86 program is running, if an interrupt is generated, the client_xxx will include the register image of the V86 program, and the client_alt_xxx will contain register images of the protected mode program. Correspondingly, when the protected mode program is running, if an interrupt is generated, the client_xxx will contain the register image of the protection mode program, and the client_alt_xxx will contain the register image of the V86 program. Client_resx is reserved without use.

After viewing this structure, you may have a problem: how to change one byte in the register, such as Al? The above structure only describes the word and double word size register group. Don't worry, find a found on VMM.inc. There are two structures for this additional structure: client_word_reg_struc and client_byte_reg_struc. If you want to access registers with word or byte size, convert client_reg_struc to client_word_reg_ruc or client_byte_reg_struc based on your needs. Next question: How do we get a pointer to the customer register structure?

This is quite simple: Generally, when VMM calls our VXD, put the address of the client register structure in the EBP. The customer register structure here is current VM. You can get this pointer from the handle of the VM. Remember, the handle of the VM is the linear address of the VM control block.

CB_S STRUCCB_VM_STATUS DD? CB_HIGH_LINEAR DD? CB_CLIENT_POINTER DD? CB_VMID DD? CB_SIGNATURE DD? CB_S Endscb

The CB_Client_Pointer contains a pointer to the client register structure of the VM. For example: You can use the code below to get a pointer to the customer register structure in the current VM:

VMMCALL GET_CUR_VM_HANDLE; RETURN THE CURRENT VM HANDLE IN EBXASSUME EBX: PTR CB_S MOV EBP, [EBX CB_CLIENT_POINTER]; Pointer to Client Reg Struct

Now we understand the customer register structure, we can use it to start working. We will use the customer register structure to transfer the value of the register group to a DOS interrupt, that is, INT 21h, function 2H, display a character. This DOS service puts the characters you want to display in DL. If we deliver the bell character (07h) to this service, it will sound through the PC speaker.

Remember, INT 21h is a DOS service, so it is available in V86 mode, how do we call a V86 interrupt in VXD? One method is to use the EXEC_INT service. This VMM service puts the interrupt number to be called in EAX. It simulates the specified interrupt and then returns to the called VM. However, it must be called in a nested execution block. Nested execution blocks are included by begin_nest_v86_exec (or begin_nest_exec) and end_nest_exec. If we want to call the int 21h function 2H, we need to convert the client_ah and client_dl of the client_byte_reg_struc structure in the nested execution block, and then put the value of 21H in Eax. When everything is ready, call EXEC_INT.

example:

The example is a dynamic VXD that invokes the function 2 of INT 21H 2 to make the PC speaker.

.386P

INCLUDE /MASM/INCLUDE / VMM.INC

INCLUDE /MASM/INCLUDE/vwin32.inc

INCLUDE /MASM/INCLUDE /V86MMGR.INC

VxDName Textequ

ControlName Textequ

Vxdmajorversion TextEqu <1>

VxdminorVersion TextEqu <0>

Vxd_static_data_seg

VXD_STATIC_DATA_ENDS

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

explain

Push_client_state

This is nothing to explain. When a VXD receives a DeviceIocontrol message, EBP has point to the current VM's client register structure. We call the PUSH_CLIENT_STATE Macro to store the status of the client register structure in the stack. Then use the POP_CLIENT_STATE macro to recover the client register.

VMMCALL BEGIN_NEST_V86_EXEC

Start the nested execution block by calling Begin_NEST_V86_EXEC.

Assume EBP: PTR Client_byte_reg_strucmov [EBP] .client_dl, 7 MOV [EBP] .client_ah, 2

Change the image of the DL and AH registers in the customer register. This change will be used by the interrupt.

MOV EAX, 21H VMMCALL EXEC_INT

EXEC_INT requires an interrupt number in Eax. We want to use INT 21h. Waiting for us to call EXEC_INT to simulate interrupts.

VMMCALL END_NEST_EXECPOP_CLIENT_STATE

When EXEC_INT returns, we completed the nested execution block and recovered the value of the client register structure in the stack. You will hear your PC speaker sound.

转载请注明原文地址:https://www.9cbs.com/read-3781.html

New Post(0)