打个广告: http://hi.baidu.com/hu3167343
这是本人刚申请的百度空间, 大家快来加我好友啊, 哈哈.
最近学习了下文件微过滤驱动的框架, 确实比文件过滤系统简单N多啊.
1.DriverEntry
NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
UNREFERENCED_PARAMETER( RegistryPath );
// 注册一个过虑器
status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&gFilterHandle );
if (NT_SUCCESS( status )) {
// 开启过滤
status = FltStartFiltering( gFilterHandle );
if (!NT_SUCCESS( status )) {
// 开启不成功则注销过滤器
FltUnregisterFilter( gFilterHandle );
}
}
return status;
}
这里的主要函数是FltRegisterFilter, 原型如下:
NTSTATUS
FltRegisterFilter(
IN PDRIVER_OBJECT Driver, //在DriverEntry中传入的参数
IN CONST FLT_REGISTRATION *Registration, //微过滤器注册结构, 这个是最重要的参数
OUT PFLT_FILTER *RetFilter //微顾虑句柄, 通常保存在全局变量中
);
FLT_REGISTRATION的结构如下:
typedef struct _FLT_REGISTRATION {
USHORT Size; //结构的大小, 一般为sizeof(FLT_REGISTRATION)
USHORT Version; //结构的版本, 一般写FLT_REGISTRATION_VERSION即可
FLT_REGISTRATION_FLAGS Flags; //标志位, 一般填0
CONST FLT_CONTEXT_REGISTRATION *ContextRegistration;
CONST FLT_OPERATION_REGISTRATION *OperationRegistration; //操作注册函数集, 这个域是最重要的
PFLT_FILTER_UNLOAD_CALLBACK FilterUnloadCallback; //卸载回调函数
PFLT_INSTANCE_SETUP_CALLBACK InstanceSetupCallback; //实例绑定回调函数, 在这里可以决定绑定哪些卷, 可以为NULL
...
} FLT_REGISTRATION, *PFLT_REGISTRATION;
其中第5个域FLT_OPERATION_REGISTRATION 结构如下:
typedef struct _FLT_OPERATION_REGISTRATION {
UCHAR MajorFunction; //IRP的主功能号
FLT_OPERATION_REGISTRATION_FLAGS Flags; //标志位, 一般填0即可, 在读写IRP中可能会有特殊, 具体参看MSDN
PFLT_PRE_OPERATION_CALLBACK PreOperation; //预操作回调函数
PFLT_POST_OPERATION_CALLBACK PostOperation; //操作后回调函数
PVOID Reserved1;
} FLT_OPERATION_REGISTRATION, *PFLT_OPERATION_REGISTRATION;
实例如下:
const FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE,
0,
NPPreCreate,
NPPostCreate },
{ IRP_MJ_OPERATION_END } //最后一项必须为这个, 否则过滤管理器,无法知道到底有多少个元素
};
const FLT_REGISTRATION FilterRegistration = {
sizeof( FLT_REGISTRATION ), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags
NULL, // Context
Callbacks, // Operation callbacks
NPUnload, // MiniFilterUnload
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
}
2.卸载例程:
NTSTATUS
NPUnload (
__in FLT_FILTER_UNLOAD_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
//注销此过滤器
FltUnregisterFilter( gFilterHandle );
return STATUS_SUCCESS;
}
3.微过滤驱动与应用层通信
(1)在DriverEntry中建立一个通信端口
//建立一个默认安全的描述符
status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );
RtlInitUnicodeString( &uniString, MINISPY_PORT_NAME );
InitializeObjectAttributes( &oa,
&uniString,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
sd );
//建立一个通信端口
status = FltCreateCommunicationPort( gFilterHandle,
&gServerPort,
&oa,
NULL,
NPMiniConnect, //R3连接通信端口时的回调例程
NPMiniDisconnect, //R3断开连接时的回调例程
NPMiniMessage, //R3发送数据时的回调函数
1 );
//最后释放安全描述符
FltFreeSecurityDescriptor( sd );
其中比较重要的函数是NPMiniMessage . 此函数在我们调用R3层函数FilterSendMessage时被调用.
函数原型如下:
NTSTATUS
NPMiniMessage (
__in PVOID ConnectionCookie,
__in_bcount_opt(InputBufferSize) PVOID InputBuffer,
__in ULONG InputBufferSize,
__out_bcount_part_opt(OutputBufferSize,*ReturnOutputBufferLength) PVOID OutputBuffer,
__in ULONG OutputBufferSize,
__out PULONG ReturnOutputBufferLength
)
其中在输入的参数中, InputBuffer 和 OutputBuffer需要注意. 这两个参数使用的都是用户模式下的地址,
过滤管理器已经帮我们做了ProbedForRead (对于InputBuffer) 和 ProbedForWrite (对于OutputBuffer)的操作.
以防止R3层传入无效的地址.
但是当我们从InputBuffer中取数据, 或者往OutputBuffer写数据时, 要对他们使用try-catch.
如下;
_try{
memcpy(OutputBuffer, strPath, strlen(strPath));
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("catch error\r\n"));
}
(2)NPUnload例程中关闭通信端口
FltCloseCommunicationPort( gServerPort );
(3)R3程序中
不是用我们常用的DeviceIoControl, 而是有了两个新的函数
连接端口:
HRESULT
WINAPI
FilterConnectCommunicationPort(
IN LPCWSTR lpPortName,
IN DWORD dwOptions,
IN LPVOID lpContext OPTIONAL,
IN DWORD dwSizeOfContext,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
OUT HANDLE *hPort
);
发送和接收数据:
HRESULT
WINAPI
FilterSendMessage(
__in HANDLE hPort,
__in_bcount LPVOID lpInBuffer,
__in DWORD dwInBufferSize,
__out_bcount_part_opt LPVOID lpOutBuffer,
__in DWORD dwOutBufferSize,
__out LPDWORD lpBytesReturned
);
在使用FilterSendMessage函数时, 我遇到了一个问题. 就是当我们不需要输入参数而把lpInBuffer传入NULL, dwInBufferSize传入0, 此函数调用会失败, R0层中的NPMiniMessage函数不会被回调. 不知道这是我个人对这个函数参数的理解问题, 还是函数本来就是这样的, 求解释~
其他我就不再累述了, 函数具体用法请参看MSDN
下面是我学习文件微过滤驱动时的实验产物, MzfFileMon, 界面如下:
Bin如下:
MzfFileMonBin.rar
R0和R3代码如下:
MzfFileMonSrc.rar
- 标 题:文件微过滤驱动学习笔记 + MzfFileMon(开源)
- 作 者:莫灰灰
- 时 间:2011-05-22 00:09:14
- 链 接:http://bbs.pediy.com/showthread.php?t=134309