ICZelion vxd TUT9

zhaozj2021-02-11  244

Virtual 8086 Memory Manager

In the previous tutorial, you learn how to simulate V86 interrupt However, there is one problem that has not been addressed yet:.. Exchanging data between VxD and V86 code We will learn how to use the V86 Memory Manager to our advantage in this Download The Example.

Some THEORY

If your VxD works with some V86 routines, it will be necessary sooner or later to pass large chunks of data to and from the V86 program. Passing a large amount of data via registers is out of question. Your next attempt might be to allocate a block of memory in ring 0 and pass the pointer to the memory block via some register so the V86 code can access the data If you do so, it will probably crash your system because V86 addressing mode requires segment:. offset pair, not the linear address. There are many solutions to that problem. However, I choose an easy way here to demonstrate services provided by the V86 Memory Manager. If somehow you can find a free memory block in the V86 region that you can use as the communcation buffer, That Would Solve One of the Problems. However, The Pointer Translation Problem Remains. You can Solve Both Problems by Using The V86 Memory Mananger '

s services. The V86 Memory Manager is the static VxD that manages memory for V86 applications. It also provides EMS and XMS services to V86 apps and API translation services to other VxDs. API translation is actually the process of copying the data from ring-0 into a buffer in V86 region and then passing the V86 address of the data to the V86 code. No magic here. The V86 Memory Manager maintains a translation buffer which is a block of memory in the V86 region for copying data from VxD to V86 region . and vice versa Initially this translation buffer is 4 kilobytes you can increase the size of this buffer by calling V86MMGR_Set_Mapping_Info Now that you know about the translation buffer, how can we copy data to and from it This question involves two services:..? V86MMGR_Allocate_Buffer and V86MMGR_Free_Buffer. V86MMGR_Allocate_Buffer allocates a block of memory from the translation buffer and optionally copies the data from ring 0 into the allocated V86 block. V86MMGR_Free_Buffer does th e reverse: it optionally copies the data from the allocated V86 block into a ring-0 buffer and frees the memory block allocated by V86MMGR_Allocate_Buffer Note that the V86 Memory Manager maintains the allocated buffers as a stack That means the allocation / deallocation must observe.. the first in / first out rule. So if you make two calls to V86MMGR_Allocate_Buffer, the first V86MMGR_Free_Buffer will free the buffer allocated by the second V86MMGR_Allocate_Buffer call. We can now proceed to examine V86MMGR_Allocate_Buffer definition. It's a register-based service.

ebxHandle of the current VMebpPointer to the current VM's client register structureecxNumber of bytes to allocate from the translation buffercarry flagclear if you do not want to copy data from ring-0 buffer to the allocated block. Set if you want to copy data from ring- 0 Buffer to the allocated blockfs: esislector: Offset of the rings the data to be copied to the allocated buffer. Ignored if the carry flag is clear.

If the call is successful, the carry flag is clear and ecx contains the number of bytes actually allocated in the translation buffer. This value can be less than the value you requested so you should keep this value for use with V86MMGR_Free_Buffer call later. Edi contains the v86 address of the allocated block with the segment in the high word, the offset in the low word. The carry flag is set if an error occurs. V86MMGR_Free_Buffer accepts exactly the same parameters as V86MMGR_Allocate_Buffer. What actually occurs when you call V86MMGR_Allocate_Buffer is that you allocate a block of memory in V86 region of the current VM and obtain the V86 address of that memory block in edi. We can use these services to pass data to and from V86 interrupts. in addition to API translation, the V86 Memory Manager also Offers APPING Service to Other Vxds. API Mapping Is Actually The Process of Mapping Some Pages in Extended Memory Into V86 Region of Every VM. You CAN Use V86MMGR_MAP_PAGES to DO API mapping. With this service, the pages are mapped into the same linear address in every VM. This waste address space if you want to work with only one VM. Also API mapping is slower than API translation so you should use API translation as much AS Possible. API MAPPING IS Required for Some V86 Operation That Needs to Access The Same Linear Address And Must Be Present in All VMS.THE EXAMPLE

This Example Uses API Translation with int 21h, 440dh Minor Code 66h, Get Media ID, To Obtain The Volume Label of Your First Fixed Disk.

