Minifilter微过滤框架:框架介绍以及驱动层和应用层的通讯
minifilter是sfilter后微软推出的过滤驱动框架。相比于sfilter,他更容易使用,需要程序员做的编码更简洁。
系统为minifilter专门制作了一个过滤管理器,这个管理器本身其实是一个传统过滤驱动,它向minifilter的使用者提供许多接口,让原本复杂的文件过滤驱动变得方便简单。之所以简单是因为传统的过滤驱动把大量的工作放在绑定设备上,而现在这些工作都交给minifilter中的过滤管理器来完成。
缺点:纯粹的使用minifilter提供的接口看不见设备对象和IRP的,所以编程自由度不大。
对minifilter的编写的第一步是向过滤管理器注册一个微过滤器,这个未过滤器是一个组件,包含了一些在文件操作的时候可能需要的回调函数。
驱动入口中最简单的版本是只包含两个函数:注册函数和开始函数。
- NTSTARTUS DriverEntry(__in PDRIVER_OBJECT DriverObject,__in PUNICODE_STRING RegistryPath)
- {
- NTSTATUS status;
- UNREFERENCED_PARAMETER(registryPath);
- status = FltRegisterFilter(DriverObject,&FilterRegisteraion,&gFilterHandle);
- ASSERT(NT_SUCCESS(status));
- if(NT_SUCCESS(status)){
- status = FltStartFiltering(gFilterHandle);
- if(!NT_SUCCESSS(status)){
- FltUnregisterFilter(gFilterHandle);
- }
- }
- return status;
- }
1.注册函数FltRegisterFilter
它的第二个参数是个结构体要自己填写完整,这个结构体中的内容包含微过滤器的方方面面。
上面说的结构名字叫FLT_REGISTRATION,这个结构中有些部分是基本信息,有些部分是回调函数。所以这个结构有点面向对象语言中类的感觉。这个结构中最NB(中文意思是“重要”)的字段就是FLT_OPERATION_REGISTRATION(大家都知道,当操作系统要对文件系统进行操作的时候,其实就是通过发送各种各样的事件请求(IRP),而文件系统就负责处理好这些请求),而字段FLT_OPERATION_REGISTRATION就是一个事件请求数组(这个数组包含该过滤驱动可以处理的所有事件),每个数组元素本身又是一个五元组,包括1.当前要处理的事件,2.标识位(这个标志位一般写0,表示全过滤,还有两种值分别是不过滤缓存读写和不过滤页读写操作),3.事件被处理前函数(Pre-operation),4.事件被处理完成后的函数(Post-operation)。
【关于过滤函数:现在的过滤函数是有标准格式的(??是吗?),因为现在访问不到IRP,所以minifilter设置了一个结构用来存放请求包中的所有信息,在个结构往往是过滤函数的第一个参数。。。。传统的过滤驱动,和对应的请求相绑定的直接处理函数的格式好像也是固定的。。。想自定义处理函数格式也行,就要封装在第一级处理函数里面。】
第一个参数是知道我们自己的这个驱动的驱动对象。这个对象是我们的驱动在初始化的时候,系统帮我们生成的。
第三个参数是一个输出值,当我们的驱动成功的注册的时候,这个参数就是指向我们的微过滤驱动的句柄。
2.开始函数FltStartFiltering
就一个参数——过滤驱动的句柄,就是上面注册函数的输出值。
自己编写设备过滤驱动,说白了就是自己编写想要过滤的事件的预处理(pre-operation)或者完成(post-operation)函数。就像上面介绍的,对应每一个事件的预处理和完成函数都在结构FLT_REGISTRATION中的FLT_OPERATION_REGISTRATION结构里声明好的。
所以我们只要编写出每一个在FLT_OPERATION_REGISTRATION中给出的预处理和完成函数的函数体就行了。
比如在FLT_OPERATION_REGISTRATION中我们写了一个字段{IRP_IO_CREATE,0,NPPreCreate,NPPostCreate}。这里我们就针对事件IRP_IO_CREATE设置了这个事件的预处理函数NPPreCreate和完成函数NPPostCreate。
作为简单的例子,下面实现NPPreCreate:
- FLT_PREOP_CALLBACK_STATUS NPPreCreate(
- __inout PFLT_CALLBACK_DATA Data,
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __deref_out_opt PVOID *CompletionContext
- )
- {
- ...
- Data->IoStatus.Status = STATUS_ACCESS_DENIED;
- Data->IoStatus.Information = 0;
- return FLT_PREOP_COMPLETE;
- }
这里就是一个过滤函数的框架,先看下这个函数的参数表。第一个参数是最重要的,PFLT_CALLBACK_DATA Data。对于接触过传统sfilter框架过滤驱动的朋友一定知道,在我们的过滤驱动过滤到上层发来的请求时,拦截到的就是一个IRP请求包,这个包中有这一次请求的几乎所有信息。现在在MINIFILTER框架中,眼前的这个参数就是当年的IRP,只是变了名字,我们操作时需要的(IRP)信息都在这个结构里。
一次文件请求操作的基本原理:
对于没接触过文件过滤驱动的朋友,这里简单说下文件过滤驱动的工作原理。当上层发生了某些文件系统请求的时候,这个请求会打包成IRP,发给底层的文件系统处理,当任务处理完的时候,文件系统会把任务完成情况打成IRP包回发给上层,通知上层请求被处理了。当我们把自己编写的过滤驱动安装到文件系统上后,我们的过滤驱动就可以拦截到IRP。这个时候,我们可以打开看看IRP里的东西,做点记录,然后什么都不改变的把IRP继续往下发,当然,也可以直接填写IRP中的一些字段然后直接回发给上层,上层收到IRP后就认为上一次的请求结束了,它根本不管这个IRP是不是文件系统发给他的。
所以大家可以看到上面的例子函数里,填写了PFLT_CALLBACK_DATA结构中的两个字段。最后的返回值FLT_PREOP_COMPLETE就表示请求已经结束了,不用再把IRP往下传了。
在minifilter中,我们除了要自己编写希望过滤的请求的预处理和完成函数。还有其他的回调函数可以编写,不过他们都是可选的,不一定要实现。具体有哪些这里就不列举了。
MINIFILTER的另一个特色:与应用层的通信
我们在编写文件过滤驱动的时候,不免会经常和上层的应用程序进行通信,在传统的文件过滤驱动框架中,想要实现驱动层和应用层的通信一般都是通过DiviceIoControl配合内核模块中的处理控制请求,或者申请一块共享存储区实现,都比较麻烦。minifilter中专门提供了通信用的API,并且这种API在使用的时候,就像是网络编程中的socket通信一样方便简单。
下面的代码是建立一个通信端口的过程:
- PSECURITY_DESCRIPTOR sd;
- OBJECT_ATTRIBUTES oa;
- status = FltBuildDefaultSecurityDescriptor(&sd,FLT_PORT_ALL_ACCESS);
- if(!NT_SUCCESS(status)){
- goto final;
- }
- RtlInitUnicodeString(&uniString,MINISPY_PORT_NAME);
- InitializeObejectAttributes(&oa,&uniString,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,NULL,sd);
- status = FltCreateCommunicationPort(gFilterHandle,&gServerPort,&oa,NULL,NPMiniConnect,NPMiniDisconnect,NPMiniMessage,1);
首先函数FltBuildDefaultSecurityDescriptor是用来申请一个安全叙述子(额,简单点,就是给使用通信端口的用户申请个权限,这里可以看到申请的权限是FLT_PORT_ALL_ACCESS,意思就是:用户层的程序连接到设置了这个权限级别的通信端口后,可以获得所有操作权限)。
下面的InitializeObejectAttributes就是用来给我们要创建的对象(名称是:MINISPY_PORT_NAME)设置一些属性值。
最后最重要的FltCreateCommunicationPort就是给这个端口定义所需要的三个函数,同时注册这个端口(注册了才能用)。这里注册的三个函数分别是:
NPMiniConnect用户层和内核层建立连接的时候会调用该函数
NPMiniDisconnect用户层和内核层断开连接的时候会调用该函数
NPMiniMessage用户层和内核层进行通讯的时候会调用
当然,既然称他们为回调函数,那他们就不是我们用户层的程序去调用的,工作原理是这样的,我们在用户层通过两个api:FilterConnectCommunicationPort和FilterSendMessage来发出请求,然后通讯端口会根据我们的请求自己去调用这三个函数完成具体的工作。其中前者对应NPMiniConnect,后者对应NPMiniMessage。
完成上面三个回调函数后,内核中的通讯代码已经准备好了。
下面就是完成通讯的另一端内容:用户层(应用层)。这里要注意的是在编写程序的时候,需要包含几个minifilter必须的头文件和库文件:FltUser.h,fltLib.lib,fltMgr.lib,具体如下:
#include <FltUser.h>
#progma comment(lib,"fltLib.lib")
#progma comment(lib,"fltMgr.lib")
后面的代码需要了解的就是一个简单的流程:先FilterConnectCommunicationPort连接上目标端口,再FilterSendMessage发送消息。原理就介绍这么多,具体的代码在下载连接中,其中,用户层和通讯端口的连接是做成了dll,首先要生成dll,然后要使用dll就用哪个app工程,里面会装载dll。另一个minifilter可以生成一个sys系统文件,把系统文件用inf文件安装上,并在cmd里面输入net start XXX(这里是sys的文件名,其实是服务名,只不过两个名称大部分情况下是一样的)通讯端口就打开了,然后app就可以试着连接和通讯了。
minifilter代码下载http://download.csdn.net/detail/arvon2012/4687632
技术相关更多文章猛击:哇啦天堂论坛技术区
http://blog.csdn.net/arvon2012/article/details/7926366
Minifilter微过滤框架:框架介绍以及驱动层和应用层的通讯的更多相关文章
- 2、CC2541芯片中级教程-OSAL操作系统(进一步了解-OLED && 普通按键和5方向按键-中断!!!)这个系统驱动层和应用层不一样~
本文根据一周CC2541笔记汇总得来—— 适合概览和知识快速索引—— 全部链接: 中级教程-OSAL操作系统\OSAL操作系统-实验01 OSAL初探 [插入]SourceInsight-工程建立方法 ...
- 驱动开发:内核枚举Minifilter微过滤驱动
Minifilter 是一种文件过滤驱动,该驱动简称为微过滤驱动,相对于传统的sfilter文件过滤驱动来说,微过滤驱动编写时更简单,其不需要考虑底层RIP如何派发且无需要考虑兼容性问题,微过滤驱动使 ...
- java框架之SpringCloud(1)-微服务及SpringCloud介绍
微服务概述 是什么 业界大牛 Martin Fowler 这样描述微服务: 参考[微服务(Microservices)-微服务原作者Martin Flower博客翻译]. 下面是关于上述博客中的部分重 ...
- 「 从0到1学习微服务SpringCloud 」08 构建消息驱动微服务的框架 Spring Cloud Stream
系列文章(更新ing): 「 从0到1学习微服务SpringCloud 」01 一起来学呀! 「 从0到1学习微服务SpringCloud 」02 Eureka服务注册与发现 「 从0到1学习微服务S ...
- .NET平台开源项目速览(13)机器学习组件Accord.NET框架功能介绍
Accord.NET Framework是在AForge.NET项目的基础上封装和进一步开发而来.因为AForge.NET更注重与一些底层和广度,而Accord.NET Framework更注重与机器 ...
- Django - Django框架 简单介绍
Django框架 简单介绍 本文地址: http://blog.csdn.net/caroline_wendy/article/details/29172271 1. 介绍 Django是一个开放源码 ...
- Go语言Web框架gwk介绍 3
Go语言Web框架gwk介绍 (三) 上一篇忘了ChanResult ChanResult 可以用来模拟BigPipe,定义如下 type ChanResult struct { Wait syn ...
- vue对比其他框架详细介绍
vue对比其他框架详细介绍 对比其他框架 — Vue.jshttps://cn.vuejs.org/v2/guide/comparison.html React React 和 Vue 有许多相似之处 ...
- python nose测试框架全面介绍七--日志相关
引: 之前使用nose框架时,一直使用--logging-config的log文件来生成日志,具体的log配置可见之前python nose测试框架全面介绍四. 但使用一段时间后,发出一个问题,生成的 ...
随机推荐
- OC学习心得【适合初学者】
一.类和对象 1.OC语言是C语言的扩充,并且OC是iOS和OS X操作系统的编程语言. ①具备完善的面向对象特性: 封装:将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内 继 ...
- 最基础的Hash
type thash=^node; node=record state:longint; next:thash; end; var a,i:longint; p:thash; hash:..]of t ...
- [shell基础]——整数比较;字符串比较;文件测试;逻辑测试符
整数比较方法一:[ ] 或 [[ ]] (1) 此方法需要使用整数比较运算符.[标注:equal 等于 greater 大于 less-then 小于] (2) 使用时一定要注意前后一 ...
- 实现压缩access(*.mdb)数据库的方法
下面的函数用来压缩access数据库 需要增加ComObj单元 //压缩与修复数据库,覆盖源文件 function CompactDatabase(AFileName,APassWord:string ...
- Android L Camera2 API 使用实例程序汇总
在网上发现几个使用Camera API2开发的实例程序,总结一下方便后续参考: 1.Camera2 Basic : https://github.com/googlesamples/android-C ...
- C++中的const关键字的用法
1.const用于修饰普通变量,表示常量,不建议修改,某种程度上不允许修改(其实也是可以修改的) 指针常量 :指针(指向的变量的值)自身是一个常量,说明不能改变自身的指向 int* const p= ...
- android数独游戏
最近没事干,照着视频教程写了一个数独游戏,很粗糙还有很多要修改的地方.下面就来说说这个游戏吧 1.自定义一个View控件,用来在屏幕上显示一个9*9的格子,其实就是横着画8条线,竖着画8跳线,然后将其 ...
- Grails 1.2参考文档速读(10):Controller
转载:http://keyvalue.blog.51cto.com/1475446/303260 从本篇起,我们将开始进入Grails的Web层,首先让我们从Controller说起. G ...
- svn 检出 Check out 请求的名称有效,但是找不到请求的类型的数据。
根据问题不同有不同的解决方案,可按照以下方法进行解决1.取消TortoiseSVN-网络-代理2.确认SVN目录地址是否正确,可在浏览器中直接打开测试.如地址是由计算机名组成请改成Ip地址进行测试
- Leetcode#106 Construct Binary Tree from Inorder and Postorder Traversal
原题地址 二叉树基本操作 [ ]O[ ] [ ][ ]O 代码: TreeNode *restore(vector<i ...