VXD编程入门教程

电脑使用小技巧

4人已加入

描述

VXD编程入门教程

一、Windows 95 DDK的安装 
 
安装Windows 95 DDK一般需要先安装Win32 SDK,原因是Windows 95 DDK 
需要Win32 SDK的16位资源编译器,但是Win32 SDK很大(一整张光盘 
的容量),而且国内难以买到,ftp站上也较少见,即使有,下载也很困难。 
笔者经过一段时间的摸索,找到了安装Windows 95 DDK的几种简单方法, 
现将方法介绍如下: 
方法之一:使用第三方资源编译器 
1、修改注册表,仿真Win32 SDK已经安装的情况。 
建立一个名为WIN32SDK.REG的注册表文件,内容为: 
 
REGEDIT4 
 
[HKEY_USERS\.Default\Software\Microsoft\Win32SDK] 
 
[HKEY_USERS\.Default\Software\Microsoft\Win32SDK\Directories] 
"Install Dir"="C:\\MSTOOLS" 
 
在资源管理器中双击此文件,将此文件中的内容添加到注册表。就可以安 
装Windows 95 DDK了。 
2、运行Windows 95 DDK中的SETUP.EXE文件,安装Windows 95 DDK到 
C:\DDK。 
3、安装MASM 6.11到C:\MASM611,安装完成后将未安装的Windows 95 DDK 
中的MASM611C目录下的文件覆盖到C:\MASM611\BIN。 
4、安装Visual C++ 5.0(4.0也可以,但不宜使用6.0)到C:\Program 
Files\DevStudio\VC。 
5、建立C:\MSTOOLS\BINW16目录,拷贝资源编译器。 
Windows 95 DDK需要一个能将Win32资源源文件编译成16位资源的资源 
编译器。如果有Win32 SDK,可以将BINW16目录下的文件直接拷贝到 
C:\MSTOOLS\BINW16,如果没有Win32 SDK,则可以使用第三方的资源编译 
器,这里以使用Borland的资源编译器为例: 
准备Turbo MASM 5.0一套,用UNPAK工具解压缩CMDLINE.PAK文件,找 
到下面三个文件: 
 
BRC.EXE 
BRCC32.EXE 
RW32CORE.DLL 
 
将这三个文件拷贝到C:\MSTOOLS\BINW16,并将BRC.EXE改名为RC.EXE即 
可。 
6、修改CONFIG.SYS增大环境变量空间。 
在CONFIG.SYS文件最后加入一行: 
 
SHELL=C:\WINDOWS\COMMAND.COM /E:8192 /P 
 
7、进入Windows 95 MS-DOS方式,初始化编译环境(最好建立一个批处 
理文件): 
 
C:\MASM611\BINR\NEW-VARS.BAT 
C:\DDK\DDKINIT.BAT 32 BASE 
(编译的设备驱动程序不同,参数也不同) 
C:\Program Files\DevStudio\VC\bin\VCVARS32.BAT 
 
就可以使用Windows 95 DDK了,连接时出现的警告可以不理会。 
方法之二:使用Windows 98 DDK 
完整版的Windows 98 DDK(约30M)包括Windows 95 DDK、全套SDK编译 
器和MASM 6.11C汇编器,安装方法非常简单:安装Windows 98 DDK和Visual 
C++ 5.0,然后直接运行“Check Build Environment”(编译带调试信息 
的设备驱动程序)或者“Free Build Environment”(编译正式发布版本 
的设备驱动程序)程序项即可。 
 
二、一个拦截Windows 95/98文件操作的VxD 
 
