Add files via upload

This commit is contained in:
87owo authored and GitHub committed 2026-01-01 17:41:40 +08:00
1 parent ba4369f829
commit 7f5eb34ac6
7 files changed
+304 -140

No files matched your search

+51 -26
View File
@@ -2,9 +2,8 @@
#include <fltKernel.h>
#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <dontuse.h>
#include <suppress.h>
#include <ntddscsi.h>
#include <ntstrsafe.h>
constexpr auto PYAS_PORT_NAME = L"\\PYAS_Output_Pipe";
constexpr auto MAX_PATH_LEN = 1024;
@@ -13,61 +12,70 @@ constexpr auto PYAS_POOL_TAG = 'SAYP';
#ifndef PROCESS_TERMINATE
#define PROCESS_TERMINATE (0x0001)
#endif
#ifndef PROCESS_CREATE_THREAD
#define PROCESS_CREATE_THREAD (0x0002)
#endif
#ifndef PROCESS_SET_SESSIONID
#define PROCESS_SET_SESSIONID (0x0004)
#endif
#ifndef PROCESS_VM_OPERATION
#define PROCESS_VM_OPERATION (0x0008)
#endif
#ifndef PROCESS_VM_READ
#define PROCESS_VM_READ (0x0010)
#endif
#ifndef PROCESS_VM_WRITE
#define PROCESS_VM_WRITE (0x0020)
#endif
#ifndef PROCESS_DUP_HANDLE
#define PROCESS_DUP_HANDLE (0x0040)
#endif
#ifndef PROCESS_CREATE_PROCESS
#define PROCESS_CREATE_PROCESS (0x0080)
#endif
#ifndef PROCESS_SET_QUOTA
#define PROCESS_SET_QUOTA (0x0100)
#endif
#ifndef PROCESS_SET_INFORMATION
#define PROCESS_SET_INFORMATION (0x0200)
#endif
#ifndef PROCESS_QUERY_INFORMATION
#define PROCESS_QUERY_INFORMATION (0x0400)
#endif
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME (0x0800)
#endif
#ifndef PROCESS_QUERY_LIMITED_INFORMATION
#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
#endif
#ifndef PROCESS_SET_LIMITED_INFORMATION
#define PROCESS_SET_LIMITED_INFORMATION (0x2000)
#ifndef POOL_FLAG_NON_PAGED
#define POOL_FLAG_NON_PAGED 0x0000000000000040UI64
#endif
#ifndef PROCESS_ALL_ACCESS
#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF)
#ifndef FSCTL_MANAGE_BYPASS_IO
#define FSCTL_MANAGE_BYPASS_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 188, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef enum _FS_BPIO_OPERATIONS {
FS_BPIO_OP_ENABLE = 1,
FS_BPIO_OP_DISABLE = 2,
FS_BPIO_OP_QUERY = 3,
FS_BPIO_OP_VOLUME_STACK_PAUSE = 4,
FS_BPIO_OP_VOLUME_STACK_RESUME = 5,
FS_BPIO_OP_STREAM_PAUSE = 6,
FS_BPIO_OP_STREAM_RESUME = 7,
FS_BPIO_OP_GET_INFO = 8
} FS_BPIO_OPERATIONS;
typedef struct _FS_BPIO_INPUT {
FS_BPIO_OPERATIONS Operation;
ULONG InFlags;
ULONGLONG Reserved1;
ULONGLONG Reserved2;
} FS_BPIO_INPUT, * PFS_BPIO_INPUT;
typedef struct _FS_BPIO_OUTPUT {
FS_BPIO_OPERATIONS Operation;
ULONG OutFlags;
ULONGLONG Reserved1;
ULONGLONG Reserved2;
NTSTATUS Status;
} FS_BPIO_OUTPUT, * PFS_BPIO_OUTPUT;
#endif
typedef struct _PYAS_MESSAGE {
@@ -86,12 +94,15 @@ typedef struct _DRIVER_DATA {
LARGE_INTEGER Cookie;
FAST_MUTEX PortMutex;
FAST_MUTEX TrackerMutex;
EX_RUNDOWN_REF PortRundown;
} DRIVER_DATA, * PDRIVER_DATA;
extern DRIVER_DATA GlobalData;
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreWrite(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_PreSetInfo(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectFile_FileSystemControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
FLT_PREOP_CALLBACK_STATUS ProtectBoot_PreDeviceControl(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext);
NTSTATUS InitializeProcessProtection();
@@ -111,4 +122,18 @@ BOOLEAN CheckFileExtensionRule(PCUNICODE_STRING FileName);
BOOLEAN CheckProtectedPathRule(PCUNICODE_STRING FileName);
BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Buffer, ULONG Length, BOOLEAN IsWrite);
NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path);
NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path, USHORT PathSize);
FORCEINLINE PVOID PyasAllocate(SIZE_T Size) {
#if (NTDDI_VERSION >= NTDDI_WIN10_VB)
return ExAllocatePool2(POOL_FLAG_NON_PAGED, Size, PYAS_POOL_TAG);
#else
PVOID Buffer = ExAllocatePoolWithTag(NonPagedPoolNx, Size, PYAS_POOL_TAG);
if (Buffer) RtlZeroMemory(Buffer, Size);
return Buffer;
#endif
}
FORCEINLINE VOID PyasFree(PVOID Ptr) {
if (Ptr) ExFreePoolWithTag(Ptr, PYAS_POOL_TAG);
}
+12 -1
View File
@@ -33,6 +33,8 @@ static NTSTATUS DriverUnload(FLT_FILTER_UNLOAD_FLAGS Flags) {
UninitializeRegistryProtection();
UninitializeProcessProtection();
ExWaitForRundownProtectionRelease(&GlobalData.PortRundown);
if (GlobalData.ServerPort) {
FltCloseCommunicationPort(GlobalData.ServerPort);
}
@@ -49,9 +51,13 @@ static NTSTATUS PortConnect(PFLT_PORT ClientPort, PVOID ServerPortCookie, PVOID
UNREFERENCED_PARAMETER(ConnectionPortCookie);
ExAcquireFastMutex(&GlobalData.PortMutex);
GlobalData.ClientPort = ClientPort;
GlobalData.PyasPid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
GlobalData.PyasProcess = PsGetCurrentProcess();
ExReInitializeRundownProtection(&GlobalData.PortRundown);
ExReleaseFastMutex(&GlobalData.PortMutex);
return STATUS_SUCCESS;
@@ -67,12 +73,15 @@ static VOID PortDisconnect(PVOID ConnectionCookie) {
GlobalData.PyasProcess = NULL;
}
ExReleaseFastMutex(&GlobalData.PortMutex);
ExWaitForRundownProtectionRelease(&GlobalData.PortRundown);
}
CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
{ IRP_MJ_CREATE, 0, ProtectFile_PreCreate, NULL },
{ IRP_MJ_WRITE, 0, ProtectFile_PreWrite, NULL },
{ IRP_MJ_SET_INFORMATION, 0, ProtectFile_PreWrite, NULL },
{ IRP_MJ_SET_INFORMATION, 0, ProtectFile_PreSetInfo, NULL },
{ IRP_MJ_FILE_SYSTEM_CONTROL, 0, ProtectFile_FileSystemControl, NULL },
{ IRP_MJ_DEVICE_CONTROL, 0, ProtectBoot_PreDeviceControl, NULL },
{ IRP_MJ_OPERATION_END }
};
@@ -106,6 +115,8 @@ extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING Reg
ExInitializeFastMutex(&GlobalData.PortMutex);
ExInitializeFastMutex(&GlobalData.TrackerMutex);
ExInitializeRundownProtection(&GlobalData.PortRundown);
status = FltRegisterFilter(DriverObject, &FilterRegistration, &GlobalData.FilterHandle);
if (!NT_SUCCESS(status)) return status;
+4 -1
View File
@@ -13,6 +13,8 @@ FLT_PREOP_CALLBACK_STATUS ProtectBoot_PreDeviceControl(PFLT_CALLBACK_DATA Data,
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
ULONG IoControlCode = Data->Iopb->Parameters.DeviceIoControl.Common.IoControlCode;
if (IoControlCode == IOCTL_DISK_SET_DRIVE_LAYOUT_EX ||
@@ -22,7 +24,8 @@ FLT_PREOP_CALLBACK_STATUS ProtectBoot_PreDeviceControl(PFLT_CALLBACK_DATA Data,
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid) && !IsInstallerProcess(Pid)) {
SendMessageToUser(4001, (ULONG)(ULONG_PTR)Pid, L"Disk_Wiper_Attempt");
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;
return FLT_PREOP_COMPLETE;
}
+151 -64
View File
@@ -14,14 +14,15 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_R
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)) {
if (!NT_SUCCESS(status) || !nameInfo) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
@@ -32,63 +33,112 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreCreate(PFLT_CALLBACK_DATA Data, PCFLT_R
}
FileName = nameInfo->Name;
if (!FileName.Buffer || FileName.Length == 0) {
goto cleanup;
}
if (FileName.Buffer) {
HANDLE Pid = PsGetCurrentProcessId();
BOOLEAN Trusted = IsProcessTrusted(Pid);
HANDLE Pid = PsGetCurrentProcessId();
BOOLEAN Trusted = IsProcessTrusted(Pid);
if (IsHoneyToken(&FileName)) {
if (!Trusted) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE)) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer);
FltReleaseFileNameInformation(nameInfo);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
return FLT_PREOP_COMPLETE;
}
if (IsHoneyToken(&FileName)) {
if (!Trusted) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE)) {
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) && !wcsstr(FileName.Buffer, L"Volume"))) {
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 (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &
(FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE | WRITE_DAC | WRITE_OWNER)) {
if (!Trusted && !IsInstallerProcess(Pid)) {
SendMessageToUser(4001, (ULONG)(ULONG_PTR)Pid, L"Disk_Wiper_Attempt");
FltReleaseFileNameInformation(nameInfo);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
return FLT_PREOP_COMPLETE;
}
if (!Trusted && !IsInstallerProcess(Pid)) {
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 | DELETE | WRITE_DAC | GENERIC_WRITE)) {
SendMessageToUser(2001, (ULONG)(ULONG_PTR)Pid, FileName.Buffer);
FltReleaseFileNameInformation(nameInfo);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
return FLT_PREOP_COMPLETE;
}
if (CheckProtectedPathRule(&FileName)) {
if (!Trusted) {
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess & (FILE_WRITE_DATA | DELETE | WRITE_DAC | GENERIC_WRITE)) {
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);
FltReleaseFileNameInformation(nameInfo);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
return FLT_PREOP_COMPLETE;
}
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;
}
}
}
}
FltReleaseFileNameInformation(nameInfo);
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;
NTSTATUS 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) || !nameInfo->Name.Buffer) {
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
if (CheckFileExtensionRule(&nameInfo->Name) || CheckProtectedPathRule(&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;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
}
}
if (nameInfo) {
FltReleaseFileNameInformation(nameInfo);
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
@@ -96,48 +146,51 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreWrite(PFLT_CALLBACK_DATA Data, PCFLT_RE
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
if (KeGetCurrentIrql() > APC_LEVEL) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (Data->RequestorMode == KernelMode) return FLT_PREOP_SUCCESS_NO_CALLBACK;
if (Data->Iopb->IrpFlags & (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO)) {
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;
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
FLT_PREOP_CALLBACK_STATUS callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
if (NT_SUCCESS(status)) {
if (NT_SUCCESS(status) && nameInfo) {
status = FltParseFileNameInformation(nameInfo);
if (NT_SUCCESS(status)) {
if (NT_SUCCESS(status) && nameInfo->Name.Buffer) {
if (CheckFileExtensionRule(&nameInfo->Name)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
PVOID WriteBuffer = NULL;
ULONG WriteLength = Data->Iopb->Parameters.Write.Length;
PVOID SystemBuffer = NULL;
PMDL Mdl = Data->Iopb->Parameters.Write.MdlAddress;
if (WriteLength > 0) {
if (Data->Iopb->Parameters.Write.MdlAddress) {
WriteBuffer = MmGetSystemAddressForMdlSafe(Data->Iopb->Parameters.Write.MdlAddress, NormalPagePriority | MdlMappingNoExecute);
}
else {
if (!Mdl) {
if (Data->Iopb->Parameters.Write.WriteBuffer && KeGetCurrentIrql() <= APC_LEVEL) {
if (NT_SUCCESS(FltLockUserBuffer(Data))) {
if (Data->Iopb->Parameters.Write.MdlAddress) {
WriteBuffer = MmGetSystemAddressForMdlSafe(Data->Iopb->Parameters.Write.MdlAddress, NormalPagePriority | MdlMappingNoExecute);
}
Mdl = Data->Iopb->Parameters.Write.MdlAddress;
}
}
}
if (WriteBuffer) {
if (CheckRansomActivity(Pid, &nameInfo->Name, WriteBuffer, WriteLength, TRUE)) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer);
FltReleaseFileNameInformation(nameInfo);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
return FLT_PREOP_COMPLETE;
if (Mdl) {
SystemBuffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority | MdlMappingNoExecute);
}
if (SystemBuffer) {
if (CheckRansomActivity(Pid, &nameInfo->Name, SystemBuffer, WriteLength, TRUE)) {
if (!IsInstallerProcess(Pid)) {
SendMessageToUser(5001, (ULONG)(ULONG_PTR)Pid, nameInfo->Name.Buffer, nameInfo->Name.Length);
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
callbackStatus = FLT_PREOP_COMPLETE;
}
}
}
}
@@ -145,5 +198,39 @@ FLT_PREOP_CALLBACK_STATUS ProtectFile_PreWrite(PFLT_CALLBACK_DATA Data, PCFLT_RE
}
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;
__try {
if (InputBuffer->Operation == FS_BPIO_OP_ENABLE) {
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
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;
FltReleaseFileNameInformation(nameInfo);
return FLT_PREOP_COMPLETE;
}
}
FltReleaseFileNameInformation(nameInfo);
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
+9 -4
View File
@@ -7,9 +7,9 @@ OB_OPERATION_REGISTRATION ObCallbacks[1];
static BOOLEAN IsSystemImage(PUNICODE_STRING FullImageName) {
if (!FullImageName || !FullImageName->Buffer) return FALSE;
if (wcsstr(FullImageName->Buffer, L"\\Windows\\System32\\") ||
wcsstr(FullImageName->Buffer, L"\\Windows\\SysWOW64\\") ||
wcsstr(FullImageName->Buffer, L"\\Windows\\WinSxS\\")) {
if (WildcardMatch(L"*\\Windows\\System32\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Windows\\SysWOW64\\*", FullImageName->Buffer, FullImageName->Length) ||
WildcardMatch(L"*\\Windows\\WinSxS\\*", FullImageName->Buffer, FullImageName->Length)) {
return TRUE;
}
return FALSE;
@@ -18,6 +18,7 @@ static BOOLEAN IsSystemImage(PUNICODE_STRING FullImageName) {
VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo) {
UNREFERENCED_PARAMETER(ImageInfo);
if (KeGetCurrentIrql() > APC_LEVEL) return;
if (!FullImageName || !FullImageName->Buffer) return;
if (ProcessId == (HANDLE)0) return;
@@ -25,7 +26,7 @@ VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INF
if (IsTargetProtected(ProcessId)) {
if (CheckFileExtensionRule(FullImageName)) {
SendMessageToUser(6001, (ULONG)(ULONG_PTR)ProcessId, FullImageName->Buffer);
SendMessageToUser(6001, (ULONG)(ULONG_PTR)ProcessId, FullImageName->Buffer, FullImageName->Length);
}
}
}
@@ -36,11 +37,15 @@ static OB_PREOP_CALLBACK_STATUS PreOpenProcess(PVOID RegistrationContext, POB_PR
if (OperationInformation->KernelHandle) return OB_PREOP_SUCCESS;
PEPROCESS TargetProcess = (PEPROCESS)OperationInformation->Object;
if (!TargetProcess) return OB_PREOP_SUCCESS;
HANDLE TargetPid = PsGetProcessId(TargetProcess);
HANDLE SourcePid = PsGetCurrentProcessId();
if (SourcePid == TargetPid) return OB_PREOP_SUCCESS;
if (IsProcessTrusted(SourcePid)) return OB_PREOP_SUCCESS;
// Low frequency path, acceptable to check installer here
if (IsInstallerProcess(SourcePid)) return OB_PREOP_SUCCESS;
BOOLEAN bProtected = IsTargetProtected(TargetPid);
+16 -9
View File
@@ -5,27 +5,34 @@ LARGE_INTEGER Cookie;
static NTSTATUS RegistryCallback(PVOID CallbackContext, PVOID Argument1, PVOID Argument2) {
UNREFERENCED_PARAMETER(CallbackContext);
if (KeGetCurrentIrql() > APC_LEVEL) return STATUS_SUCCESS;
REG_NOTIFY_CLASS Class = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
if (Class == RegNtPreSetValueKey || Class == RegNtPreDeleteKey || Class == RegNtPreCreateKey) {
REG_SET_VALUE_KEY_INFORMATION* Info = (REG_SET_VALUE_KEY_INFORMATION*)Argument2;
PCUNICODE_STRING KeyName;
PCUNICODE_STRING KeyName = NULL;
if (!NT_SUCCESS(CmCallbackGetKeyObjectIDEx(&Cookie, Info->Object, NULL, &KeyName, 0))) {
return STATUS_SUCCESS;
}
if (CheckRegistryRule(KeyName)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
if (!IsInstallerProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, KeyName->Buffer);
CmCallbackReleaseKeyObjectIDEx(KeyName);
return STATUS_ACCESS_DENIED;
if (KeyName && KeyName->Buffer) {
if (CheckRegistryRule(KeyName)) {
HANDLE Pid = PsGetCurrentProcessId();
if (!IsProcessTrusted(Pid)) {
if (!IsInstallerProcess(Pid)) {
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, KeyName->Buffer, KeyName->Length);
CmCallbackReleaseKeyObjectIDEx(KeyName);
return STATUS_ACCESS_DENIED;
}
}
}
}
CmCallbackReleaseKeyObjectIDEx(KeyName);
if (KeyName) {
CmCallbackReleaseKeyObjectIDEx(KeyName);
}
}
return STATUS_SUCCESS;
}
+61 -35
View File
@@ -2,7 +2,7 @@
constexpr auto MAX_TRACKERS = 64;
constexpr auto RANSOM_TIME_WINDOW_MS = 3000;
constexpr auto RANSOM_COUNT_THRESHOLD = 3;
constexpr auto RANSOM_COUNT_THRESHOLD = 5;
constexpr auto HIGH_ENTROPY_THRESHOLD = 15;
typedef struct _RANSOM_TRACKER {
@@ -16,7 +16,11 @@ RANSOM_TRACKER RansomTrackers[MAX_TRACKERS];
static BOOLEAN HasSuffix(PCUNICODE_STRING String, PCWSTR Suffix) {
if (!String || !String->Buffer || !Suffix) return FALSE;
SIZE_T SuffixLenBytes = wcslen(Suffix) * sizeof(WCHAR);
SIZE_T SuffixLenBytes = 0;
while (Suffix[SuffixLenBytes / sizeof(WCHAR)] != L'\0') {
SuffixLenBytes += sizeof(WCHAR);
}
if (String->Length < SuffixLenBytes) return FALSE;
UNICODE_STRING SuffixPart{};
@@ -31,11 +35,13 @@ static BOOLEAN HasSuffix(PCUNICODE_STRING String, PCWSTR Suffix) {
}
BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes) {
if (!Pattern || !String) return FALSE;
PCWSTR mp = NULL;
PCWSTR cp = NULL;
PCWSTR StringEnd = (PCWSTR)((PUCHAR)String + StringLengthBytes);
while (String < StringEnd && *String) {
while ((PUCHAR)String < (PUCHAR)StringEnd) {
WCHAR pChar = *Pattern;
WCHAR sChar = *String;
@@ -58,7 +64,7 @@ BOOLEAN WildcardMatch(PCWSTR Pattern, PCWSTR String, USHORT StringLengthBytes) {
}
while (*Pattern == L'*') Pattern++;
return !*Pattern && (String >= StringEnd || !*String);
return !*Pattern && ((PUCHAR)String >= (PUCHAR)StringEnd);
}
const PCWSTR RegistryBlockList[] = {
@@ -212,23 +218,29 @@ BOOLEAN IsTargetProtected(HANDLE ProcessId) {
}
BOOLEAN IsInstallerProcess(HANDLE ProcessId) {
if (KeGetCurrentIrql() > APC_LEVEL) return FALSE;
NTSTATUS status;
BOOLEAN isTrusted = FALSE;
PEPROCESS Process = NULL;
PUNICODE_STRING imageFileName = NULL;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (!NT_SUCCESS(status)) return FALSE;
PUNICODE_STRING imageFileName;
status = SeLocateProcessImageName(Process, &imageFileName);
if (NT_SUCCESS(status) && imageFileName) {
for (int i = 0; i < sizeof(TrustedInstallerNames) / sizeof(TrustedInstallerNames[0]); i++) {
if (HasSuffix(imageFileName, TrustedInstallerNames[i])) {
isTrusted = TRUE;
break;
if (imageFileName->Buffer) {
for (int i = 0; i < sizeof(TrustedInstallerNames) / sizeof(TrustedInstallerNames[0]); i++) {
if (HasSuffix(imageFileName, TrustedInstallerNames[i])) {
isTrusted = TRUE;
break;
}
}
}
ExFreePool(imageFileName);
}
ObDereferenceObject(Process);
@@ -329,6 +341,11 @@ BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Bu
ExAcquireFastMutex(&GlobalData.TrackerMutex);
if (IsWrite && !SuspiciousWrite) {
ExReleaseFastMutex(&GlobalData.TrackerMutex);
return FALSE;
}
PRANSOM_TRACKER Tracker = NULL;
PRANSOM_TRACKER EmptySlot = NULL;
@@ -365,7 +382,7 @@ BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Bu
ULONG Weight = 1;
if (IsWrite) {
Weight = SuspiciousWrite ? RANSOM_COUNT_THRESHOLD : 1;
Weight = SuspiciousWrite ? 2 : 1;
}
Tracker->ActivityCount += Weight;
@@ -378,38 +395,47 @@ BOOLEAN CheckRansomActivity(HANDLE ProcessId, PUNICODE_STRING FileName, PVOID Bu
return Result;
}
NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path) {
PFLT_PORT LocalClientPort = NULL;
ExAcquireFastMutex(&GlobalData.PortMutex);
LocalClientPort = GlobalData.ClientPort;
ExReleaseFastMutex(&GlobalData.PortMutex);
if (!LocalClientPort) {
return STATUS_PORT_DISCONNECTED;
}
NTSTATUS SendMessageToUser(ULONG Code, ULONG Pid, PWCHAR Path, USHORT PathSize) {
if (KeGetCurrentIrql() > APC_LEVEL) return STATUS_UNSUCCESSFUL;
PYAS_MESSAGE msg;
RtlZeroMemory(&msg, sizeof(msg));
msg.MessageCode = Code;
msg.ProcessId = Pid;
if (Path) {
ULONG CopyLen = 0;
while (CopyLen < MAX_PATH_LEN - 1 && Path[CopyLen] != L'\0') {
__try {
msg.Path[CopyLen] = Path[CopyLen];
CopyLen++;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
break;
}
if (Path && PathSize > 0) {
size_t MaxSize = sizeof(msg.Path) - sizeof(WCHAR);
size_t BytesToCopy = PathSize;
if (BytesToCopy > MaxSize) {
BytesToCopy = MaxSize;
}
msg.Path[CopyLen] = L'\0';
__try {
RtlCopyMemory(msg.Path, Path, BytesToCopy);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return STATUS_ACCESS_VIOLATION;
}
msg.Path[BytesToCopy / sizeof(WCHAR)] = L'\0';
}
LARGE_INTEGER timeout{};
timeout.QuadPart = -(5 * 10000);
return FltSendMessage(GlobalData.FilterHandle, &LocalClientPort, &msg, sizeof(msg), NULL, NULL, &timeout);
if (!ExAcquireRundownProtection(&GlobalData.PortRundown)) {
return STATUS_PORT_DISCONNECTED;
}
NTSTATUS status = STATUS_SUCCESS;
if (GlobalData.ClientPort) {
LARGE_INTEGER timeout{};
timeout.QuadPart = -(5 * 10000);
PFLT_PORT Port = GlobalData.ClientPort;
status = FltSendMessage(GlobalData.FilterHandle, &Port, &msg, sizeof(msg), NULL, NULL, &timeout);
}
else {
status = STATUS_PORT_DISCONNECTED;
}
ExReleaseRundownProtection(&GlobalData.PortRundown);
return status;
}