293 lines
12 KiB
C++
293 lines
12 KiB
C++
#include "DriverCommon.h"
|
|
|
|
static BOOLEAN IsHoneyToken(PUNICODE_STRING Path) {
|
|
if (!Path || !Path->Buffer) return FALSE;
|
|
if (WildcardMatch(L"*PYAS_Honey*", Path->Buffer, Path->Length) ||
|
|
WildcardMatch(L"*Backup_Secret*", Path->Buffer, Path->Length)) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
|
|
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
|
|
UNICODE_STRING FileName = { 0 };
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
FLT_PREOP_CALLBACK_STATUS callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
|
|
if (!NT_SUCCESS(status) || !nameInfo) {
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
status = FltParseFileNameInformation(nameInfo);
|
|
if (!NT_SUCCESS(status)) {
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
FileName = nameInfo->Name;
|
|
if (!FileName.Buffer || FileName.Length == 0) {
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
HANDLE Pid = PsGetCurrentProcessId();
|
|
BOOLEAN Trusted = IsProcessTrusted(Pid);
|
|
|
|
ULONG CreateDisposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF;
|
|
BOOLEAN IsCreateAction = (CreateDisposition == FILE_CREATE ||
|
|
CreateDisposition == FILE_SUPERSEDE ||
|
|
CreateDisposition == FILE_OVERWRITE ||
|
|
CreateDisposition == FILE_OVERWRITE_IF ||
|
|
CreateDisposition == FILE_OPEN_IF);
|
|
|
|
if (IsHoneyToken(&FileName)) {
|
|
if (!Trusted) {
|
|
if ((Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE)) || IsCreateAction) {
|
|
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer, FileName.Length);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (WildcardMatch(L"\\Device\\PhysicalDrive*", FileName.Buffer, FileName.Length) ||
|
|
(WildcardMatch(L"\\Device\\Harddisk*", FileName.Buffer, FileName.Length) && !WildcardMatch(L"*Volume*", FileName.Buffer, FileName.Length))) {
|
|
|
|
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &
|
|
(FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE | WRITE_DAC | WRITE_OWNER)) {
|
|
|
|
if (!Trusted) {
|
|
UNICODE_STRING MsgStr = RTL_CONSTANT_STRING(L"Disk_Wiper_Attempt");
|
|
SendMessageToUser(4001, (ULONG)(ULONG_PTR)Pid, MsgStr.Buffer, MsgStr.Length);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CheckProtectedPathRule(&FileName)) {
|
|
if (!Trusted) {
|
|
if ((Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &
|
|
(FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | DELETE | WRITE_DAC | GENERIC_WRITE)) || IsCreateAction) {
|
|
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer, FileName.Length);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CheckFileExtensionRule(&FileName)) {
|
|
if (!Trusted) {
|
|
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (DELETE | FILE_DELETE_CHILD)) {
|
|
if (CheckRansomActivity(Pid, &FileName, NULL, 0, FALSE)) {
|
|
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer, FileName.Length);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (nameInfo) {
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
}
|
|
return callbackStatus;
|
|
}
|
|
|
|
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreSetInfo(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
|
|
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
FILE_INFORMATION_CLASS infoClass = Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
|
|
|
|
if (infoClass != FileDispositionInformation &&
|
|
infoClass != FileRenameInformation &&
|
|
infoClass != FileRenameInformationEx) {
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
|
|
FLT_PREOP_CALLBACK_STATUS callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
|
|
|
|
if (!NT_SUCCESS(status) || !nameInfo) goto cleanup;
|
|
|
|
status = FltParseFileNameInformation(nameInfo);
|
|
if (!NT_SUCCESS(status) || !nameInfo->Name.Buffer) goto cleanup;
|
|
|
|
HANDLE Pid = PsGetCurrentProcessId();
|
|
if (!IsProcessTrusted(Pid)) {
|
|
if (CheckProtectedPathRule(&nameInfo->Name)) {
|
|
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (CheckFileExtensionRule(&nameInfo->Name)) {
|
|
if (CheckRansomActivity(Pid, &nameInfo->Name, NULL, 0, FALSE)) {
|
|
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (nameInfo) {
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
}
|
|
return callbackStatus;
|
|
}
|
|
|
|
FLT_PREOP_CALLBACK_STATUS ProtectFile_SetSecurity(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
|
|
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
|
|
FLT_PREOP_CALLBACK_STATUS callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
|
|
|
|
if (!NT_SUCCESS(status) || !nameInfo) goto cleanup;
|
|
|
|
status = FltParseFileNameInformation(nameInfo);
|
|
if (!NT_SUCCESS(status) || !nameInfo->Name.Buffer) goto cleanup;
|
|
|
|
SECURITY_INFORMATION SecurityInfo = Data->Iopb->Parameters.SetSecurity.SecurityInformation;
|
|
|
|
if (SecurityInfo & (OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) {
|
|
if (CheckProtectedPathRule(&nameInfo->Name)) {
|
|
HANDLE Pid = PsGetCurrentProcessId();
|
|
if (!IsProcessTrusted(Pid)) {
|
|
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (nameInfo) {
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
}
|
|
return callbackStatus;
|
|
}
|
|
|
|
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreWrite(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
|
|
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if (Data->Iopb->IrpFlags & (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE)) {
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
ULONG WriteLength = Data->Iopb->Parameters.Write.Length;
|
|
if (WriteLength == 0) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
|
|
FLT_PREOP_CALLBACK_STATUS callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
|
|
|
|
if (!NT_SUCCESS(status) || !nameInfo) goto cleanup;
|
|
|
|
status = FltParseFileNameInformation(nameInfo);
|
|
if (!NT_SUCCESS(status) || !nameInfo->Name.Buffer) goto cleanup;
|
|
|
|
if (CheckFileExtensionRule(&nameInfo->Name)) {
|
|
HANDLE Pid = PsGetCurrentProcessId();
|
|
|
|
if (!IsProcessTrusted(Pid)) {
|
|
PVOID SystemBuffer = NULL;
|
|
PMDL Mdl = Data->Iopb->Parameters.Write.MdlAddress;
|
|
|
|
if (!Mdl) {
|
|
if (Data->Iopb->Parameters.Write.WriteBuffer && KeGetCurrentIrql() <= APC_LEVEL) {
|
|
if (NT_SUCCESS(FltLockUserBuffer(Data))) {
|
|
Mdl = Data->Iopb->Parameters.Write.MdlAddress;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Mdl) {
|
|
SystemBuffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority | MdlMappingNoExecute);
|
|
}
|
|
|
|
if (SystemBuffer) {
|
|
if (CheckRansomActivity(Pid, &nameInfo->Name, SystemBuffer, WriteLength, TRUE)) {
|
|
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (nameInfo) {
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
}
|
|
return callbackStatus;
|
|
}
|
|
|
|
FLT_PREOP_CALLBACK_STATUS ProtectFile_FileSystemControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) {
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
|
|
if (Data->Iopb->Parameters.FileSystemControl.Common.FsControlCode != FSCTL_MANAGE_BYPASS_IO) {
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
PFS_BPIO_INPUT InputBuffer = (PFS_BPIO_INPUT)Data->Iopb->Parameters.FileSystemControl.Neither.InputBuffer;
|
|
if (!InputBuffer) return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
FS_BPIO_OPERATIONS Operation;
|
|
|
|
__try {
|
|
Operation = InputBuffer->Operation;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
|
|
FLT_PREOP_CALLBACK_STATUS callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if (Operation == FS_BPIO_OP_ENABLE) {
|
|
if (NT_SUCCESS(FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo)) && nameInfo) {
|
|
if (NT_SUCCESS(FltParseFileNameInformation(nameInfo))) {
|
|
if (CheckFileExtensionRule(&nameInfo->Name) || CheckProtectedPathRule(&nameInfo->Name)) {
|
|
Data->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
callbackStatus = FLT_PREOP_COMPLETE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nameInfo) {
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
}
|
|
return callbackStatus;
|
|
} |