VxD——虚拟设备驱动程序,顾名思义,VxD是用来控制硬件设备的,那么 
这里为什么要讲一个拦截Windows 95/98文件操作的VxD呢?其实,VxD 
不仅仅可以用来控制硬件设备,因为VxD工作在80386保护模式Ring 0 
特权级(最高特权级)上,而一般的应用程序工作在Ring 3特权级(最 
低特权级)上,所以VxD可以完成许多API不能完成的功能,例如端口读 
写、物理内存读写、中断调用、API拦截等。正因为如此,VxD在Windows 
系统编程中有广泛用途,其实大家一般都是碰到Windows API不能解决或 
者难以解决的问题才考虑编写VxD解决问题。 
这里介绍的拦截Windows 95/98文件操作的VxD可以用来拦截Windows 95 
/98(Windows NT不支持VxD)的所有文件操作,那么这个VxD有什么用 
途呢?最大的用途可能是——病毒防火墙,用来对文件操作进行过滤,可 
以进行动态病毒检测和动态杀毒。这个VxD使用的原理和目前流行的CIH 
病毒传染的原理是基本相同的。 
(其实大家如果要问我为什么要写这么一个VxD,那是因为——我是Virus 
版的版主啦) 
该VxD的文件名是FILEHOOK.VXD,源程序(FILEHOOK.ASM)如下: 
 
;FILEHOOK.VXD--拦截Windows 95/98文件操作的VxD 
 
.386p 
 
.XLIST 
 
INCLUDE VMM.Inc 
INCLUDE VWin32.Inc 
INCLUDE Shell.Inc 
 
MASM=1 
 
INCLUDE IFS.Inc 
INCLUDE IFSMgr.Inc 
 
.LIST 
 
;VxD声明 
 
Declare_Virtual_Device 
FILEHOOK,1,0,VxD_Control,Undefined_Device_ID,,, 
 
;保护模式数据段 
 
VxD_DATA_SEG 
 Prev_File_System_Api_Hook dd 0 
 In_File_System_Api_Hook db 0 
 Message1 db 'Open file !',0 
 Caption1 db 'FILEHOOK',0 
VxD_DATA_ENDS 
 
;保护模式代码段 
 
VxD_CODE_SEG 
 
;系统控制过程 
 
BeginProc VxD_Control 
 Control_Dispatch SYS_DYNAMIC_DEVICE_INIT,VxD_Device_Init 
 Control_Dispatch SYS_DYNAMIC_DEVICE_EXIT,VxD_Device_Exit 
 Control_Dispatch W32_DEVICEIOCONTROL,VxD_IOCTL 
 clc 
 ret 
EndProc VxD_Control 
 
;IOCTL 控制(设备I/O控制)过程 
 
BeginProc VxD_IOCTL 
 ;获取DeviceIoControl控制代码 
 mov ecx,[esi.dwIoControlCode] 
 cmp ecx,1 
 jz Install_File_System_Api_Hook 
 cmp ecx,2 
 jz Uninstall_File_System_Api_Hook 
 jmp VxD_IOCTL_Exit 
 
;安装文件系统API 钩子 
 
Install_File_System_Api_Hook: 
 mov eax,OFFSET32 File_System_Api_Hook 
 VxDCall IFSMgr_InstallFileSystemApiHook  
 or eax,eax 
 jz Error_Handler 
 ;保存上一个文件系统API 钩子地址 
 mov Prev_File_System_Api_Hook,eax 
 jmp VxD_IOCTL_Exit 
 
;移去文件系统API 钩子 
 
Uninstall_File_System_Api_Hook: 
 mov eax,OFFSET32 File_System_Api_Hook 
 VxDCall IFSMgr_RemoveFileSystemApiHook  
 cmp eax,0FFFFFFFFH 
 jz Error_Handler 
 jmp VxD_IOCTL_Exit 
 
;IOCTL 控制过程结束 
 
VxD_IOCTL_Exit: 
 xor eax,eax 
 clc 
 ret 
 
;错误处理 
 
Error_Handler: 
 mov eax,0FFFFFFFFH 
 stc 
 ret 
EndProc VxD_IOCTL 
 
;VxD_Device_Exit过程 
 
BeginProc VxD_Device_Exit 
 clc 
 ret 
EndProc VxD_Device_Exit 
 
;文件系统API 钩子过程(C语言调用方式) 
 
BeginProc File_System_Api_Hook,CCALL 
 ArgVar FSDFnAddr,DWORD 
 ArgVar FunctionNum,DWORD 
 ArgVar Drive,DWORD 
 ArgVar ResourceFlags,DWORD 
 ArgVar CodePage,DWORD 
 ArgVar pir,DWORD 
 EnterProc 
 pushad 
 ;防止重入 
 cmp byte ptr In_File_System_Api_Hook,00h 
 jnz Prev_Hook 
 ;比较是打开文件操作吗? 
 cmp dword ptr FunctionNum,IFSFN_OPEN 
 jnz Prev_Hook 
 ;设置重入标志 
 inc byte ptr In_File_System_Api_Hook 
 ;取当前VM句柄 
 VMMCall Get_Cur_VM_Handle 
 ;显示消息框 
 mov eax,MB_ICONASTERISK+MB_OK 
 mov ecx,OFFSET32 Message1 
 mov edi,OFFSET32 Caption1 
 mov esi,0 
 mov edx,0 
 VxDCall Shell_Message 
 ;取消重入标志 
 dec byte ptr In_File_System_Api_Hook 
 
;转到上一个文件系统API 钩子地址 
 
Prev_Hook: 
 popad 
 LeaveProc 
 mov eax,Prev_File_System_Api_Hook 
 jmp [eax] 
 Return 
EndProc File_System_Api_Hook 
 
VxD_CODE_ENDS 
 
;保护模式初始化代码段 
 
VxD_ICODE_SEG 
 
;VxD_Device_Init过程 
 
BeginProc VxD_Device_Init 
 clc 
 ret 
EndProc VxD_Device_Init 
 
VxD_ICODE_ENDS 
 
end 
 
该VxD在设备控制过程(VxD_Control过程)中处理了3个系统控制消息, 
分别是SYS_DYNAMIC_DEVICE_INIT(动态VxD初始化)、 
SYS_DYNAMIC_DEVICE_EXIT(动态VxD退出)和W32_DEVICEIOCONTROL(设 
备I/O控制),对应的消息处理过程分别是VxD_Device_Init、 
VxD_Device_Exit和VxD_IOCTL。其中VxD_Device_Init过程和 
VxD_Device_Exit过程只清除进位标志返回(表示成功),VxD_IOCTL过程 
是Windows 95/98应用程序与VxD通信的接口,完成文件系统API钩子 
的安装和移去工作,[esi.dwIOControlCode]中是设备I/O控制代码,该 
控制代码为1时安装文件系统API钩子,为2时移去文件系统API钩子。 
File_System_Api_Hook是文件系统API钩子过程,这里作为一个简单的实 
例,钩子过程判断是否是打开文件操作,如果是则显示一个简单的消息框, 
然后跳转到上一个文件钩子(相当于旧的文件系统API入口)。如果需要 
扩充功能,可以在该过程中增加代码。 
汇编连接VxD需要一个模块定义文件和一个NMAKE文件(手工汇编连接当 
然也可以)。这两个文件都可以直接用DDK中的GENERIC实例中的模块定 
义文件和NMAKE文件修改而成,模块定义文件(FILEHOOK.DEF)如下: 
 
VXD FILEHOOK DYNAMIC 
 
DESCRIPTION 'File System API Hook Program' 
 
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 
    _LMSGTABLE  CLASS 'MCODE'   PRELOAD NONDISCARDABLE IOPL 
    _LMSGDATA   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 
    _PMSGTABLE  CLASS 'MCODE'   NONDISCARDABLE IOPL 
    _PMSGDATA   CLASS 'MCODE'   NONDISCARDABLE IOPL 
    _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 
        FILEHOOK_DDB @1 
 
NMAKE文件(MAKEFILE)如下: 
 
