程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> VxD編程入門教程

VxD編程入門教程

編輯:關於VC++

一、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_USEDE FAULT,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函數請查閱相關手冊 或者幫助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved