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;
}
- This code checks to see if it’s a directory and leaves if it is…Are you hitting that path?
- 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?