文件防刪除保護(miniifiter)

0x01 思路(原理)數組

  驅動層文件保護的思路是經過minifilter過濾文件刪除相關的IRP,並將目標文件與被保護文件相比較,命中保護規則的話返回STATUS_ACCESS_DENIED拒絕訪問;也能夠進一步利用回調函數獲取的FLT_CALLBACK_DATA結構體解析文件刪除操做對應的發起者進程,與白名單進程(容許執行刪除操做的進程)相比較。ide

      

  須要過濾的IRP類型:IRP_MJ_SET_INFORMATION與IRP_MJ_CREATE(或還有其餘類型IRP須要過濾,還沒有知)函數

       IRP_MJ_SET_INFORMATION的產生緣由通常是請求設置文件屬性等等,好比ZwSetInformationFile函數能夠發起此IRP.這裏順帶說一句的是,許多驅動都用ZwSetInformationFile函數來實現強刪文件的,好比騰訊電腦管家中的TSSysKit.sys驅動中文件穿透操做的刪除文件就是調用ZwSetInformationFile函數將FileInformationClass設爲FileDispositionInformation且((PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->DeleteFile設爲TRUE來達到刪除文件的目的(若是是強刪正在運行的文件,那麼還需將文件對象的SectionObjectPointer->ImageSectionObject和 SectionObjectPointer->DataSectionObject 兩個字段置零)。所以,對於IRP_MJ_SET_INFORMATION,應當檢查FileInformationClass是不是FileRenameInformation和FileShortNameInformation標誌。post

  IRP_MJ_CREATE的產生緣由通常是請求打開文件句柄,文件對象以及其餘內核對象等等,好比ZwCreateFile函數能夠發起此IRP.若是ZwCreateFile函數指定了FILE_DELETE_ON_CLOSE標誌,那麼當最後一個文件句柄被NtClose關閉時,文件會被刪除,這也就是過濾IRP_MJ_CREATE的緣由。所以,對於IRP_MJ_CREATE,應當檢查是否有FILE_DELETE_ON_CLOSE 標誌指定。spa

 

 

0x01 源碼及註釋以下線程

  1 #include <fltKernel.h>
  2 //#include "FileDeleteProtect.h"
  3 
  4 #define DEBUG
  5 #ifdef DEBUG
  6 #define DBG_PRINTF(_fmt, ...) DbgPrint(_fmt, __VA_ARGS__)
  7 #else
  8 #define DBG_PRINTF(_fmt, ...) { NOTHING; }
  9 #endif
 10 
 11 
 12 DRIVER_INITIALIZE DriverEntry;
 13 
 14 NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath);
 15 NTSTATUS Unload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags);
 16 FLT_PREOP_CALLBACK_STATUS PreAntiDelete(_Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Flt_CompletionContext_Outptr_ PVOID *CompletionContext);
 17 
 18 //過濾IRP的回調數組
 19 CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
 20     { IRP_MJ_CREATE, 0, PreAntiDelete, NULL },                // DELETE_ON_CLOSE 標誌.
 21     { IRP_MJ_SET_INFORMATION, 0, PreAntiDelete, NULL },        // FileDispositionInformation(Ex).
 22     { IRP_MJ_OPERATION_END }
 23 };
 24 
 25 CONST FLT_REGISTRATION FilterRegistration = {
 26     sizeof(FLT_REGISTRATION),                // Size
 27     FLT_REGISTRATION_VERSION,                // Version
 28     0,                                        // Flags
 29     NULL,                                    // ContextRegistration
 30     Callbacks,                                // OperationRegistration
 31     Unload,                                    // FilterUnloadCallback
 32     NULL,                                    // InstanceSetupCallback
 33     NULL,                                    // InstanceQueryTeardownCallback
 34     NULL,                                    // InstanceTeardownStartCallback
 35     NULL,                                    // InstanceTeardownCompleteCallback
 36     NULL,                                    // GenerateFileNameCallback
 37     NULL,                                    // NormalizeNameComponentCallback
 38     NULL                                    // NormalizeContextCleanupCallback
 39 };
 40 
 41 PFLT_FILTER Filter;
 42 static UNICODE_STRING Protected = RTL_CONSTANT_STRING(L"EXE");
 43 
 44 NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
 45 
 46     UNREFERENCED_PARAMETER(RegistryPath);
 47 
 48     NTSTATUS Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
 49     if (!NT_SUCCESS(Status)) {
 50         DBG_PRINTF("Failed to register filter: <0x%08x>.\n", Status);
 51         return Status;
 52     }
 53 
 54     Status = FltStartFiltering(Filter);
 55     if (!NT_SUCCESS(Status)) {
 56         DBG_PRINTF("Failed to start filter: <0x%08x>.\n", Status);
 57         FltUnregisterFilter(Filter);
 58     }
 59 
 60     return Status;
 61 }
 62 
 63 NTSTATUS Unload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags) {
 64     UNREFERENCED_PARAMETER(Flags);
 65     DBG_PRINTF("Unload called.\n");
 66     FltUnregisterFilter(Filter);
 67 
 68     return STATUS_SUCCESS;
 69 }
 70 
 71 /*
 72 * PreCallback的調用時機
 73 * IRP_MJ_CREATE——ZwCreateFile
 74 * IRP_MJ_SET_INFORMATION——ZwSetInformation.
 75 */
 76 FLT_PREOP_CALLBACK_STATUS PreAntiDelete(_Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Flt_CompletionContext_Outptr_ PVOID *CompletionContext) {
 77     UNREFERENCED_PARAMETER(CompletionContext);
 78     PAGED_CODE();//PreCallback的IRQL應當<= APC_LEVEL
 79 
 80     FLT_PREOP_CALLBACK_STATUS Status = FLT_PREOP_SUCCESS_NO_CALLBACK;//再也不調用postoperation callback routine,
 81 
 82 
 83     BOOLEAN IsDirectory;//目錄操做跳過,無論
 84     NTSTATUS status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDirectory);
 85     if (NT_SUCCESS(status)) {
 86         if (IsDirectory == TRUE) {
 87             return Status;
 88         }
 89     }
 90 
 91     if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
 92         if (!FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DELETE_ON_CLOSE)) {
 93             return Status;
 94         }
 95     }
 96 
 97 
 98     if (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION) {
 99         switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass) {
100         case FileRenameInformation:
101         case FileRenameInformationEx:
102         case FileDispositionInformation:
103         case FileDispositionInformationEx:
104         case FileRenameInformationBypassAccessCheck:
105         case FileRenameInformationExBypassAccessCheck:
106         case FileShortNameInformation:
107             break;
108         default:
109             return Status;
110         }
111     }
112 
113     /*
114     ZwCreateFile和ZwSetInformation函數都是運行在PASSIVE_LEVEL的,因此當前的線程上下文
115     應當就是ZwCreateFile或ZwSetInformation函數的調用者進程對應的線程的上下文Context,
116     因此這裏能夠判斷調用者進程是否在白名單中(若是存在白名單進程的話)
117     if (IoThreadToProcess(Data->Thread) == WhiteListProcess) {
118     return FLT_PREOP_SUCCESS_NO_CALLBACK;
119     }
120     */
121 
122     PFLT_FILE_NAME_INFORMATION FileNameInfo = NULL;
123     if (FltObjects->FileObject != NULL) {
124         status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &FileNameInfo);
125         if (NT_SUCCESS(status)) {
126             FltParseFileNameInformation(FileNameInfo);
127             //if (RtlCompareUnicodeString(&FileNameInfo->Name, &Protected, TRUE) == 0) {
128             if (RtlCompareUnicodeString(&FileNameInfo->Extension, &Protected, TRUE) == 0) {
129                 DBG_PRINTF("Protecting file deletion/rename!");
130                 Data->IoStatus.Status = STATUS_ACCESS_DENIED;
131                 Data->IoStatus.Information = 0;
132                 Status = FLT_PREOP_COMPLETE;
133             }
134             // Clean up file name information.
135             FltReleaseFileNameInformation(FileNameInfo);
136         }
137     }
138 
139     return Status;
140 }
View Code
相關文章
相關標籤/搜索