Detecting Folder(Directory) deletion in minifilter

Hi everybody,
I want to detect Folder(Directory) is deletion/Renaming on Windows.
How can i detect ??
Thank you.

How much research have you done? Do you know how to detect a file delete or rename?

Yes. This is detect file deletion, and it’s Ok.

_**
FLT_PREOP_CALLBACK_STATUS badgirlFilterAntiDelete(Inout PFLT_CALLBACK_DATA Data, In PCFLT_RELATED_OBJECTS FltObjects, Flt_CompletionContext_Outptr PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(CompletionContext);
PAGED_CODE();
FLT_PREOP_CALLBACK_STATUS ret = FLT_PREOP_SUCCESS_NO_CALLBACK;
// Ignore directories
BOOLEAN IsDir;
NTSTATUS status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDir);
if (NT_SUCCESS(status)) {
if (IsDir) {
return ret;
}
}

if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
	if (!FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DELETE_ON_CLOSE)) {
		return ret;
	}
}

// Process requests with FileDispositionInformation, FileDispositionInformationEx  or file renames
if (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION) {
	switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass) {
	case FileRenameInformation:
	case FileRenameInformationEx:
	case FileDispositionInformation:
	case FileDispositionInformationEx:
	case FileRenameInformationBypassAccessCheck:
	case FileRenameInformationExBypassAccessCheck:
		break;

	default:
		return ret;
	}
}

PFLT_FILE_NAME_INFORMATION FileNameInfo = NULL;
if (FltObjects->FileObject) {
	status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &FileNameInfo);
	if (NT_SUCCESS(status)) {
		FltParseFileNameInformation(FileNameInfo);
		
		Data->IoStatus.Status = STATUS_ACCESS_DENIED;
		Data->IoStatus.Information = 0;

		ret = FLT_PREOP_COMPLETE;
		
		DbgPrint("[DENIED] %wZ\n", FileNameInfo->Name);
	}
	else {
		DbgPrint("[ERROR] Failed to get file name information!\n");
	}
}
else {
	DbgPrint("[ERROR] FltObjects->FileObject is NULL!\n");
}

return ret;

}**_

Yes. This is detect file deletion and its Ok.

FLT_PREOP_CALLBACK_STATUS badgirlFilterAntiDelete(Inout PFLT_CALLBACK_DATA Data, In PCFLT_RELATED_OBJECTS FltObjects, Flt_CompletionContext_Outptr PVOID* CompletionContext) {
UNREFERENCED_PARAMETER(CompletionContext);

PAGED_CODE();

FLT_PREOP_CALLBACK_STATUS ret = FLT_PREOP_SUCCESS_NO_CALLBACK;

// Ignore directories
BOOLEAN IsDir;
NTSTATUS status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDir);
if (NT_SUCCESS(status)) {
	if (IsDir) {
		return ret;
	}
}

// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-create
// When the system tries to open a handle to a file object,
// detect requests that have DELETE_ON_CLOSE in DesiredAccess
if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
	if (!FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DELETE_ON_CLOSE)) {
		return ret;
	}
}

// Process requests with FileDispositionInformation, FileDispositionInformationEx  or file renames
if (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION) {
	switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass) {
	case FileRenameInformation:
	case FileRenameInformationEx:
	case FileDispositionInformation:
	case FileDispositionInformationEx:
	case FileRenameInformationBypassAccessCheck:
	case FileRenameInformationExBypassAccessCheck:
		break;

	default:
		return ret;
	}
}

PFLT_FILE_NAME_INFORMATION FileNameInfo = NULL;
if (FltObjects->FileObject) {
	status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &FileNameInfo);
	if (NT_SUCCESS(status)) {
		FltParseFileNameInformation(FileNameInfo);
		
		Data->IoStatus.Status = STATUS_ACCESS_DENIED;
		Data->IoStatus.Information = 0;

		ret = FLT_PREOP_COMPLETE;
		
		DbgPrint("[DENIED] %wZ\n", FileNameInfo->Name);
	}
	else {
		DbgPrint("[ERROR] Failed to get file name information!\n");
	}
}
else {
	DbgPrint("[ERROR] FltObjects->FileObject is NULL!\n");
}

return ret;

}

  1. This code checks to see if it’s a directory and leaves if it is…Are you hitting that path?
  2. You can’t delete non-empty directories so you’ll see each file get deleted before the directory does

Yes. This is detect file deletion and it’s Ok.
*_
FLT_PREOP_CALLBACK_STATUS badgirlFilterAntiDelete(Inout PFLT_CALLBACK_DATA Data, In PCFLT_RELATED_OBJECTS FltObjects, Flt_CompletionContext_Outptr PVOID
CompletionContext) {
UNREFERENCED_PARAMETER(CompletionContext);

PAGED_CODE();

FLT_PREOP_CALLBACK_STATUS ret = FLT_PREOP_SUCCESS_NO_CALLBACK;

// Ignore directories
BOOLEAN IsDir;
NTSTATUS status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDir);
if (NT_SUCCESS(status)) {
	if (IsDir) {
		return ret;
	}
}

// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-create
// When the system tries to open a handle to a file object,
// detect requests that have DELETE_ON_CLOSE in DesiredAccess
if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
	if (!FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DELETE_ON_CLOSE)) {
		return ret;
	}
}

// Process requests with FileDispositionInformation, FileDispositionInformationEx  or file renames
if (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION) {
	switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass) {
	case FileRenameInformation:
	case FileRenameInformationEx:
	case FileDispositionInformation:
	case FileDispositionInformationEx:
	case FileRenameInformationBypassAccessCheck:
	case FileRenameInformationExBypassAccessCheck:
		break;

	default:
		return ret;
	}
}

PFLT_FILE_NAME_INFORMATION FileNameInfo = NULL;
if (FltObjects->FileObject) {
	status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &FileNameInfo);
	if (NT_SUCCESS(status)) {
		FltParseFileNameInformation(FileNameInfo);
		
		Data->IoStatus.Status = STATUS_ACCESS_DENIED;
		Data->IoStatus.Information = 0;

		ret = FLT_PREOP_COMPLETE;
		
		DbgPrint("[DENIED] %wZ\n", FileNameInfo->Name);
	}
	else {
		DbgPrint("[ERROR] Failed to get file name information!\n");
	}
}
else {
	DbgPrint("[ERROR] FltObjects->FileObject is NULL!\n");
}

return ret;

}_**

The code starts with this:

// Ignore directories
BOOLEAN IsDir;
NTSTATUS status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDir);
if (NT_SUCCESS(status)) {
    if (IsDir) {
        return ret;
    }
}

Are you hitting that code path?