+HCU's special Project: 'Our protections'
tough
A FIRST INTRODUCTION TO VxD

by +RCG, 14 January 1998
cracker

	A FIRST INTRODUCTION TO VxD



I will introduce you some basic aspects about

the VxD programming (don't you think I have much

more idea than you, this is my first W95 VxD :-)



First you must know that a VxD can do everything

we want, no more Ring3 restrictions, you can

stop completely the system, read or write any

memory address, hook all interrupts or exceptions,

take control of the IO ports, for that reason

I recomend you to reverse a little WinIce so you

could see how these great programmers do it, also

is a good idea study a little VxDMonitor,FileMonitor

and RegMonitor all from Bryce Cogswell and Mark

Russinovich, BTW I have been able to create my

VxD thanks to they sourcers, M$ documentation about

this makes laught.





A VxD has two parts, one is the Initialization Part

of Code that is discardable, so when the VxD has been

loaded and initializated, the memory area of this code

(and it data) is freed, and a locked (permanent) part

that is only released when the VxD is unloaded.



At the initialization you must perform the critical

actions like hooking int,s ,devices, API,s ,etc.



Well no more words and lets see it with an example,

lets try to intercept timing functions of W95 so 

we will use it as a TSR for reversing purposes.

I will use Hedit 2.0 because it is a 'small' 

program (although 340Kb is a little overbloated)

so everyone could download the program and follow

the example easily. Hedit get the system time and

then compares it with another stored value and 

if the system_time is lower than the stored value 

a good guy is asummed, so we can tell the program

we are in the year 1088 and then we will be good guys

(quite obvious).



If you read my WinIce essay, you will remember that

W95 uses the Old Int 21h service 2Ah in order to get

the system time, so we will path these service.



Our VxD will check all time requests by hooking the

Int 21h service 2Ah and then will check if the caller

is Hedit gives it a good guy date otherwise lets DOS

give the correct date. Easy is it?



BTW, I have also added a complete service list with

the codes, so you can monitor (or intercept) every

call to a service using next function:



	mov	eax,Service_ID

	mov	esi,Our_New_Procedure

	VmmCall	Hook_Device_Service

	jc	Not_Installed

	mov	[Real_Proc],esi



Our_New_Proc:

	Do 	something

	jmp	[Real_Proc]









		    THE SOURCE (vxdbody.asm)



.386p

	.xlist

	include	vmm.inc

	include vwin32.inc

.list



;============================================================================

;                         S O M E   E Q U 

;============================================================================



VXDBODYName              EQU      ;Must be 16 chars

VXDBODYRev               EQU     00H



VXDBODY_MAJOR_VERSION    EQU     1

VXDBODY_MINOR_VERSION    EQU     0





ErrorCode               EQU 0FFFFFFFFh



;============================================================================

; 			  P U B L I C   D A T A

;============================================================================



VXD_LOCKED_DATA_SEG



FLAGS   dd 0

SYS_VM  dd 0

LD      dd 0





VXD_LOCKED_DATA_ENDS





;===================================

;D E V I C E   D E C L A R A T I O N

;===================================



VXD_LOCKED_CODE_SEG



DECLARE_VIRTUAL_DEVICE VXDBODY,  \

        VXDBODY_MAJOR_VERSION,   \

        VXDBODY_MINOR_VERSION,   \

        VXDBODY_Control, ,       \

	UNDEFINED_INIT_ORDER





;=================

;M A I N   C O D E

;=================





public VXDBODY_Control

VXDBODY_Control PROC NEAR



        Control_Dispatch SYS_DYNAMIC_DEVICE_INIT,       VXDBODY_Device_Init

        Control_Dispatch SYS_DYNAMIC_DEVICE_EXIT,       VXDBODY_Device_Exit

        Control_Dispatch W32_DEVICEIOCONTROL,           VXDBODY_ioctl

	clc

	ret



VXDBODY_Control ENDP





Public VXDBODY_ioctl

BeginProc VXDBODY_ioctl



	mov	ecx,[esi].dwIoControlCode	; get ioctl code

        cmp     ecx,1

        je      Function1

        cmp     ecx,2

        je      Function2

        jmp     RetSuccess



Function1:

        ;Here everything you want

        ;No more Ring3 limitations

        jmp     RetSuccess



Function2:

        ;Here other function

        ;and so on.

        jmp     RetSuccess 



RetSuccess:

        xor     eax, eax     ;return zero = success

	clc

	ret

