前言
某些情况下,我们需要保护文件或文件夹,不被恶意 MountPoint
或 HardLink
等操作。
有以下几种可选方案:
1、在操作文件之前,先检测是否被 MountPoint
,如果有则解除。
2、利用MiniFilter过滤驱动,来拦截所有的 MountPoint
等操作。
3、使用DACL权限管理机制,在 MountPoint
时,请求的是 FILE_WRITE_ATTRIBUTES
权限,
所以可以在目标中添加 拒绝Users组的写入属性
权限,而Users组在CreateFile时,需要排除请求
写入属性权限,即 FILE_ALL_ACCESS & ~FILE_WRITE_ATTRIBUTES
,否则会因为权限被拒绝而
打开文件失败。注:只是修改的Users组,其他组不受影响。修改父目录的权限后,其所有子目录
可以自动继承该权限。重要:目标的拥有者不能是Users组,因为拥有者具有全部权限
。
使用MiniFilter过滤
MountPoint操作对应到MiniFilter驱动中,主功能码为 IRP_MJ_FILE_SYSTEM_CONTROL
,
内部控制码是 FSCTL_SET_REPARSE_POINT
。
HardLink操作对应到MiniFilter驱动中,主功能码是 IRP_MJ_SET_INFORMATION
,对应的
FileInformationClass
为 FileLinkInformation
。
注册 FLT_OPERATION_REGISTRATION
的结构体,如下所示
1 2 3 4 5
| FLT_OPERATION_REGISTRATION Callbacks[] = { { IRP_MJ_SET_INFORMATION, 0, PtPreSetInfromation, NULL }, { IRP_MJ_FILE_SYSTEM_CONTROL, 0, PtPreFileSystemControl, NULL }, { IRP_MJ_OPERATION_END } };
|
过滤文件映射的处理函数如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| FLT_POSTOP_CALLBACK_STATUS PtPreSetInfromation( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Out_ PVOID *CompletionContext) { ULONG ProcessID = 0; PEPROCESS EProcess = NULL; NTSTATUS Status = STATUS_SUCCESS; PFLT_FILE_NAME_INFORMATION NameInfo = NULL; UNREFERENCED_PARAMETER(CompletionContext); EProcess = FltGetRequestorProcess(Data); ProcessID = FltGetRequestorProcessId(Data); if (Data->Iopb->Parameters.SetFileInformation.FileInformationClass != FileLinkInformation) return FLT_PREOP_SUCCESS_NO_CALLBACK; Status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &NameInfo); if (!NT_SUCCESS(Status) return FLT_PREOP_SUCCESS_NO_CALLBACK; Status = FltParseFileNameInformation(NameInfo); if (!NT_SUCCESS(Status)) { FltReleaseFileNameInformation(NameInfo); return FLT_PREOP_SUCCESS_NO_CALLBACK; } Data->Iopb->TargetFileObject; if (IsProtectFile(NameInfo)) { FltReleaseFileNameInformation(NameInfo); Data->IoStatus.Status = STATUS_ACCESS_DENIED; return FLT_PREOP_COMPLETE; } FltReleaseFileNameInformation(NameInfo); return FLT_PREOP_SUCCESS_NO_CALLBACK; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| FLT_POSTOP_CALLBACK_STATUS PtPreFileSystemControl( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Out_ PVOID *CompletionContext) { ULONG ProcessID = 0; PEPROCESS EProcess = NULL; NTSTATUS Status = STATUS_SUCCESS; PFLT_FILE_NAME_INFORMATION NameInfo = NULL; UNREFERENCED_PARAMETER(CompletionContext); EProcess = FltGetRequestorProcess(Data); ProcessID = FltGetRequestorProcessId(Data); if (Data->Iopb->Parameters.FileSystemControl.Common.FsControlCode != FSCTL_SET_REPARSE_POINT) return FLT_PREOP_SUCCESS_NO_CALLBACK; Status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &NameInfo); if (!NT_SUCCESS(Status) return FLT_PREOP_SUCCESS_NO_CALLBACK; Status = FltParseFileNameInformation(NameInfo); if (!NT_SUCCESS(Status)) { FltReleaseFileNameInformation(NameInfo); return FLT_PREOP_SUCCESS_NO_CALLBACK; } Data->Iopb->TargetFileObject; if (IsProtectFile(NameInfo)) { FltReleaseFileNameInformation(NameInfo); Data->IoStatus.Status = STATUS_ACCESS_DENIED; return FLT_PREOP_COMPLETE; } FltReleaseFileNameInformation(NameInfo); return FLT_PREOP_SUCCESS_NO_CALLBACK; }
|
注意:无论是 MountPoint
还是 HardLink
都存在 源对象
和 目的对象
,这里只处理了 源对象
。
可以参考链接 http://www.sinkland.cn/?p=204 中的例子来处理 目的对象
。