mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
fixed "don't allow kernel-mode to bypass protection" by allowing rule creators to bypass the rules
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1296 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
Binary file not shown.
@@ -81,10 +81,16 @@
|
||||
#define KPH_TIMEOUT_TO_SEC ((LONGLONG) 1 * 10 * 1000 * 1000)
|
||||
#define KPH_REL_TIMEOUT_IN_SEC(Time) (Time * -1 * KPH_TIMEOUT_TO_SEC)
|
||||
|
||||
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
|
||||
VOID DriverUnload(PDRIVER_OBJECT DriverObject);
|
||||
NTSTATUS KphDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
NTSTATUS KphDispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
NTSTATUS KphDispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
NTSTATUS KphUnsupported(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
|
||||
BOOLEAN AddClientEntry(HANDLE ProcessId);
|
||||
BOOLEAN IsProcessClient(HANDLE ProcessId);
|
||||
BOOLEAN RemoveClientEntry(HANDLE ProcessId);
|
||||
|
||||
#endif
|
||||
@@ -38,6 +38,7 @@ typedef struct _KPH_PROCESS_ENTRY
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
PEPROCESS Process;
|
||||
PEPROCESS CreatorProcess;
|
||||
HANDLE Tag;
|
||||
LOGICAL AllowKernelMode;
|
||||
ACCESS_MASK ProcessAllowMask;
|
||||
|
||||
@@ -28,6 +28,17 @@
|
||||
#include "include/ps.h"
|
||||
#include "include/version.h"
|
||||
|
||||
typedef struct _KPH_CLIENT_ENTRY
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
HANDLE ProcessId;
|
||||
} KPH_CLIENT_ENTRY, *PKPH_CLIENT_ENTRY;
|
||||
|
||||
LIST_ENTRY ClientListHead;
|
||||
KSPIN_LOCK ClientListLock;
|
||||
NPAGED_LOOKASIDE_LIST ClientLookasideList;
|
||||
static BOOLEAN ProtectionInitialized = FALSE;
|
||||
|
||||
#pragma alloc_text(PAGE, KphDispatchCreate)
|
||||
#pragma alloc_text(PAGE, KphDispatchClose)
|
||||
#pragma alloc_text(PAGE, KphDispatchDeviceControl)
|
||||
@@ -35,25 +46,6 @@
|
||||
#pragma alloc_text(PAGE, KphUnsupported)
|
||||
#pragma pack(1)
|
||||
|
||||
static BOOLEAN ProtectionInitialized = FALSE;
|
||||
|
||||
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
UNICODE_STRING dosDeviceName;
|
||||
|
||||
RtlInitUnicodeString(&dosDeviceName, KPH_DEVICE_DOS_NAME);
|
||||
IoDeleteSymbolicLink(&dosDeviceName);
|
||||
IoDeleteDevice(DriverObject->DeviceObject);
|
||||
|
||||
if (ProtectionInitialized)
|
||||
{
|
||||
KphProtectDeinit();
|
||||
ProtectionInitialized = FALSE;
|
||||
}
|
||||
|
||||
dprintf("Driver unloaded\n");
|
||||
}
|
||||
|
||||
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
@@ -78,6 +70,19 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
/* Initialize client list structures */
|
||||
InitializeListHead(&ClientListHead);
|
||||
KeInitializeSpinLock(&ClientListLock);
|
||||
ExInitializeNPagedLookasideList(
|
||||
&ClientLookasideList,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
sizeof(KPH_CLIENT_ENTRY),
|
||||
KPH_TAG,
|
||||
0
|
||||
);
|
||||
|
||||
RtlInitUnicodeString(&deviceName, KPH_DEVICE_NAME);
|
||||
RtlInitUnicodeString(&dosDeviceName, KPH_DEVICE_DOS_NAME);
|
||||
|
||||
@@ -105,6 +110,26 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
UNICODE_STRING dosDeviceName;
|
||||
|
||||
RtlInitUnicodeString(&dosDeviceName, KPH_DEVICE_DOS_NAME);
|
||||
IoDeleteSymbolicLink(&dosDeviceName);
|
||||
IoDeleteDevice(DriverObject->DeviceObject);
|
||||
|
||||
/* Destroy client list structures */
|
||||
ExDeleteNPagedLookasideList(&ClientLookasideList);
|
||||
|
||||
if (ProtectionInitialized)
|
||||
{
|
||||
KphProtectDeinit();
|
||||
ProtectionInitialized = FALSE;
|
||||
}
|
||||
|
||||
dprintf("Driver unloaded\n");
|
||||
}
|
||||
|
||||
NTSTATUS KphDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
@@ -119,6 +144,13 @@ NTSTATUS KphDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add a client entry. */
|
||||
if (!AddClientEntry(PsGetCurrentProcessId()))
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
dprintf("Client (PID %d) connected\n", PsGetCurrentProcessId());
|
||||
dprintf("Base IOCTL is 0x%08x\n", KPH_CTL_CODE(0));
|
||||
|
||||
@@ -135,6 +167,9 @@ NTSTATUS KphDispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
dprintf("Removed %d protection entries\n", count);
|
||||
}
|
||||
|
||||
/* Remove the client entry. */
|
||||
RemoveClientEntry(PsGetCurrentProcessId());
|
||||
|
||||
dprintf("Client (PID %d) disconnected\n", PsGetCurrentProcessId());
|
||||
|
||||
return status;
|
||||
@@ -149,6 +184,80 @@ VOID InitProtection()
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN AddClientEntry(HANDLE ProcessId)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PKPH_CLIENT_ENTRY entry = ExAllocateFromNPagedLookasideList(&ClientLookasideList);
|
||||
|
||||
if (!entry)
|
||||
return FALSE;
|
||||
|
||||
KeAcquireSpinLock(&ClientListLock, &oldIrql);
|
||||
InsertHeadList(&ClientListHead, &entry->ListEntry);
|
||||
KeReleaseSpinLock(&ClientListLock, oldIrql);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN IsProcessClient(HANDLE ProcessId)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PLIST_ENTRY entry = ClientListHead.Flink;
|
||||
|
||||
KeAcquireSpinLock(&ClientListLock, &oldIrql);
|
||||
|
||||
while (entry != &ClientListHead)
|
||||
{
|
||||
PKPH_CLIENT_ENTRY clientEntry =
|
||||
CONTAINING_RECORD(entry, KPH_CLIENT_ENTRY, ListEntry);
|
||||
|
||||
if (clientEntry->ProcessId == ProcessId)
|
||||
{
|
||||
KeReleaseSpinLock(&ClientListLock, oldIrql);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
entry = entry->Flink;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&ClientListLock, oldIrql);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN RemoveClientEntry(HANDLE ProcessId)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PLIST_ENTRY entry = ClientListHead.Flink;
|
||||
|
||||
KeAcquireSpinLock(&ClientListLock, &oldIrql);
|
||||
|
||||
while (entry != &ClientListHead)
|
||||
{
|
||||
PKPH_CLIENT_ENTRY clientEntry =
|
||||
CONTAINING_RECORD(entry, KPH_CLIENT_ENTRY, ListEntry);
|
||||
|
||||
if (clientEntry->ProcessId == ProcessId)
|
||||
{
|
||||
RemoveEntryList(&clientEntry->ListEntry);
|
||||
ExFreeToNPagedLookasideList(
|
||||
&ClientLookasideList,
|
||||
clientEntry
|
||||
);
|
||||
KeReleaseSpinLock(&ClientListLock, oldIrql);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
entry = entry->Flink;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&ClientListLock, oldIrql);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* from YAPM */
|
||||
NTSTATUS GetObjectName(PFILE_OBJECT FileObject, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength)
|
||||
{
|
||||
|
||||
@@ -161,7 +161,7 @@ NTSTATUS NTAPI KphNewObOpenObjectByPointer(
|
||||
access = DesiredAccess;
|
||||
|
||||
/* If we have an access state, get the desired access from it. */
|
||||
if (PassedAccessState != NULL)
|
||||
if (PassedAccessState)
|
||||
access = PassedAccessState->OriginalDesiredAccess;
|
||||
|
||||
/* Search for and copy the corresponding process protection entry. */
|
||||
@@ -174,6 +174,8 @@ NTSTATUS NTAPI KphNewObOpenObjectByPointer(
|
||||
if (
|
||||
/* check if kernel-mode is exempt from protection */
|
||||
!(processEntry.AllowKernelMode && AccessMode == KernelMode) &&
|
||||
/* allow the creator of the rule to bypass protection */
|
||||
processEntry.CreatorProcess != PsGetCurrentProcess() &&
|
||||
(access & mask) != access
|
||||
)
|
||||
{
|
||||
@@ -228,10 +230,11 @@ PKPH_PROCESS_ENTRY KphProtectAddEntry(
|
||||
/* Lookaside list no longer needed. */
|
||||
ExReleaseRundownProtection(&ProtectedProcessRundownProtect);
|
||||
|
||||
if (entry == NULL)
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
entry->Process = Process;
|
||||
entry->CreatorProcess = PsGetCurrentProcess();
|
||||
entry->Tag = Tag;
|
||||
entry->AllowKernelMode = AllowKernelMode;
|
||||
entry->ProcessAllowMask = ProcessAllowMask;
|
||||
@@ -326,7 +329,7 @@ BOOLEAN KphProtectRemoveByProcess(
|
||||
{
|
||||
PKPH_PROCESS_ENTRY entry = KphProtectFindEntry(Process, NULL);
|
||||
|
||||
if (entry == NULL)
|
||||
if (!entry)
|
||||
return FALSE;
|
||||
|
||||
KphpProtectRemoveEntry(entry);
|
||||
|
||||
Reference in New Issue
Block a user