Анализ
Мы проанализируем label.asm, который является win32-приложением, загружающим VxD.
invoke DeviceIoControl,hVxD,1,NULL,0,addr DiskLabel,12,\ addr BytesReturned,NULL
Он вызывает DeviceIoControl с кодом устройства равным 1, без входного буфера, с указателем на буфер вывода и его размер. DiskLabe - это буфер для получения метки тома, который возвратит VxD. Количество байтов, которые будут фактически возвращены, будут сохранены в переменной BytesReturned. Этот пример демонстрирует, как передавать данные VxD и как получить их от него: вы передает входной/выходной буфер VxD, и тот читает/записывает в предложенный буфер.
Сейчас мы проанализируем VxD-код.
VMMCall Get_Sys_VM_Handle mov Handle,ebx assume ebx:ptr cb_s mov ebp,[ebx+CB_Client_Pointer]
Когда VxD получает сообщение W32_DeviceIoControl, он вызывает Get_Sys_VM_Handle, чтобы получить хэндл системной VM и сохраняет ее в переменную под названием Handle. Затем он извлекает указатель на CRS из контрольного блока VM.
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
Теперь он подготавливает параметры, которые будут переданы V86MMGR_Allocate_Buffer. Мы должны инициализировать зарезервированный буфер, начинаем с инструкции stc. Мы помещаем смещение MediaID в esi и селектоp в fs, а затем вызываем V86MMGR_Allocate_Buffer. Помните, что esi содержит указатель на DIOCParam, чтобы мы могли сохрнить их с помощью рush esi и 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
Мы подготавливаем значения в CRS для int 21h, 440Dh minor code 66h, указав, что мы хотим получить media ID диска C. Мы также копируем значение edi в edx (edi содержит V86-адрес блока памяти, зарезервированного с помощью V86MMGR_Allocate_Buffer).
mov [ebp].Client_dx,dx shr edx,16 mov [ebp].Client_ds,dx