Mini-Filter拦截JPG失效:无法阻止「Windows照片」打开图片求助
解决方案:Mini-Filter拦截Windows照片应用JPG打开失效问题
我之前碰到过一模一样的问题,Windows照片这个UWP应用的文件访问逻辑确实有点绕,咱们来一步步拆解原因和解决办法:
核心原因分析
你提到PostOperationCallback已经被调用,但拦截失效,主要有几个关键点:
- 拦截时机太晚:PostCreate阶段调用
FltCancelFileOpen时,文件句柄已经被应用(或其代理进程)成功获取,此时取消操作已经无法阻止应用读取文件。 - UWP应用的代理访问:Windows照片是UWP应用,它的文件操作并非直接发起,而是通过系统Broker进程(比如
FileBroker.exe)代理执行,你的拦截逻辑可能没处理这种间接请求。 - 快速IO绕过:Windows照片可能使用快速IO(Fast IO)路径读取文件,而你的驱动只注册了常规MJ_CREATE回调,没覆盖快速IO场景。
具体解决方案
1. 把拦截逻辑移到PreCreate回调(最可靠的方式)
在文件打开操作的PreCreate阶段直接拒绝请求,这是阻止文件被打开的最佳时机,因为此时系统还没完成文件句柄的创建。示例代码如下:
FLT_PREOP_CALLBACK_STATUS PreCreateCallback( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Out_ PVOID *CompletionContext ) { UNREFERENCED_PARAMETER(CompletionContext); PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; NTSTATUS status = FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &fileNameInfo ); if (NT_SUCCESS(status)) { UNICODE_STRING jpgExt; RtlInitUnicodeString(&jpgExt, L".JPG"); // 忽略大小写匹配扩展名 if (RtlCompareUnicodeString(&fileNameInfo->Extension, &jpgExt, TRUE) == 0) { DbgPrint("Blocking JPG file access in PreCreate...\n"); // 直接返回访问拒绝错误 Data->IoStatus.Status = STATUS_ACCESS_DENIED; Data->IoStatus.Information = 0; FltReleaseFileNameInformation(fileNameInfo); return FLT_PREOP_COMPLETE; } FltReleaseFileNameInformation(fileNameInfo); } return FLT_PREOP_SUCCESS_WITH_CALLBACK; }
2. 处理UWP Broker进程的代理请求
Windows照片的文件操作会通过Broker进程发起,你需要在回调中验证请求的发起进程,确保拦截这些代理请求:
- 使用
FltGetRequestorProcessId获取请求进程ID - 通过
PsLookupProcessByProcessId获取进程对象,再查询进程名称(比如检查是否是FileBroker.exe或explorer.exe) - 结合令牌信息(
SeQueryInformationToken)判断是否属于UWP沙箱环境,针对性拦截
3. 注册快速IO回调防止绕过
Windows照片可能使用快速IO路径读取文件,你的驱动需要注册对应的快速IO回调(比如FastIoRead、FastIoQueryBasicInfo),在这些回调中同样检查文件扩展名并拒绝操作。
4. 优化PostCreate阶段的拦截逻辑(如果必须用PostCreate)
如果因为某些原因必须在PostCreate阶段处理,需要确保不仅调用FltCancelFileOpen,还要主动关闭文件句柄并设置错误状态:
FLT_POSTOP_CALLBACK_STATUS PostCreateCallback( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_opt_ PVOID CompletionContext, _In_ FLT_POST_OPERATION_FLAGS Flags ) { UNREFERENCED_PARAMETER(CompletionContext); UNREFERENCED_PARAMETER(Flags); if (Data->IoStatus.Status == STATUS_SUCCESS) { PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; NTSTATUS status = FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &fileNameInfo ); if (NT_SUCCESS(status)) { UNICODE_STRING jpgExt; RtlInitUnicodeString(&jpgExt, L".JPG"); if (RtlCompareUnicodeString(&fileNameInfo->Extension, &jpgExt, TRUE) == 0) { DbgPrint("Canceling JPG file open in PostCreate...\n"); // 取消打开操作 FltCancelFileOpen(FltObjects->Instance, Data); // 主动关闭文件句柄,确保应用无法使用 FltClose(FltObjects->FileObject); // 设置错误状态 Data->IoStatus.Status = STATUS_ACCESS_DENIED; Data->IoStatus.Information = 0; } FltReleaseFileNameInformation(fileNameInfo); } } return FLT_POSTOP_FINISHED_PROCESSING; }
额外注意事项
- 确保你的驱动有足够的权限:UWP应用运行在沙箱中,驱动需要具备
SeSecurityPrivilege等权限才能正确拦截其请求。 - 测试不同的JPG文件场景:比如网络共享中的JPG、本地磁盘的JPG,确保拦截逻辑覆盖所有场景。
内容的提问来源于stack exchange,提问作者Bryce Woods
相关产品推荐
相关产品推荐