; ------------------------------------------------- --------------; vxdlabel.asm; ------------------------------- ------------------------------- .386p include /masm/include/vmm.inc include / masm / include / vwin32 .inc include /masm/incvxdname textequ ControlName TextEqu vxdmajorversion textequ <1> vxdminorversion texteq <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 VMMCall Get_Sys_VM_Handle mov Handle, ebx assume ebx: ptr cb_s mov ebp, [ebx CB_Client_Pointer] mov ecx, sizeof MID stc push esi mov esi, OFFSET32 MediaID push ds pop fs VxDCall V86MMGR_Allocate_Buffer pop esi jc EndI mov allocSize, ecx Push_Client_State VMMCall Begin_Nest_V86_Exec assume ebp: ptr Client_Byte_Reg_Struc mov [ebp] .Client_ch, 8 mov [ebp] .Client_cl, 66h assume ebp: ptr Client_word_reg_struc mov edx, edi mov [ebp ] .Client_bx, 3; Drive a MOV [EBP] .client_ax, 440dh MOV [EBP] .client_dx, DX SHR EDX, 16 MOV [EBP] .client_ds, DX MOV EAX, 21H VMMCALL EXEC_INT VMMMCALL END_NEST_EXEC POP_CLIENT_STATE; ---- ------------------------------------------------------------------------------------------------------------------ ------------- Mov ECX, Allocsize Stc Mov EBX, Handle Push ESI MOV ESI, Offset32 Mediaid Push DS Pop Fs Vxdcall V86MMGR_Free_Buffer Pop ESI MOV EDX , Esi assume edx: ptr DIOCParams mov edi, [edx] .lpvOutBuffer mov esi, OFFSET32 MediaID.midVolLabel mov ecx, 11 rep movsb mov byte ptr [edi], 0 mov ecx, [edx] .lpcbBytesReturned mov dword ptr [edx] , 11 EndI:? (?) (?) .endif xor eax, eax ret EndProc OnDeviceIoControl VXD_PAGEABLE_CODE_ENDSVXD_PAGEABLE_DATA_SEG MID struct midInfoLevel dw 0 midSerialNum dd midVolLabel db 11 dup midFileSysType db 8 dup MID ends MediaID MID <> Handle dd allocSize dd VXD_PAGEABLE_DATA_ENDS??

end

; ------------------------------------------------- -----------; label.asm; The win32 vxd loadinger.; -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------- .386 .Model Flat, StdCall Option Casemap: None

include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.libDlgProc PROTO: DWORD ,: DWORD,: DWORD,: DWORD .DATA FAILURE DB "Cannot Load Vxdlabel.vxd", 0 Appname DB "Get Disk Label", 0 VxdName DB "///vxdlabel.vxd" ,0 OutputTemplate DB" Volume Label of Drive C ", 0

.DATA? HINSTANCE HINSTANCE? HVXD DD? Disklabel DB 12 DUP (?) BYTESRETURNED DD?

.const IDD_vxdrun EQU 101 IDC_Load EQU 1000

.code Start: Invoke GetModuleHandle, Null Mov Hinstance, Eax Invoke Dialogboxparam, Hinstance, IDd_vxdrun, Null, Addr Dlgproc, Null Invoke EXITPROCESS, EAX

DlgProc proc hDlg: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM .IF uMsg == WM_INITDIALOG invoke CreateFile, addr VxDName, 0,0,0,0, FILE_FLAG_DELETE_ON_CLOSE, 0 .if eax == INVALID_HANDLE_VALUE invoke MessageBox, hDlg , addr Failure, addr AppName, MB_OK MB_ICONERROR mov hVxD, 0 invoke EndDialog, hDlg, NULL .else mov hVxD, eax .endif .elseif uMsg == WM_CLOSE .if hVxD! = 0 invoke CloseHandle, hVxD .endif invoke EndDialog, hDlg , 0 .ELSEIF uMsg == WM_COMMAND mov eax, wParam mov edx, wParam shr edx, 16 .if dx == BN_CLICKED .IF ax == IDC_LOAD invoke DeviceIoControl, hVxD, 1, NULL, 0, addr DiskLabel, 12, addr BytesReturned Null Invoke Messagebox, HDLG, AddR Disklabel, Addr OutputTemplate, MB_OK MB_ICONISEMATION .Endif .Endif.else Mov Eax, False Ret .ndif Mov ENX, TRUE RET DLGPROC ENDS End Start

