VxD編程入門教程

來源:互聯網
上載者:User

VxD編程入門教程
作者:TBsoft

--------------------------------------------------------------------------------

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.