!ifdef MASTER_MAKE 
BUILD_BITS=32 
BUILD_TYPE=base 
!INCLUDE $(DDKROOT)\master.mk 
!endif 
 
NAME = filehook 
 
# supply the location of a 16-bit linker 
 
LINK = 
 
#       Definitions for the debug level 
 
!ifdef DEBUG 
DDEBUG  =-DDEBLEVEL=1 -DDEBUG 
!else 
DDEBUG  =-DDEBLEVEL=0 
!endif 
 
#       Definitions for MASM 6 Assembler 
 
ASM    = ml 
AFLAGS = -coff -DBLD_COFF -DIS_32 -W2 -c -Cx -Zm -DMASM6 $(DDEBUG) 
ASMENV = ML 
LFLAGS = /VXD /NOD 
 
#       MASM 6 only inference rules 
 
.asm.obj: 
 set $(ASMENV)=$(AFLAGS) 
 $(ASM) -Fo$*.obj $< 
 
all : $(NAME).VXD 
 
OBJS = filehook.obj 
 
filehook.obj: filehook.asm 
 
$(NAME).vxd: $(NAME).def $(OBJS) 
        link @<<$(NAME).lnk 
$(LFLAGS) 
/OUT:$(NAME).vxd 
/MAP:$(NAME).map 
/DEF:$(NAME).def 
$(OBJS) 
<< 
        mapsym -s -o $(NAME).sym $(NAME).map 
 
clean: 
 -@del *.obj 
 -@del *.vxd 
 -@del *.exp 
 -@del *.lib 
 -@del *.map 
 -@del *.sym 
 
有了这两个文件,运行NMAKE即可汇编连接VxD。 
 
三、Windows 95/98应用程序与VxD的通信 
 
Windows 95/98应用程序与VxD的通信一般使用DeviceIoControl函数, 
这里给出一个实例源程序(FHTEST.C)如下: 
 
//拦截Windows 95/98文件操作测试程序 
 
#include  
#include "tchar.h" 
 
#define INSTALL_FILE_SYSTEM_API_HOOK 1 
#define UNINSTALL_FILE_SYSTEM_API_HOOK 2 
 
