一、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_FLAG_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_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); 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函数请查阅相关手册或者帮助。
|