Analysis

We will Examine Label.asm Which is The win32 Application Which Loads the Vxd First.

invoke DeviceIoControl, hVxD, 1, NULL, 0, addr DiskLabel, 12, / addr BytesReturned, NULLIt calls DeviceIoControl with device code equal to 1, no input buffer, a pointer to an output buffer and its size. DiskLabel is the buffer set aside for receiving the volume label returned by the VxD The number of bytes actually returned will be stored in BytesReturned variable This example demonstrates how to pass data to and receive data from a VxD:.. you pass input / output buffers to the VxD and the VxD Reads from / Write to The Submitted Buffers. We Will Examine The VXD Code next.

Vmmcall get_sys_vm_handle mov handle, EBX Assume EBX: PTR CB_S MOV EBP, [EBX CB_CLIENT_POINTER]

When the VxD receives W32_DeviceIoControl message, it calls Get_Sys_VM_Handle to obtain the system VM handle and store it into a variable named Handle. It next extracts the pointer to the client register structure from the VM control block into ebp.

Mov ECX, SIZEOF MID STC PUSH ESI MOV ESI, Offset32 Mediaid Push DS POP FS VXDCALL V86MMGR_ALLOCATE_BUFFER POP ESI JC ENDI MOV Allocsize, ECX

Next, it prepares the parameters to be passed to V86MMGR_Allocate_Buffer. We must initialize the allocated buffer, hence the stc instruction. We put the offset of MediaID into esi and the selector into fs then call V86MMGR_Allocate_Buffer. You'll recall that esi contains the pointer To Diocparams So We Must Preserve It by Push ESI and POP ESI.

Push_Client_State VMMCall Begin_Nest_V86_Exec assume ebp: ptr Client_Byte_Reg_Struc mov [ebp] .Client_ch, 8 mov [ebp] .Client_cl, 66h assume ebp: ptr Client_word_reg_struc mov edx, edi mov [ebp] .Client_bx, 3; drive C mov [ebp] .Client_ax 440DH

We prepare the values ​​in the client register structure for the int 21h, 440Dh minor code 66h. Specifying that we want to get the media ID of drive C. We also copy the value in edi into edx (edi contains the V86 address of the memory Block allocated by v86mmgr_allocate_buffer) .MOV [EBP] .client_dx, dx shr edx, 16 MOV [EBP] .client_ds, dx

Since Int 21h, 440DH, Minor Code 66h Expects Pointer To An Mid Structure In DS: DX, We Must Break The Segment: Offset Pair in Edx Into Two Parts and Put Theme Into The Corresponding Register images.

MOV EAX, 21H VMMCALL EXEC_INT VMMCALL END_NEST_EXEC POP_CLIENT_STATE

WHEN EVERYTHING IS Ready, We call exec_int to Simulate the interrupt.

Mov ECX, Allocsize Stc Mov EBX, Handle Push ESI MOV ESI, Offset32 Mediaid Push DS Pop Fs Vxdcall V86mmgr_Free_buffer Pop ESI

After Exec_Int returns, the allocated buffer is filled by the information we want. The next step is to retrieve that information. We achieve that goal by calling V86MMGR_Free_Buffer. This service frees the memory block allocated by V86MMGR_Allocate_Memory and copies the data in the allocated memory block To the specified ring-0 Memory Block. Like V86mmgr_allocate_memory, if you want the copy operation, you must set the carry flag prior to calling the service.

mov edx, esi assume edx: ptr DIOCParams mov edi, [edx] .lpvOutBuffer mov esi, OFFSET32 MediaID.midVolLabel mov ecx, 11 rep movsb mov byte ptr [edi], 0 mov ecx, [edx] .lpcbBytesReturned mov dword ptr [ EDX], 11

After We Have The Information In The Ring-0 Buffer, We Copy The Volume Label to The Buffer Provided by The Win32 Application. We can access the buffer of diocparams.

[ICZelion's Win32 Assembly HomePage]

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

New Post(0)