static TCHAR szAppName[]=_T("FHTEST"); 
static TCHAR szAppTitle[]=_T("拦截Windows 95/98文件操作测试程 
序"); 
static HANDLE hDevice; 
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT Message,WPARAM 
wParam,LPARAM lParam); 
 
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE 
hPrevInstance,LPSTR lpCmdLine,int nCmdShow) 

 HWND hWnd; 
 WNDCLASSEX wcex; 
 MSG Msg; 
 //本程序不能在Windows NT中运行 
 if(GetVersion()<0x80000000) 
 { 
  MessageBox(NULL,_T("本程序不能在Windows NT中运行! 
"),szAppTitle,MB_ICONINFORMATION|MB_OK); 
  return FALSE; 
 } 
 if(!hPrevInstance) 
 { 
  wcex.cbSize=sizeof(WNDCLASSEX); 
  wcex.style=CS_HREDRAW|CS_VREDRAW; 
  wcex.lpfnWndProc=WndProc; 
  wcex.cbClsExtra=0; 
  wcex.cbWndExtra=0; 
  wcex.hInstance=hInstance; 
  wcex.hIcon=LoadIcon(hInstance,IDI_APPLICATION); 
  wcex.hCursor=LoadCursor(NULL,IDC_ARROW); 
  wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1); 
  wcex.lpszMenuName=NULL; 
  wcex.lpszClassName=szAppName; 
  wcex.hIconSm=LoadIcon(hInstance,IDI_APPLICATION); 
  if(!RegisterClassEx(&wcex)) return FALSE; 
 } 
 hWnd=CreateWindow(szAppName,szAppTitle,WS_OVERLAPPEDWINDOW, 
 
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, 
       0,0,hInstance,NULL); 
 if(!hWnd) return FALSE; 
 ShowWindow(hWnd,nCmdShow); 
 UpdateWindow(hWnd); 
 while(GetMessage(&Msg,0,0,0)) 
 { 
  TranslateMessage(&Msg); 
  DispatchMessage(&Msg); 
 } 
 return Msg.wParam; 

 
LRESULT CALLBACK WndProc(HWND hWnd,UINT Message,WPARAM 
wParam,LPARAM lParam) 

 HDC hDC; 
 PAINTSTRUCT ps; 
 DWORD cb; 
 BOOL bResult; 
 switch(Message) 
 { 
 case WM_CREATE: 
 
 hDevice=CreateFile("\\\\.\\FILEHOOK.VXD",0,0,NULL,0,FILE_FLA 
G_DELETE_ON_CLOSE,NULL); 
  if(hDevice!=INVALID_HANDLE_VALUE) 
  { 
 
 bResult=DeviceIoControl(hDevice,INSTALL_FILE_SYSTEM_API_HOOK, 
NULL,0,NULL,0,&cb,0); 
   if(bResult) MessageBox(hWnd,_T("文件系统API 钩子安装 
成功!"),szAppTitle,MB_ICONINFORMATION|MB_OK); 
   else MessageBox(hWnd,_T("不能安装文件系统API 钩子! 
"),szAppTitle,MB_ICONINFORMATION|MB_OK); 
  } 
  else 
  { 
   MessageBox(hWnd,_T("不能打开FILEHOOK.VXD! 
"),szAppTitle,MB_ICONINFORMATION|MB_OK); 
  } 
  break; 
 case WM_PAINT: 
  hDC=BeginPaint(hWnd,&ps); 
  EndPaint(hWnd,&ps); 
  break; 
 case WM_DESTROY: 
  if(hDevice!=INVALID_HANDLE_VALUE) 
  { 
 
 bResult=DeviceIoControl(hDevice,UNINSTALL_FILE_SYSTEM_API_HO 
OK,NULL,0,NULL,0,&cb,0); 
   if(bResult) MessageBox(hWnd,_T("文件系统API 钩子移去 
成功!"),szAppTitle,MB_ICONINFORMATION|MB_OK); 
   else MessageBox(hWnd,_T("不能移去文件系统API 钩子! 
"),szAppTitle,MB_ICONINFORMATION|MB_OK); 
   CloseHandle(hDevice); 
  } 
  else 
  { 
   MessageBox(hWnd,_T("不能打开FILEHOOK.VXD! 
"),szAppTitle,MB_ICONINFORMATION|MB_OK); 
  } 
  PostQuitMessage(0); 
  break; 
 default: 
  return DefWindowProc(hWnd,Message,wParam,lParam); 
 } 
 return 0; 

 
本程序使用CreateFile函数动态装载VxD,然后用DeviceIoControl函数 
向VxD发送设备I/O控制代码,安装和移去文件系统API钩子,最后用 
CloseHandle函数动态移去VxD。 
运行该程序时,如果文件系统API钩子安装成功,会显示出“文件系统API 
钩子安装成功!”的消息框,然后只要进行打开文件操作,就会显示出“Open 
File !”的消息框。退出该程序时,如果文件API钩子移去成功,会显示 
出“文件API钩子移去成功!”的消息框,以后进行打开文件操作时不再 
显示消息框。 
 
四、小结 
 
上述实例演示了一个完整的拦截Windows 95/98文件系统API的VxD和 
Windows 95/98应用程序与该VxD通信的方法。该VxD可以作为一个基本 
框架,稍作修改即可用于病毒防火墙等软件。其实VxD的功能远不止这些, 
充分利用VxD的功能可以编写出许多用API不能编写出的高级应用程序。 
本教程只是一个简单的VxD编程例子,因为笔者水平所限,加之时间较少, 
写得较为简单,还请大家见谅,同时也欢迎大家讨论。本教程中使用的VMM 
功能、VxD功能和API函数请查阅相关手册或者帮助。 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 相关推荐
  • VXD

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分