RetFail:

        mov     eax,ErrorCode

        stc

        ret





EndProc VXDBODY_ioctl





BeginProc Our_Int_Handler



        pushad

        mov     eax,[ebp.Client_EAX]

        cmp     ax,2A00h                ;Get_System_Time DOS function?

        jne     Let_DOS_Work

        

        xor     eax,eax

        mov     FLAGS,eax		;Must be zero



        VxDCall VWIN32_GetCurrentProcessHandle

        mov     eax,[eax+38h]

        or      al,7

        mov     LD,eax    		;Store the Local Descriptor



        VmmCall Get_Sys_VM_Handle

        mov     SYS_VM,ebx



        VmmCall _SelectorMapFlat 



        add     eax,0F2h        ;Now eax points to the caller name

        mov     ebx,[eax]

        cmp     ebx,'ideH'      ;Hedit inverted

        jne     Let_DOS_Work

        mov     bl,[eax+4]

        cmp     bl,'t'

        jne     Let_DOS_Work



        mov     [ebp.Client_AX],1      ;Day of week

        mov     [ebp.Client_CX],1088   ;Year

        mov     [ebp.Client_DX],0101h  ;Day and Month 



Is_Hedit:

        popad

        clc     ;consume the interrupt

        ret



Let_DOS_Work:

        popad

   	stc   ; don't consume the interrupt

   	ret



EndProc Our_Int_Handler







Public VXDBODY_Device_Exit

BeginProc VXDBODY_Device_Exit



        mov     eax, 21h

        mov     esi, OFFSET32 Our_Int_Handler

        VMMCall UnHook_V86_Int_Chain

	clc

	ret



EndProc VXDBODY_Device_Exit



VXD_LOCKED_CODE_ENDS





VXD_ICODE_SEG



BeginProc VXDBODY_Device_Init



        mov     eax, 21h

        mov     esi, OFFSET32 Our_Int_Handler

   	VMMCall Hook_V86_Int_Chain

	clc

	ret



EndProc VXDBODY_Device_Init



VXD_ICODE_ENDS





end







		THE DEFINITIONS (vxdbody.def)





VXD VXDBODY DYNAMIC

SEGMENTS

	_LPTEXT		CLASS 'LCODE'   PRELOAD NONDISCARDABLE

	_LTEXT		CLASS 'LCODE'   PRELOAD NONDISCARDABLE

	_LDATA		CLASS 'LCODE'   PRELOAD NONDISCARDABLE

	_TEXT		CLASS 'LCODE'   PRELOAD NONDISCARDABLE

	_DATA		CLASS 'LCODE'   PRELOAD NONDISCARDABLE

	CONST		CLASS 'LCODE'   PRELOAD NONDISCARDABLE

	_TLS		CLASS 'LCODE'   PRELOAD NONDISCARDABLE

	_BSS		CLASS 'LCODE'   PRELOAD NONDISCARDABLE

        _MSGTABLE	CLASS 'MCODE'	PRELOAD NONDISCARDABLE IOPL

        _MSGDATA	CLASS 'MCODE'	PRELOAD NONDISCARDABLE IOPL

        _IMSGTABLE	CLASS 'MCODE'	PRELOAD DISCARDABLE IOPL

        _IMSGDATA	CLASS 'MCODE'	PRELOAD DISCARDABLE IOPL

        _ITEXT		CLASS 'ICODE'   DISCARDABLE

	_IDATA		CLASS 'ICODE'   DISCARDABLE

	_PTEXT		CLASS 'PCODE'   NONDISCARDABLE

	_PDATA		CLASS 'PDATA'   NONDISCARDABLE SHARED

	_STEXT		CLASS 'SCODE'   RESIDENT

	_SDATA		CLASS 'SCODE'   RESIDENT

	_DBOSTART	CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING

	_DBOCODE	CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING

	_DBODATA	CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING

	_16ICODE	CLASS '16ICODE' PRELOAD DISCARDABLE

	_RCODE		CLASS 'RCODE'

EXPORTS

        VXDBODY_DDB





		THE MAKEFILE (makefile.   )



OBJECTS = vxdbody.obj



vxdbody.vxd:     $(OBJECTS) vxdbody.def

        LINK.EXE @attach a simple program that opens our vxd and closes it,

and (not implemented yet) sends orders to our vxd.



Soon more (but you must work on your own)





+rcg 1998

tough
Back to Our protections