1、用VXD技术实现的文件系统保护程序示例用VXD技术实现的文件系统保护程序示例要对Windows9x操作系统下的文件进行保护,只能通过驱动级开发来实现。通常情况下是写一个Installable File System Hook(IFSH,可安装文件系统挂钩程序)加载在系统中,然后在其中监控系统的文件操作。当发现系统在作你希望监控的操作时,进行你需要的操作(此时系统并没有进行实际的操作,你赶在了系统操作之前)。进行此项开发需要相应平台的IFS kit (可安装文件系统开发包),Windows9x的在它们的DDK中已经包含,但Windows NT和Windows 2000的IFS kit需要向微软购
2、买(目前估价$6000,国内好象还没有,你自己找吧,看运气了)。现在大部分杀毒软件号称的虚拟机技术就是我们将要介绍的基于IFS(可安装文件系统,下同)的文件系统操作技术。不同的是它们是在文件操作之前检查一下特征码,看有没有感染病毒,而我们所要作的是检查一下该文件是否允许存取,对它们作相应的保护。下面我们以一个用于指定的文件的操作保护的程序为例介绍一下这种技术。我们把它设计成为对磁盘(逻辑盘)、具体文件作相应保护的工具。为了简化起见,我们只启用了防删除保护。同样的原理你也可以自己扩充功能。完整的源代码可以从以下网址下载:并且在不断发展更新中,欢迎时常访问本站并更新你的代码。本套程序包括后台VXD
3、驱动程序和前台程序两个部分。本程序开发环境如下:Windows 98 第二版VC+ 6.0专业版VTOOLSD 3.0(DRIVERSTUDIO 2.0中自带的)一、 后台VXD程序的生成和编写我们用VXD辅助开发工具VTOOLSD 3.0版本来生成程序框架。1. 设置一般选项打开vtoolsd的Quick Vxd后将设备参数页作如下设置:其中在设备名框中输入的”FILHOOK”将作为生成的设备名出现在系统中,你可以用Vtoolsd自带的 vxd viewer查看系统中加载的驱动程序,如果你已经成功加载此驱动程序,你将看到如下图所示的画面:证明已经加载入系统中。2. 程序入口方式设置一般情况下
4、,我们在windows9x下加载的VXD驱动程序都必需使用”Protected Mode”保护模式方式。关于详细的说明,请参阅本专栏前面的文章中的介绍。3. 必需响应的系统消息由于我们的驱动程序要求必需能动态加载,而且能够响应win32应用程序的控制,并与Win32前台程序交互作用,所以必需响应系统的如下三个消息 (由操作系统的虚拟机管理器VMM发给我们的驱动程序的系统通知消息) :SYS_DYNAMIC_DEVICE_EXIT :驱动程序动态卸载通知消息SYS_DYNAMIC_DEVICE_INIT :驱动程序动态加载通知消息W32_DEVICEIOCONTROL :WIN32设备输入输出控
5、制消息(由win32前台程序发给VXD驱动程序的消息)生成框架后,我们再加入自己的代码。第一部分:实现文件定义。/ - main module for VxD FILEHOOK#define DEVICE_MAIN#include filehook.hDeclare_Virtual_Device(FILEHOOK) /VXD设备名#undef DEVICE_MAIN/此处为我们加入的控制消息定义,注意,这里的消息不是windows消息,而是由DeviceIoControl函数发给VXD的消息。#define REMOVE_DRV 100 /删除在保护列表中的一个驱动器#define REMOV
6、E_FILE 101 /删除在文件列表中的一个文件#define REMOVE_DIR 102 /删除在目录列表中的一个目录名#define ADD_DIR 103 /添加要保护的目录名到列表中#define ADD_DRV 104 /添加要保护的驱动器到列表中#define ADD_FILE 105 /添加要保护的文件名到列表中#define STARTP 106 /启动保护#define STOPP 107 /停止保护#define PREAD 10 /读保护#define PDELETE 11 /删除保护 ,目前我们只实现此保护#define PWRITE 12 /写保护#define
7、PALL 13 /保护所有的操作#define PCREATE 14 /禁止创建文件 由于时间关系,我们只实现了文件删除保护和驱动器删除保护。其它的保护只是响应不同的系统操作类型而已。(目录操作保护和文件操作保护机理不同,另文探讨)FilehookVM:FilehookVM(VMHANDLE hVM) : VVirtualMachine(hVM) FilehookThread:FilehookThread(THREADHANDLE hThread) : VThread(hThread) BOOL FilehookDevice:OnSysDynamicDeviceInit() PrevHook
8、= IFSMgr_InstallFileSystemApiHook(MyIfsHook);/安装文件系统挂钩回调函数 /初始化数据成员 FILE=DIR=NULL; /将目录和文件列表指针初始化为NULL,实际上,文件名和目录列表都是一个单链表,你也可以用hash表等来实现。 ENDFILE=FILE; /初始化尾指针 ENDFILE-Next=NULL; /将尾指针的下一个元素指针初始化为NULL ENDDIR=DIR; ENDDIR-Next=NULL; for(int i=0;iNext; delete temp; while(DIR!=NULL)/目录列表 temp=:DIR; :DI
9、R=:DIR-Next; delete temp; :WriteLog(logfile,正常结束运行!);/记入日志 WORD pError; R0_CloseFile(logfile,&pError);/关闭日志文件 IFSMgr_RemoveFileSystemApiHook(MyIfsHook); /卸载文件挂钩回调用函数 return TRUE;DWORD FilehookDevice:OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams)/前台控制消息响应函数 switch(pDIOCParams-dioc_IOCtlCode)/检查操作类型,这
10、些消息是在前面定义的 case ADD_FILE:/添加文件 FT *file,*pfile; pfile=(FT *)pDIOCParams-dioc_InBuf;/生成一个FT类型的指针并指向传递过来的内存区域 WriteLog(logfile,添加文件); /记入日志,当然在正式发行时可以去掉,这里是为了调试方便 WriteLog(logfile,pfile-PathName);/记录添加的文件名,可以和前台的对比,看有没有误传,这里也是为了调试方便 file=new FT; /分配内存 if(file!=NULL) memcpy(file,pfile,sizeof(FT); /将传递过
11、来的内存块保存下来,以下代码是典型的链表操作 if(:FILE=NULL) /如果是列表中的第一个文件 :FILE=file; else /接下来的文件 :ENDFILE-Next=file; file-Next=NULL; ENDFILE=file; break; case ADD_DIR:/添加目录,与上面的代码类似 FT *dir,*pdir; /目录和文件实际上相似,所以用相同的结构定义 pdir=(FT *)pDIOCParams-dioc_InBuf; dir=new FT; if(dir!=NULL) memcpy(dir,pdir,sizeof(FT); if(:DIR=NUL
12、L) :DIR=dir; else :ENDDIR-Next=dir; dir-Next=NULL; :ENDDIR=dir; break; case ADD_DRV:/添加驱动器,将相应的元素的iIsIn设为1即可;如:如果加入的是A盘,就将下标为0的元素的iIsIn设为1,依次类推。 DT * driver; /DT和FT都是结构 driver=(DT *)pDIOCParams-dioc_InBuf; /取得传入的参数 if(driver-iIsIn=A&driver-iIsIniIsIn-A.iIsIn=1;/将相应的置1 DRIVERdriver-iIsIn-A.iProtype=d
13、river-iProtype; break; default: break; return 0;int _cdecl MyIfsHook(pIFSFunc pfn, int fn, int Drive, int ResType,int CodePage, pioreq pir)/挂钩回调函数 _QWORD result;/取文件名时的返回值域,详见vtoolsd的帮助 unsigned char * path; /取得的路径指针 int s; char * action;/调试用变量,配合dout函数你可以在Driver Monitor中看到它的值 switch(fn) case IFSFN_
14、OPEN: action=打开文件; /* path= (unsigned char*)malloc(pir-ir_ppath-pp_totalLength+3); if(path!=NULL) path0=Drive+A-1; path1=:; UniToBCSPath(path+2,pir-ir_ppath-pp_elements,pir-ir_ppath-pp_totalLength,BCS_OEM,&result); strcpy(FileName,(char *)path); free(path); else action=分配内存失败!; */ break; case IFSFN_
15、READ: action=读取文件; break; case IFSFN_WRITE: action=写出文件; break; case IFSFN_RENAME: action=更名文件; break; case IFSFN_DELETE: action=删除文件; path= (unsigned char*)malloc(pir-ir_ppath-pp_totalLength+3); if(path!=NULL) path0=Drive+A-1; path1=:; UniToBCSPath(path+2,pir-ir_ppath-pp_elements,pir-ir_ppath-pp_to
16、talLength,BCS_OEM,&result);/取得文件路径,并将用unicode表示的文件路径名转换为C语言风格的字符串,由Vtoolsd提供的例程。 strcpy(FileName,(char *)path); for(int i=0;iNext) /判断是不是在操作受保护的文件/注意:一般情况下的删除操作只是将文件改名放到回收站中,所以得不到保护。这里保护的只是直接按住shift键后删除的文件。如果要保护放到加收站中的文件,需要监视文件更名操作,并且首先要得知回收站文件夹的路径。 if(!strcmp(temp-PathName,(const char *)path)/是的话就保
17、护 WriteLog(logfile,由于保护以下文件不能被删除!); WriteLog(logfile,temp-PathName); return 0; /直接返回就行了,这样其它的ifs hook函数就得不到动作的机会,包括操作系统的API函数。 free(path); else action=分配内存失败!; break; case IFSFN_DIR: action=目录操作; break; /如果在Driver moniter中监视的话可以 return (*PrevHook)(pfn, fn, Drive, ResType, CodePage, pir);/传给下一个hook 函
18、数头文件定义:/ FILEHOOK.h - include file for VxD FILEHOOK#include #define DEVICE_CLASS FilehookDevice#define FILEHOOK_DeviceID UNDEFINED_DEVICE_ID#define FILEHOOK_Init_Order UNDEFINED_INIT_ORDER#define FILEHOOK_Major 1#define FILEHOOK_Minor 0class FilehookDevice : public VDevicepublic: virtual BOOL OnSysD
19、ynamicDeviceInit(); virtual BOOL OnSysDynamicDeviceExit(); virtual DWORD OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams); / int FilehookDevice:MyIfsHook(pIFSFunc pfn, int fn, int Drive, int ResType,int CodePage, pioreq pir); ;class FilehookVM : public VVirtualMachinepublic: FilehookVM(VMHANDLE hVM);c
20、lass FilehookThread : public VThreadpublic: FilehookThread(THREADHANDLE hThread);/-以上代码为vtoolsd自动生成代码int _cdecl MyIfsHook(pIFSFunc pfn, int fn, int Drive, int ResType,int CodePage, pioreq pir);/-ppIFSFileHookFunc PrevHook;/保存以前的钩子函数的变量 char FileName512;/-char* GetResTypeString(int restype)/读取操作的文件系统
21、类型 switch (restype) case IFSFH_RES_UNC: return IFSFH_RES_UNC; case IFSFH_RES_NETWORK: return IFSFH_RES_NETWORK; case IFSFH_RES_LOCAL: return IFSFH_RES_LOCAL; case IFSFH_RES_CFSD: return IFSFH_RES_CFSD; case IFSFH_RES_NETWORK + IFSFH_RES_UNC: return IFSFH_RES_NETWORK (UNC); case IFSFH_RES_LOCAL + IFS
22、FH_RES_UNC: return IFSFH_RES_LOCAL (UNC); case IFSFH_RES_CFSD + IFSFH_RES_UNC: return IFSFH_RES_CFSD (UNC); default: return Unknown; /-void WriteLog(HANDLE logfile,char * log) /日志记载函数 WORD pError; static int logoffset=0;/记录日志文件的偏移量,R0级的文件函数实际上是文件中断调用的简单封装。 char temp512; strcpy(temp,log); tempstrlen(
23、log)=r; tempstrlen(log)+1=n; tempstrlen(log)+2=0; R0_WriteFile(true,logfile,temp,strlen(temp),logoffset,&pError);/调用ring0级写文件函数 logoffset+=strlen(temp);/-typedef struct File_Type /FT文件类型定义short int Driver;char PathName512;struct File_Type * Next;short int iProType;/保护类型 FT;/文件项FT * DIR,* ENDDIR;/保护目
24、录列表头指针FT * FILE,* ENDFILE;/保护文件列表头指针typedef struct Driver_Type /驱动器类型定义short int iIsIn;short int iProtype;/保护类型 DT;DT DRIVER26;/要保护的驱动器HANDLE logfile;重要提示:在作文件读、写操作时请不要再作取文件名的操作,此时由于这些操作的连续性,将导致使机重资源急剧消耗,大部分情况下将导致蓝屏死机。/-以下为前台程序在程序中添加三个对话框,分别添加目录,添加文件名,添加驱动器。目录添加对话框的头文件(类定义部分)/-/ CAddDir dialogclass
25、CAddDir : public CDialog/ Constructionpublic: CAddDir(CWnd* pParent = NULL); / standard constructor/ Dialog Data /AFX_DATA(CAddDir) enum IDD = IDD_DIALOG2 ; CString m_dir;/添加一个数据成员,和一个编辑框关联 /AFX_DATA/ Overrides / ClassWizard generated virtual function overrides /AFX_VIRTUAL(CAddDir) public: protected: virtual void DoDataExchange(
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1