其他
Minifilter学习的那些事
本文为看雪论坛优秀文章
看雪论坛作者ID:0xC5
1 前言
2 Minifilter简介及基本结构
3 Minifilter重要数据结构
及代码实现
DriverEntry代码如下:
NTSTATUS
DriverEntry (
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
UNREFERENCED_PARAMETER( RegistryPath );
PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("MyMinifiter!DriverEntry: Entered\n") );
//若注册成功则返回微过滤器的句柄
status = FltRegisterFilter( DriverObject,
## &FilterRegistration,//这是一个重要的数据结构,包含着我们过滤操作的回调函数
&gFilterHandle );
FLT_ASSERT( NT_SUCCESS( status ) );
if (NT_SUCCESS( status )) {
//依据注册成功的句柄开启过滤
status = FltStartFiltering( gFilterHandle );
if (!NT_SUCCESS( status ))
FltUnregisterFilter( gFilterHandle );
}
}
return status;
}
FilterRegistration参数的声明如下,具体的结构体的定义在这里就不贴出了。
CONST FLT_REGISTRATION FilterRegistration = {
sizeof( FLT_REGISTRATION ), //结构的大小
FLT_REGISTRATION_VERSION, //版本
0, //微过滤器标志位
NULL, //Context
Callbacks, //回调函数
MyMinifiterUnload, //卸载回调函数
MyMinifiterInstanceSetup, //安装实例回调
MyMinifiterInstanceQueryTeardown, //控制实例销毁函数
MyMinifiterInstanceTeardownStart, //实例解绑定函数
MyMinifiterInstanceTeardownComplete, // 实例解绑定完成函数
NULL, //生成文件名回调
NULL, //格式化名字组件回调
NULL //格式化上下文清理回调
};
重点关注Callbacks,里面包含着处理请求的过滤函数,分为两种,一是在请求之前进行处理(Pre-Operation Fun),另一种是在请求完成之后处理(Post-Operation Fun)。下面是一个例子:
CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE, //Request的功能号
0, //标志位,置0表示仅对/读写回调有用
MyMinifiterPreOperation, //Pre-Operation Fun
MyMinifiterPostOperation }, //Post-Operation Fun
{ IRP_MJ_CREATE_NAMED_PIPE,
0,
MyMinifiterPreOperation,
MyMinifiterPostOperation },
{ IRP_MJ_CLOSE,
0,
MyMinifiterPreOperation,
MyMinifiterPostOperation },
{ IRP_MJ_READ,
0,
MyMinifiterPreOperation,
MyMinifiterPostOperation },
{ IRP_MJ_OPERATION_END } //最后一个元素必须存在否则过滤管理器不知道有多少个回调参数
4 编写一个自己的Minifilter
4.1 inf文件
4.2 Callback设置
Vs生成的框架默认是没有注册任何回调的,可以根据自己需要在//TODO注释后声明自己要过滤的操作和回调函数。也可以偷懒直接吧if 0 修改成if 1 直接过滤所有操作。当然此声明中Vs提供了默认的回调函数,也可以自行选择修改。
4.3 回调函数
FLT_PREOP_CALLBACK_STATUS
FsFilter1PreOperation ( //FsFilter1是驱动名称
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
FLT_POSTOP_CALLBACK_STATUS
FsFilter1PostOperation (
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_opt_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
至此,一个简单的Mnifilter驱动就已经能够成功生成并能够进行加载了(BTW,x64还得自行签名或者强制禁用驱动签名)。
5 实现简单的过滤操作
5.1 过滤文件
FLT_PREOP_CALLBACK_STATUS
MyMinifiterPreOperation (
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
NTSTATUS status;
PFLT_FILE_NAME_INFORMATION nameInfo;
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
PAGED_CODE();
__try {
status = FltGetFileNameInformation(Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo);
if (NT_SUCCESS(status)) {
FltParseFileNameInformation(nameInfo);
if (wcsstr(nameInfo->Name.Buffer, L"calc.exe") //过滤计算器
Data->IoStatus.Status = STATUS_ACCESS_DENIED;//填写拒绝
Data->IoStatus.Information = 0;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
//release resource
FltReleaseFileNameInformation(nameInfo);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
DbgPrint("EXCEPTION_EXECUTE_HANDLER\n");
}
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
5.2 文件重定向
FLT_PREOP_CALLBACK_STATUS
MyMinifiterPreOperation (
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
NTSTATUS status;
PFLT_FILE_NAME_INFORMATION nameInfo;
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
UNICODE_STRING desFilename;
RtlCreateUnicodeString(&desFilename, L"\\DEVICE\\HARDDISKVOLUME3\\USERS\\User\\DESKTOP\\2.TXT");//为了方便测试路径我写死了,实际操作也很简单仅仅只是字符串的拼接
PFILE_OBJECT FileObject;
PAGED_CODE();
__try {
status = FltGetFileNameInformation(Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo);
if (NT_SUCCESS(status)) {
FltParseFileNameInformation(nameInfo);
if (wcsstr(nameInfo->Name.Buffer, L"1.txt")) {
FileObject = Data->Iopb->TargetFileObject;
FileObject->FileName = desFilename;//替换成目标文件的路径。
Data->IoStatus.Information = IO_REPARSE;
Data->IoStatus.Status = STATUS_REPARSE;
Data->Iopb->TargetFileObject->RelatedFileObject = NULL;
FltSetCallbackDataDirty(Data);
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
//release resource
FltReleaseFileNameInformation(nameInfo);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
DbgPrint("EXCEPTION_EXECUTE_HANDLER\n");
}
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
6 Some interesting thing
7 结语
看雪ID:0xC5
https://bbs.pediy.com/user-home-768770.htm
*本文由看雪论坛 0xC5 原创,转载请注明来自看雪社区。
本文参与了#看雪30天发帖打卡挑战#活动。
发帖见证成长,坚持见证不凡。
不仅可以收获进步,还可赢取物质奖励哦!
想要了解更多活动详情,戳 ↓
另外,贴心提示本次再印刷还没购买0day安全正版书籍的小伙伴抓紧时间啦!
目前已满500本,可安排发货啦!
点击以下小程序即可预购!
推荐文章++++
求分享
求点赞
求在看