310 lines
12 KiB
C
310 lines
12 KiB
C
#include <ntifs.h>
|
|
#include "DriverEntry.h"
|
|
#include "ProtectRules.h"
|
|
|
|
LARGE_INTEGER g_CmRegHandle;
|
|
PDEVICE_OBJECT g_ControlDeviceObject;
|
|
KSPIN_LOCK g_ProtectLock;
|
|
FAST_MUTEX HookMutex;
|
|
PDRIVER_OBJECT DiskDrvObj = NULL;
|
|
KEVENT g_LogDrainEvent;
|
|
BOOLEAN g_Unloading = FALSE;
|
|
BOOLEAN g_CmRegActive = FALSE;
|
|
EX_RUNDOWN_REF g_Rundown;
|
|
PDEVICE_OBJECT g_GuardDevice = NULL;
|
|
|
|
PDEVICE_OBJECT g_MbrFilterTargets[MAX_MBR_TARGETS] = { 0 };
|
|
ULONG g_MbrFilterCount = 0;
|
|
|
|
volatile LONG g_LogWorkCount = 0;
|
|
static UNICODE_STRING g_DeviceName;
|
|
static WCHAR g_DeviceNameBuf[64];
|
|
static UNICODE_STRING g_SymLink = RTL_CONSTANT_STRING(L"\\??\\PYAS_Driver");
|
|
static BOOLEAN g_SymLinkCreated = FALSE;
|
|
|
|
static NTSTATUS CombinedDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
if (DeviceObject == g_ControlDeviceObject) {
|
|
PIO_STACK_LOCATION s = IoGetCurrentIrpStackLocation(Irp);
|
|
if (s->MajorFunction == IRP_MJ_CREATE || s->MajorFunction == IRP_MJ_CLOSE || s->MajorFunction == IRP_MJ_CLEANUP) {
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
{
|
|
PIO_STACK_LOCATION s = IoGetCurrentIrpStackLocation(Irp);
|
|
if (s->MajorFunction == IRP_MJ_PNP) {
|
|
PDEVICE_OBJECT lower = (PDEVICE_OBJECT)DeviceObject->DeviceExtension;
|
|
if (s->MinorFunction == IRP_MN_REMOVE_DEVICE) {
|
|
NTSTATUS st;
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
st = lower ? IoCallDriver(lower, Irp) : STATUS_SUCCESS;
|
|
if (lower) IoDetachDevice(lower);
|
|
IoDeleteDevice(DeviceObject);
|
|
return st;
|
|
}
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return IoCallDriver((PDEVICE_OBJECT)DeviceObject->DeviceExtension, Irp);
|
|
}
|
|
}
|
|
return FileProtectDispatch(DeviceObject, Irp);
|
|
}
|
|
|
|
static NTSTATUS AttachDiskFilters(PDRIVER_OBJECT DriverObject)
|
|
{
|
|
UNICODE_STRING name = RTL_CONSTANT_STRING(L"\\Driver\\Disk");
|
|
UNICODE_STRING sym = RTL_CONSTANT_STRING(L"IoDriverObjectType");
|
|
POBJECT_TYPE* pType = (POBJECT_TYPE*)MmGetSystemRoutineAddress(&sym);
|
|
|
|
if (!pType || !*pType)
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
NTSTATUS status = ObReferenceObjectByName(&name, OBJ_CASE_INSENSITIVE, NULL, 0, *pType, KernelMode, NULL, (PVOID*)&DiskDrvObj);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
ULONG done = 0;
|
|
status = IoEnumerateDeviceObjectList(DiskDrvObj, NULL, 0, &done);
|
|
if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS) {
|
|
ObDereferenceObject(DiskDrvObj);
|
|
DiskDrvObj = NULL;
|
|
return status;
|
|
}
|
|
PDEVICE_OBJECT* list = ExAllocatePool2(POOL_FLAG_NON_PAGED, done * sizeof(PDEVICE_OBJECT), 'dskT');
|
|
if (!list) {
|
|
ObDereferenceObject(DiskDrvObj);
|
|
DiskDrvObj = NULL;
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
status = IoEnumerateDeviceObjectList(DiskDrvObj, list, done * sizeof(PDEVICE_OBJECT), &done);
|
|
if (!NT_SUCCESS(status)) {
|
|
ExFreePool2(list, 'dskT', NULL, 0);
|
|
ObDereferenceObject(DiskDrvObj);
|
|
DiskDrvObj = NULL;
|
|
return status;
|
|
}
|
|
for (ULONG i = 0; i < done && g_MbrFilterCount < MAX_MBR_TARGETS; ++i) {
|
|
PDEVICE_OBJECT lower = list[i], filter, attached = NULL;
|
|
status = IoCreateDevice(DriverObject, 0, NULL, lower->DeviceType, lower->Characteristics, FALSE, &filter);
|
|
if (!NT_SUCCESS(status))
|
|
continue;
|
|
|
|
filter->Flags |= (lower->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE));
|
|
status = IoAttachDeviceToDeviceStackSafe(filter, lower, &attached);
|
|
if (!NT_SUCCESS(status) || !attached) {
|
|
IoDeleteDevice(filter);
|
|
continue;
|
|
}
|
|
filter->StackSize = lower->StackSize + 1;
|
|
filter->AlignmentRequirement = lower->AlignmentRequirement;
|
|
filter->DeviceExtension = attached;
|
|
filter->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
g_MbrFilterTargets[g_MbrFilterCount++] = filter;
|
|
}
|
|
for (ULONG i = 0; i < done; ++i)
|
|
ObDereferenceObject(list[i]);
|
|
ExFreePool2(list, 'dskT', NULL, 0);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static NTSTATUS AttachFsFilters(PDRIVER_OBJECT DriverObject)
|
|
{
|
|
UNICODE_STRING symDev = RTL_CONSTANT_STRING(L"IoDeviceObjectType");
|
|
POBJECT_TYPE* pDevType = (POBJECT_TYPE*)MmGetSystemRoutineAddress(&symDev);
|
|
if (!pDevType || !*pDevType)
|
|
return STATUS_NOT_SUPPORTED;
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
for (ULONG i = 0; g_AttachDisk[i] && g_MbrFilterCount < MAX_MBR_TARGETS; ++i) {
|
|
UNICODE_STRING name;
|
|
RtlInitUnicodeString(&name, g_AttachDisk[i]);
|
|
PDEVICE_OBJECT fsCtl = NULL;
|
|
|
|
status = ObReferenceObjectByName(&name, OBJ_CASE_INSENSITIVE, NULL, 0, *pDevType, KernelMode, NULL, (PVOID*)&fsCtl);
|
|
if (!NT_SUCCESS(status) || !fsCtl)
|
|
continue;
|
|
|
|
PDRIVER_OBJECT fsDrv = fsCtl->DriverObject;
|
|
if (fsDrv) {
|
|
ULONG need = 0;
|
|
|
|
status = IoEnumerateDeviceObjectList(fsDrv, NULL, 0, &need);
|
|
if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_SUCCESS) {
|
|
PDEVICE_OBJECT* list = (PDEVICE_OBJECT*)ExAllocatePool2(POOL_FLAG_NON_PAGED, need * sizeof(PDEVICE_OBJECT), 'fsTA');
|
|
if (list) {
|
|
|
|
status = IoEnumerateDeviceObjectList(fsDrv, list, need * sizeof(PDEVICE_OBJECT), &need);
|
|
if (NT_SUCCESS(status)) {
|
|
for (ULONG j = 0; j < need && g_MbrFilterCount < MAX_MBR_TARGETS; ++j) {
|
|
|
|
PDEVICE_OBJECT lower = list[j], filter, attached = NULL;
|
|
NTSTATUS s2 = IoCreateDevice(DriverObject, 0, NULL, lower->DeviceType, lower->Characteristics, FALSE, &filter);
|
|
if (!NT_SUCCESS(s2))
|
|
continue;
|
|
|
|
filter->Flags |= (lower->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE));
|
|
s2 = IoAttachDeviceToDeviceStackSafe(filter, lower, &attached);
|
|
if (!NT_SUCCESS(s2) || !attached) {
|
|
IoDeleteDevice(filter);
|
|
continue;
|
|
}
|
|
filter->StackSize = lower->StackSize + 1;
|
|
filter->AlignmentRequirement = lower->AlignmentRequirement;
|
|
filter->DeviceExtension = attached;
|
|
filter->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
g_MbrFilterTargets[g_MbrFilterCount++] = filter;
|
|
}
|
|
}
|
|
ExFreePool2(list, 'fsTA', NULL, 0);
|
|
}
|
|
}
|
|
}
|
|
ObDereferenceObject(fsCtl);
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|
{
|
|
UNREFERENCED_PARAMETER(RegistryPath);
|
|
|
|
KeInitializeSpinLock(&g_ProtectLock);
|
|
ExInitializeFastMutex(&HookMutex);
|
|
KeInitializeEvent(&g_LogDrainEvent, NotificationEvent, TRUE);
|
|
g_Unloading = FALSE;
|
|
g_CmRegActive = FALSE;
|
|
|
|
InterlockedExchange(&g_LogWorkCount, 0);
|
|
ExInitializeRundownProtection(&g_Rundown);
|
|
{
|
|
UNICODE_STRING guardName = RTL_CONSTANT_STRING(L"\\Device\\PYAS_Driver_Guard");
|
|
NTSTATUS gs = IoCreateDevice(DriverObject, 0, &guardName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_GuardDevice);
|
|
if (!NT_SUCCESS(gs))
|
|
return STATUS_DEVICE_BUSY;
|
|
}
|
|
{
|
|
LARGE_INTEGER t = KeQueryPerformanceCounter(NULL);
|
|
g_DeviceName.Buffer = g_DeviceNameBuf;
|
|
g_DeviceName.MaximumLength = sizeof(g_DeviceNameBuf);
|
|
RtlStringCchPrintfW(g_DeviceName.Buffer, RTL_NUMBER_OF(g_DeviceNameBuf), L"\\Device\\PYAS_Driver_%p_%I64x", DriverObject, t.QuadPart);
|
|
g_DeviceName.Length = (USHORT)(wcslen(g_DeviceName.Buffer) * sizeof(WCHAR));
|
|
}
|
|
NTSTATUS status = IoCreateDevice(DriverObject, 0, &g_DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_ControlDeviceObject);
|
|
if (!NT_SUCCESS(status))
|
|
return status;
|
|
|
|
DriverObject->DriverUnload = DriverUnload;
|
|
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
|
|
DriverObject->MajorFunction[i] = CombinedDispatch;
|
|
|
|
DriverObject->Flags |= 0x20;
|
|
|
|
g_ControlDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
IoDeleteSymbolicLink(&g_SymLink);
|
|
{
|
|
UINT i = 0;
|
|
for (; i < 50; ++i) {
|
|
status = IoCreateSymbolicLink(&g_SymLink, &g_DeviceName);
|
|
if (NT_SUCCESS(status))
|
|
break;
|
|
|
|
LARGE_INTEGER d = { 0 };
|
|
d.QuadPart = -10LL * 1000LL * 10LL;
|
|
KeDelayExecutionThread(KernelMode, FALSE, &d);
|
|
IoDeleteSymbolicLink(&g_SymLink);
|
|
}
|
|
if (!NT_SUCCESS(status)) {
|
|
IoDeleteDevice(g_ControlDeviceObject);
|
|
g_ControlDeviceObject = NULL;
|
|
if (g_GuardDevice) { IoDeleteDevice(g_GuardDevice); g_GuardDevice = NULL; }
|
|
return status;
|
|
}
|
|
}
|
|
g_SymLinkCreated = TRUE;
|
|
{
|
|
static WCHAR regAltBuf[32];
|
|
static UNICODE_STRING regAlt;
|
|
LARGE_INTEGER t = KeQueryPerformanceCounter(NULL);
|
|
RtlStringCchPrintfW(regAltBuf, RTL_NUMBER_OF(regAltBuf), L"385100.%I64x", t.QuadPart);
|
|
RtlInitUnicodeString(®Alt, regAltBuf);
|
|
|
|
status = CmRegisterCallbackEx(RegistryProtectCallback, ®Alt, DriverObject, NULL, &g_CmRegHandle, NULL);
|
|
if (NT_SUCCESS(status))
|
|
g_CmRegActive = TRUE;
|
|
}
|
|
InitImageProtect();
|
|
InitInjectProtect();
|
|
InitRemoteProtect();
|
|
InitScreenProtect();
|
|
{
|
|
NTSTATUS ps = InitProcessProtect();
|
|
if (!NT_SUCCESS(ps)) {
|
|
CHAR b[64] = { 0 };
|
|
RtlStringCchPrintfA(b, RTL_NUMBER_OF(b), "PROC_INIT | 0x%08X", ps);
|
|
SendPipeLog(b, strlen(b));
|
|
}
|
|
else {
|
|
static CHAR ok[] = "PROC_INIT | 0x00000000";
|
|
SendPipeLog(ok, sizeof(ok) - 1);
|
|
}
|
|
}
|
|
AttachFsFilters(DriverObject);
|
|
AttachDiskFilters(DriverObject);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
|
|
{
|
|
UNREFERENCED_PARAMETER(DriverObject);
|
|
|
|
g_Unloading = TRUE;
|
|
if (g_SymLinkCreated) {
|
|
IoDeleteSymbolicLink(&g_SymLink);
|
|
g_SymLinkCreated = FALSE;
|
|
}
|
|
if (g_CmRegActive) {
|
|
CmUnRegisterCallback(g_CmRegHandle);
|
|
g_CmRegActive = FALSE;
|
|
}
|
|
UninitInjectProtect();
|
|
UninitImageProtect();
|
|
UninitRemoteProtect();
|
|
UninitScreenProtect();
|
|
UninitProcessProtect();
|
|
|
|
ExWaitForRundownProtectionRelease(&g_Rundown);
|
|
if (InterlockedCompareExchange((volatile LONG*)&g_LogWorkCount, 0, 0) != 0) {
|
|
KeWaitForSingleObject(&g_LogDrainEvent, Executive, KernelMode, FALSE, NULL);
|
|
}
|
|
if (InterlockedCompareExchange(&g_LogWorkCount, 0, 0) != 0) {
|
|
KeResetEvent(&g_LogDrainEvent);
|
|
while (InterlockedCompareExchange(&g_LogWorkCount, 0, 0) != 0)
|
|
KeWaitForSingleObject(&g_LogDrainEvent, Executive, KernelMode, FALSE, NULL);
|
|
}
|
|
for (ULONG i = 0; i < g_MbrFilterCount; ++i) {
|
|
if (g_MbrFilterTargets[i]) {
|
|
IoDetachDevice((PDEVICE_OBJECT)g_MbrFilterTargets[i]->DeviceExtension);
|
|
IoDeleteDevice(g_MbrFilterTargets[i]);
|
|
g_MbrFilterTargets[i] = NULL;
|
|
}
|
|
}
|
|
g_MbrFilterCount = 0;
|
|
if (DiskDrvObj) {
|
|
ObDereferenceObject(DiskDrvObj);
|
|
DiskDrvObj = NULL;
|
|
}
|
|
if (g_ControlDeviceObject) {
|
|
IoDeleteDevice(g_ControlDeviceObject);
|
|
g_ControlDeviceObject = NULL;
|
|
}
|
|
if (g_GuardDevice) {
|
|
IoDeleteDevice(g_GuardDevice);
|
|
g_GuardDevice = NULL;
|
|
}
|
|
} |