From ef4127c167bb6b4ecae47ae9045ee0e22ad7f5a8 Mon Sep 17 00:00:00 2001
From: lhodges1 <lachiehodges7785@gmail.com>
Date: Mon, 21 Aug 2023 00:12:04 +1000
Subject: [PATCH] excellent progress :)

---
 driver/callbacks.c            | 138 ++++++++++++++
 driver/callbacks.h            |  47 +++++
 driver/common.h               | 344 ++++++++++++++++++++++++++++++++++
 driver/driver.c               |  81 ++++++++
 driver/driver.h               |  16 ++
 driver/driver.vcxproj         |   4 +
 driver/driver.vcxproj.filters |  12 ++
 driver/ioctl.c                |   8 +
 driver/ioctl.h                |   7 +
 driver/queue.c                |  70 +++++++
 driver/queue.h                |  37 ++++
 service/Types.cs              |   6 +-
 service/Worker.cs             |  14 ++
 user/km/driver.cpp            |  84 ++++++++-
 user/km/driver.h              |  13 +-
 user/km/kmanager.cpp          |   5 +
 user/km/kmanager.h            |   1 +
 user/report.h                 |  12 +-
 18 files changed, 884 insertions(+), 15 deletions(-)
 create mode 100644 driver/callbacks.c
 create mode 100644 driver/callbacks.h
 create mode 100644 driver/queue.c
 create mode 100644 driver/queue.h

diff --git a/driver/callbacks.c b/driver/callbacks.c
new file mode 100644
index 0000000..da1d6a0
--- /dev/null
+++ b/driver/callbacks.c
@@ -0,0 +1,138 @@
+#include "callbacks.h"
+
+#include "common.h"
+#include "driver.h"
+
+#include "queue.h"
+
+PQUEUE_HEAD report_queue = NULL;
+
+VOID InitCallbackReportQueue( PBOOLEAN Status )
+{
+	report_queue = QueueCreate();
+
+	if ( report_queue == NULL )
+		*Status = FALSE;
+
+	*Status = TRUE;
+}
+
+VOID DeleteCallbackReportQueueHead()
+{
+	ExFreePoolWithTag( report_queue, QUEUE_POOL_TAG );
+}
+
+VOID InsertReportToQueue( POPEN_HANDLE_FAILURE_REPORT Report )
+{
+	QueuePush( report_queue, Report );
+}
+
+PVOID PopFirstReportFromQueue( report_queue )
+{
+	return QueuePop( report_queue );
+}
+
+VOID ObPostOpCallbackRoutine(
+	_In_ PVOID RegistrationContext,
+	_In_ POB_POST_OPERATION_INFORMATION OperationInformation
+)
+{
+
+}
+
+OB_PREOP_CALLBACK_STATUS ObPreOpCallbackRoutine(
+	_In_ PVOID RegistrationContext,
+	_In_ POB_PRE_OPERATION_INFORMATION OperationInformation
+)
+{
+	UNREFERENCED_PARAMETER( RegistrationContext );
+
+	/* access mask to completely strip permissions */
+	ACCESS_MASK deny_access = SYNCHRONIZE | PROCESS_TERMINATE;
+
+	/* Access mask to be used for crss / lsass */
+	ACCESS_MASK downgrade_access = 0;
+
+	/*
+	* This callback routine is executed in the context of the thread that
+	* is requesting to open said handle
+	*/
+	PEPROCESS process_creator = PsGetCurrentProcess();
+	PEPROCESS target_process = ( PEPROCESS )OperationInformation->Object;
+
+	LONG target_process_id = PsGetProcessId( target_process );
+	LONG process_creator_id = PsGetProcessId( process_creator );
+
+	LONG protected_process_id;
+	LONG parent_process_id;
+
+	GetProtectedProcessId( &protected_process_id );
+	GetProtectedProcessParentId( &parent_process_id );
+
+	LPCSTR process_creator_name = PsGetProcessImageFileName( process_creator );
+	LPCSTR target_process_name = PsGetProcessImageFileName( target_process );
+
+	if ( protected_process_id ==  target_process_id)
+	{
+		if ( !strcmp( process_creator_name, "lsass.exe" ) || !strcmp( process_creator_name, "csrss.exe" ) )
+		{
+			/* We will downgrade these handles later */
+			DEBUG_LOG( "Handles created by CSRSS and LSASS are allowed for now..." );
+		}
+		/* NOTE: try allowing only 1 handle from the proc creator */
+		else if ( parent_process_id == process_creator_id )
+		{
+			/* Allow handles created by the protected process' creator i.e explorer, cmd etc. */
+			DEBUG_LOG( "Process creator: %s handles are fine for now...", process_creator_name );
+		}
+		else
+		{
+			OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = deny_access;
+			OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = deny_access;
+			DEBUG_LOG( "handle stripped from: %s", process_creator_name );
+		}
+	}
+
+	return OB_PREOP_SUCCESS;
+}
+
+VOID ProcessCreateNotifyRoutine(
+	_In_ HANDLE ParentId,
+	_In_ HANDLE ProcessId,
+	_In_ BOOLEAN Create
+)
+{
+	NTSTATUS status;
+	PEPROCESS parent_process;
+	PEPROCESS target_process;
+	LONG parent_process_id;
+	LPCSTR target_process_name = NULL;
+	LPCSTR parent_process_name = NULL;
+
+	status = PsLookupProcessByProcessId( ParentId, &parent_process );
+
+	if ( !NT_SUCCESS( status ) )
+		return;
+
+	status = PsLookupProcessByProcessId( ProcessId, &target_process );
+
+	if ( !NT_SUCCESS( status ) )
+		return;
+
+	parent_process_name = PsGetProcessImageFileName( parent_process );
+
+	if ( !parent_process_name )
+		return;
+
+	target_process_name = PsGetProcessImageFileName( target_process );
+
+	if ( !target_process_name )
+		return;
+
+	if ( !strcmp( target_process_name, "notepad.exe") )
+	{
+		parent_process_id = PsGetProcessId( target_process );
+		UpdateProtectedProcessId( parent_process_id );
+		LOG_INFO( "Protected process parent proc id: %lx", parent_process_id );
+	}
+}
\ No newline at end of file
diff --git a/driver/callbacks.h b/driver/callbacks.h
new file mode 100644
index 0000000..1d0e860
--- /dev/null
+++ b/driver/callbacks.h
@@ -0,0 +1,47 @@
+#ifndef CALLBACKS_H
+#define CALLBACKS_H
+
+#include <ntifs.h>
+#include <wdftypes.h>
+#include <wdf.h>
+
+typedef struct _OPEN_HANDLE_FAILURE_REPORT
+{
+	INT report_code;
+	INT is_kernel_handle;
+	LONG process_id;
+	LONG thread_id;
+	LONG desired_access;
+	CHAR process_name[ 64 ];
+
+}OPEN_HANDLE_FAILURE_REPORT, *POPEN_HANDLE_FAILURE_REPORT;
+
+//handle access masks
+//https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
+#define PROCESS_CREATE_PROCESS 0x0080
+#define PROCESS_TERMINATE 0x0001
+#define PROCESS_CREATE_THREAD 0x0002
+#define PROCESS_DUP_HANDLE 0x0040
+#define PROCESS_QUERY_INFORMATION 0x0400
+#define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
+#define PROCESS_SET_INFORMATION 0x0200
+#define PROCESS_SET_QUOTA 0x0100
+#define PROCESS_SUSPEND_RESUME 0x0800
+#define PROCESS_VM_OPERATION 0x0008
+#define PROCESS_VM_READ 0x0010
+#define PROCESS_VM_WRITE 0x0020
+
+VOID ObPostOpCallbackRoutine(
+	_In_ PVOID RegistrationContext,
+	_In_ POB_POST_OPERATION_INFORMATION OperationInformation
+);
+
+OB_PREOP_CALLBACK_STATUS ObPreOpCallbackRoutine(
+	_In_ PVOID RegistrationContext,
+	_In_ POB_PRE_OPERATION_INFORMATION OperationInformation
+);
+
+VOID InitCallbackReportQueue(PBOOLEAN Status);
+VOID DeleteCallbackReportQueueHead();
+
+#endif
diff --git a/driver/common.h b/driver/common.h
index c4e8fec..5a0624a 100644
--- a/driver/common.h
+++ b/driver/common.h
@@ -116,4 +116,348 @@ Thread Information Block: (GS register)
 	...
 */
 
+#pragma once
+
+#include <ntifs.h>
+#include <wdftypes.h>
+
+typedef struct _OBJECT_TYPE
+{
+    LIST_ENTRY TypeList;
+    UNICODE_STRING Name;
+    PVOID DefaultObject;
+    UCHAR Index;
+    ULONG TotalNumberOfObjects;
+    ULONG TotalNumberOfHandles;
+    ULONG HighWaterNumberOfObjects;
+    ULONG HighWaterNumberOfHandles;
+    PVOID TypeInfo; //_OBJECT_TYPE_INITIALIZER
+    EX_PUSH_LOCK TypeLock;
+    ULONG Key;
+    LIST_ENTRY CallbackList;
+
+} OBJECT_TYPE, * POBJECT_TYPE;
+
+typedef struct _PEB_LDR_DATA {
+    BYTE Reserved1[ 8 ];
+    PVOID Reserved2[ 3 ];
+    LIST_ENTRY InMemoryOrderModuleList;
+} PEB_LDR_DATA, * PPEB_LDR_DATA;
+
+typedef struct _LDR_DATA_TABLE_ENTRY {
+    PVOID Reserved1[ 2 ];
+    LIST_ENTRY InMemoryOrderLinks;
+    PVOID Reserved2[ 2 ];
+    PVOID DllBase;
+    PVOID Reserved3[ 2 ];
+    UNICODE_STRING FullDllName;
+    BYTE Reserved4[ 8 ];
+    PVOID Reserved5[ 3 ];
+#pragma warning(push)
+#pragma warning(disable: 4201) // we'll always use the Microsoft compiler
+    union {
+        ULONG CheckSum;
+        PVOID Reserved6;
+    } DUMMYUNIONNAME;
+#pragma warning(pop)
+    ULONG TimeDateStamp;
+} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
+
+typedef struct _PEB {
+    BYTE                          Reserved1[ 2 ];
+    BYTE                          BeingDebugged;
+    BYTE                          Reserved2[ 1 ];
+    PVOID                         Reserved3[ 2 ];
+    PPEB_LDR_DATA                 Ldr;
+    PVOID                         ProcessParameters;
+    PVOID                         Reserved4[ 3 ];
+    PVOID                         AtlThunkSListPtr;
+    PVOID                         Reserved5;
+    ULONG                         Reserved6;
+    PVOID                         Reserved7;
+    ULONG                         Reserved8;
+    ULONG                         AtlThunkSListPtr32;
+    PVOID                         Reserved9[ 45 ];
+    BYTE                          Reserved10[ 96 ];
+    PVOID                         PostProcessInitRoutine;
+    BYTE                          Reserved11[ 128 ];
+    PVOID                         Reserved12[ 1 ];
+    ULONG                         SessionId;
+} PEB, * PPEB;
+
+typedef struct _PEB32 {
+    UCHAR InheritedAddressSpace;
+    UCHAR ReadImageFileExecOptions;
+    UCHAR BeingDebugged;
+    UCHAR BitField;
+    ULONG Mutant;
+    ULONG ImageBaseAddress;
+    ULONG Ldr;
+    ULONG ProcessParameters;
+    ULONG SubSystemData;
+    ULONG ProcessHeap;
+    ULONG FastPebLock;
+    ULONG AtlThunkSListPtr;
+    ULONG IFEOKey;
+    ULONG CrossProcessFlags;
+    ULONG UserSharedInfoPtr;
+    ULONG SystemReserved;
+    ULONG AtlThunkSListPtr32;
+    ULONG ApiSetMap;
+} PEB32, * PPEB32;
+
+typedef struct _PEB_LDR_DATA32 {
+    ULONG Length;
+    UCHAR Initialized;
+    ULONG SsHandle;
+    LIST_ENTRY32 InLoadOrderModuleList;
+    LIST_ENTRY32 InMemoryOrderModuleList;
+    LIST_ENTRY32 InInitializationOrderModuleList;
+} PEB_LDR_DATA32, * PPEB_LDR_DATA32;
+
+typedef struct _LDR_DATA_TABLE_ENTRY32 {
+    LIST_ENTRY32 InLoadOrderLinks;
+    LIST_ENTRY32 InMemoryOrderLinks;
+    LIST_ENTRY32 InInitializationOrderLinks;
+    ULONG DllBase;
+    ULONG EntryPoint;
+    ULONG SizeOfImage;
+    UNICODE_STRING32 FullDllName;
+    UNICODE_STRING32 BaseDllName;
+    ULONG Flags;
+    USHORT LoadCount;
+    USHORT TlsIndex;
+    LIST_ENTRY32 HashLinks;
+    ULONG TimeDateStamp;
+} LDR_DATA_TABLE_ENTRY32, * PLDR_DATA_TABLE_ENTRY32;
+
+typedef struct _HANDLE_TABLE_ENTRY_INFO
+{
+    ULONG AuditMask;
+    ULONG MaxRelativeAccessMask;
+
+} HANDLE_TABLE_ENTRY_INFO, * PHANDLE_TABLE_ENTRY_INFO;
+
+typedef union _EXHANDLE
+{
+    struct
+    {
+        int TagBits : 2;
+        int Index : 30;
+    } u;
+    void* GenericHandleOverlay;
+    ULONG_PTR Value;
+} EXHANDLE, * PEXHANDLE;
+
+#pragma warning(disable : 4214 4201)
+
+#pragma pack(push, 1)
+typedef struct _POOL_HEADER // Size=16
+{
+    union
+    {
+        struct
+        {
+            unsigned long PreviousSize : 8; // Size=4 Offset=0 BitOffset=0 BitCount=8
+            unsigned long PoolIndex : 8; // Size=4 Offset=0 BitOffset=8 BitCount=8
+            unsigned long BlockSize : 8; // Size=4 Offset=0 BitOffset=16 BitCount=8
+            unsigned long PoolType : 8; // Size=4 Offset=0 BitOffset=24 BitCount=8
+        };
+        unsigned long Ulong1; // Size=4 Offset=0
+    };
+    unsigned long PoolTag; // Size=4 Offset=4
+    union
+    {
+        struct _EPROCESS* ProcessBilled; // Size=8 Offset=8
+        struct
+        {
+            unsigned short AllocatorBackTraceIndex; // Size=2 Offset=8
+            unsigned short PoolTagHash; // Size=2 Offset=10
+        };
+    };
+} POOL_HEADER, * PPOOL_HEADER;
+#pragma pack(pop)
+
+typedef struct _HANDLE_TABLE_ENTRY // Size=16
+{
+    union
+    {
+        ULONG_PTR VolatileLowValue; // Size=8 Offset=0
+        ULONG_PTR LowValue; // Size=8 Offset=0
+        struct _HANDLE_TABLE_ENTRY_INFO* InfoTable; // Size=8 Offset=0
+        struct
+        {
+            ULONG_PTR Unlocked : 1; // Size=8 Offset=0 BitOffset=0 BitCount=1
+            ULONG_PTR RefCnt : 16; // Size=8 Offset=0 BitOffset=1 BitCount=16
+            ULONG_PTR Attributes : 3; // Size=8 Offset=0 BitOffset=17 BitCount=3
+            ULONG_PTR ObjectPointerBits : 44; // Size=8 Offset=0 BitOffset=20 BitCount=44
+        };
+    };
+    union
+    {
+        ULONG_PTR HighValue; // Size=8 Offset=8
+        struct _HANDLE_TABLE_ENTRY* NextFreeHandleEntry; // Size=8 Offset=8
+        union _EXHANDLE LeafHandleValue; // Size=8 Offset=8
+        struct
+        {
+            ULONG GrantedAccessBits : 25; // Size=4 Offset=8 BitOffset=0 BitCount=25
+            ULONG NoRightsUpgrade : 1; // Size=4 Offset=8 BitOffset=25 BitCount=1
+            ULONG Spare : 6; // Size=4 Offset=8 BitOffset=26 BitCount=6
+        };
+    };
+    ULONG TypeInfo; // Size=4 Offset=12
+} HANDLE_TABLE_ENTRY, * PHANDLE_TABLE_ENTRY;
+
+typedef struct _HANDLE_TABLE_FREE_LIST
+{
+    EX_PUSH_LOCK FreeListLock;
+    PHANDLE_TABLE_ENTRY FirstFreeHandleEntry;
+    PHANDLE_TABLE_ENTRY LastFreeHandleEntry;
+    LONG HandleCount;
+    ULONG HighWaterMark;
+} HANDLE_TABLE_FREE_LIST, * PHANDLE_TABLE_FREE_LIST;
+
+typedef struct _HANDLE_TRACE_DB_ENTRY
+{
+    CLIENT_ID ClientId;
+    PVOID Handle;
+    ULONG Type;
+    PVOID StackTrace[ 16 ];
+
+} HANDLE_TRACE_DB_ENTRY, * PHANDLE_TRACE_DB_ENTRY;
+
+
+
+typedef struct _HANDLE_TRACE_DEBUG_INFO
+{
+    LONG RefCount;
+    ULONG TableSize;
+    ULONG BitMaskFlags;
+    FAST_MUTEX CloseCompactionLock;
+    ULONG CurrentStackIndex;
+    HANDLE_TRACE_DB_ENTRY TraceDb[ 1 ];
+
+} HANDLE_TRACE_DEBUG_INFO, * PHANDLE_TRACE_DEBUG_INFO;
+
+typedef struct _HANDLE_TABLE
+{
+    ULONG NextHandleNeedingPool;
+    LONG ExtraInfoPages;
+    ULONGLONG TableCode;
+    PEPROCESS QuotaProcess;
+    LIST_ENTRY HandleTableList;
+    ULONG UniqueProcessId;
+    union {
+        ULONG Flags;
+        struct {
+            UCHAR StrictFIFO : 1;
+            UCHAR EnableHandleExceptions : 1;
+            UCHAR Rundown : 1;
+            UCHAR Duplicated : 1;
+            UCHAR RaiseUMExceptionOnInvalidHandleClose : 1;
+        };
+    };
+    EX_PUSH_LOCK HandleContentionEvent;
+    EX_PUSH_LOCK HandleTableLock;
+    union {
+        HANDLE_TABLE_FREE_LIST FreeLists[ 1 ];
+        UCHAR ActualEntry[ 32 ];
+    };
+
+    struct _HANDLE_TRACE_DEBUG_INFO* DebugInfo;
+
+} HANDLE_TABLE, * PHANDLE_TABLE;
+
+typedef BOOLEAN( *EX_ENUMERATE_HANDLE_ROUTINE )(
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
+    IN HANDLE Handle,
+    IN PVOID EnumParameter
+    );
+
+typedef struct _OBJECT_CREATE_INFORMATION
+{
+    ULONG Attributes;
+    PVOID RootDirectory;
+    CHAR ProbeMode;
+    ULONG PagedPoolCharge;
+    ULONG NonPagedPoolCharge;
+    ULONG SecurityDescriptorCharge;
+    PVOID SecurityDescriptor;
+    struct _SECURITY_QUALITY_OF_SERVICE* SecurityQos;
+    struct _SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
+
+} OBJECT_CREATE_INFORMATION, * POBJECT_CREATE_INFORMATION;
+
+typedef struct _OBJECT_HEADER
+{
+    LONGLONG PointerCount;
+    union {
+        LONGLONG HandleCount;
+        PVOID NextToFree;
+    };
+    EX_PUSH_LOCK Lock;
+    UCHAR TypeIndex;
+    union {
+        UCHAR TraceFlags;
+        struct {
+            UCHAR DbgRefTrace : 1;
+            UCHAR DbgTracePermanent : 1;
+        };
+    };
+    UCHAR InfoMask;
+    union {
+        UCHAR Flags;
+        struct {
+            UCHAR NewObject : 1;
+            UCHAR KernelObject : 1;
+            UCHAR KernelOnlyAccess : 1;
+            UCHAR ExclusiveObject : 1;
+            UCHAR PermanentObject : 1;
+            UCHAR DefaultSecurityQuota : 1;
+            UCHAR SingleHandleEntry : 1;
+            UCHAR DeletedInline : 1;
+        };
+    };
+    ULONG Reserved;
+    union {
+        POBJECT_CREATE_INFORMATION ObjectCreateInfo;
+        PVOID QuotaBlockCharged;
+    };
+    PVOID SecurityDescriptor;
+    QUAD Body;
+} OBJECT_HEADER, * POBJECT_HEADER;
+
+NTKERNELAPI
+BOOLEAN
+ExEnumHandleTable(
+    __in PHANDLE_TABLE HandleTable,
+    __in EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
+    __in PVOID EnumParameter,
+    __out_opt PHANDLE Handle
+);
+
+NTKERNELAPI
+POBJECT_TYPE
+NTAPI
+ObGetObjectType(
+    _In_ PVOID Object
+);
+
+typedef struct _EX_PUSH_LOCK_WAIT_BLOCK* PEX_PUSH_LOCK_WAIT_BLOCK;
+
+NTKERNELAPI
+VOID
+FASTCALL
+ExfUnblockPushLock(
+    _Inout_ PEX_PUSH_LOCK PushLock,
+    _Inout_opt_ PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock
+);
+
+LPCSTR
+NTSYSAPI
+NTAPI
+PsGetProcessImageFileName(
+    PEPROCESS Process
+);
+
 #endif
diff --git a/driver/driver.c b/driver/driver.c
index 76428c7..f49b92f 100644
--- a/driver/driver.c
+++ b/driver/driver.c
@@ -2,6 +2,49 @@
 
 #include "common.h"
 #include "ioctl.h"
+#include "callbacks.h"
+
+PVOID callback_registration_handle;
+
+LONG protected_process_id;
+LONG protected_process_parent_id;
+KGUARDED_MUTEX mutex;
+
+VOID UpdateProtectedProcessId( 
+	_In_ LONG NewProcessId 
+)
+{
+	KeAcquireGuardedMutex( &mutex );
+	protected_process_id = NewProcessId;
+	KeReleaseGuardedMutex( &mutex );
+}
+
+VOID GetProtectedProcessId(
+	_Out_ PLONG ProcessId
+)
+{
+	KeAcquireGuardedMutex( &mutex );
+	*ProcessId = protected_process_id;
+	KeReleaseGuardedMutex( &mutex );
+}
+
+VOID GetProtectedProcessParentId( 
+	_Out_ PLONG ProcessId 
+)
+{
+	KeAcquireGuardedMutex( &mutex );
+	*ProcessId = protected_process_parent_id;
+	KeReleaseGuardedMutex( &mutex );
+}
+
+VOID UpdateProtectedProcessParentId( 
+	_In_ LONG NewProcessId 
+)
+{
+	KeAcquireGuardedMutex( &mutex );
+	protected_process_parent_id = NewProcessId;
+	KeReleaseGuardedMutex( &mutex );
+}
 
 VOID DriverUnload(
 	_In_ PDRIVER_OBJECT DriverObject
@@ -18,6 +61,7 @@ NTSTATUS DriverEntry(
 {
 	UNREFERENCED_PARAMETER( RegistryPath );
 
+	BOOLEAN flag;
 	NTSTATUS status;
 
 	status = IoCreateDevice(
@@ -49,6 +93,43 @@ NTSTATUS DriverEntry(
 	DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = DeviceControl;
 	DriverObject->DriverUnload = DriverUnload;
 
+	KeInitializeGuardedMutex( &mutex );
+
+	InitCallbackReportQueue(&flag);
+
+	if ( !flag )
+	{
+		IoDeleteSymbolicLink( &DEVICE_SYMBOLIC_LINK );
+		IoDeleteDevice( DriverObject->DeviceObject );
+		return STATUS_FAILED_DRIVER_ENTRY;
+	}
+
+	OB_CALLBACK_REGISTRATION callback_registration = { 0 };
+	OB_OPERATION_REGISTRATION operation_registration = { 0 };
+
+	operation_registration.ObjectType = PsProcessType;
+	operation_registration.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
+	operation_registration.PreOperation = ObPreOpCallbackRoutine;
+	operation_registration.PostOperation = ObPostOpCallbackRoutine;
+
+	callback_registration.Version = OB_FLT_REGISTRATION_VERSION;
+	callback_registration.OperationRegistration = &operation_registration;
+	callback_registration.OperationRegistrationCount = 1;
+	callback_registration.RegistrationContext = NULL;
+
+	status = ObRegisterCallbacks(
+		&callback_registration,
+		&callback_registration_handle
+	);
+
+	if ( !NT_SUCCESS( status ) )
+	{
+		DeleteCallbackReportQueueHead();
+		IoDeleteSymbolicLink( &DEVICE_SYMBOLIC_LINK );
+		IoDeleteDevice( DriverObject->DeviceObject );
+		return STATUS_FAILED_DRIVER_ENTRY;
+	}
+
 	DEBUG_LOG( "DonnaAC Driver Entry Complete. type: %lx", DriverObject->DeviceObject->DeviceType );
 
 	return status;
diff --git a/driver/driver.h b/driver/driver.h
index 754a5d9..d30eb32 100644
--- a/driver/driver.h
+++ b/driver/driver.h
@@ -8,4 +8,20 @@
 UNICODE_STRING DEVICE_NAME = RTL_CONSTANT_STRING( L"\\Device\\DonnaAC" );
 UNICODE_STRING DEVICE_SYMBOLIC_LINK = RTL_CONSTANT_STRING( L"\\??\\DonnaAC" );
 
+VOID UpdateProtectedProcessId(
+	_In_ LONG NewProcessId 
+);
+
+VOID GetProtectedProcessId(
+	_Out_ PLONG ProcessId
+);
+
+VOID GetProtectedProcessParentId(
+	_Out_ PLONG ProcessId
+);
+
+VOID UpdateProtectedProcessParentId(
+	_In_ LONG NewProcessId
+);
+
 #endif
\ No newline at end of file
diff --git a/driver/driver.vcxproj b/driver/driver.vcxproj
index 9578dc5..b91300d 100644
--- a/driver/driver.vcxproj
+++ b/driver/driver.vcxproj
@@ -117,17 +117,21 @@
     <FilesToPackage Include="$(TargetPath)" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="callbacks.c" />
     <ClCompile Include="driver.c" />
     <ClCompile Include="ioctl.c" />
     <ClCompile Include="modules.c" />
     <ClCompile Include="nmi.c" />
+    <ClCompile Include="queue.c" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="callbacks.h" />
     <ClInclude Include="common.h" />
     <ClInclude Include="driver.h" />
     <ClInclude Include="ioctl.h" />
     <ClInclude Include="modules.h" />
     <ClInclude Include="nmi.h" />
+    <ClInclude Include="queue.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/driver/driver.vcxproj.filters b/driver/driver.vcxproj.filters
index cb11864..0d49a77 100644
--- a/driver/driver.vcxproj.filters
+++ b/driver/driver.vcxproj.filters
@@ -36,6 +36,12 @@
     <ClCompile Include="modules.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="callbacks.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="queue.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="driver.h">
@@ -53,5 +59,11 @@
     <ClInclude Include="modules.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="callbacks.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="queue.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/driver/ioctl.c b/driver/ioctl.c
index 6caff1b..516591e 100644
--- a/driver/ioctl.c
+++ b/driver/ioctl.c
@@ -4,6 +4,7 @@
 
 #include "nmi.h"
 #include "modules.h"
+#include "driver.h"
 
 NTSTATUS DeviceControl(
 	_In_ PDRIVER_OBJECT DriverObject,
@@ -88,6 +89,13 @@ NTSTATUS DeviceControl(
 
 		break;
 
+	case IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH:;
+
+		PDRIVER_INITIATION_INFORMATION information = ( PDRIVER_INITIATION_INFORMATION )Irp->AssociatedIrp.SystemBuffer;
+		UpdateProtectedProcessId( information->protected_process_id );
+		break;
+
+
 	default:
 		DEBUG_ERROR( "Invalid IOCTL passed to driver" );
 		break;
diff --git a/driver/ioctl.h b/driver/ioctl.h
index 3518ac2..18fb8ba 100644
--- a/driver/ioctl.h
+++ b/driver/ioctl.h
@@ -9,6 +9,13 @@
 
 #define IOCCTL_RUN_NMI_CALLBACKS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2001, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define IOCTL_VALIDATE_DRIVER_OBJECTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2002, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2004, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+typedef struct _DRIVER_INITIATION_INFORMATION
+{
+	LONG protected_process_id;
+
+} DRIVER_INITIATION_INFORMATION, * PDRIVER_INITIATION_INFORMATION;
 
 NTSTATUS DeviceControl(
 	_In_ PDRIVER_OBJECT DriverObject,
diff --git a/driver/queue.c b/driver/queue.c
new file mode 100644
index 0000000..7a5f9e8
--- /dev/null
+++ b/driver/queue.c
@@ -0,0 +1,70 @@
+#include "queue.h"
+
+PQUEUE_HEAD QueueCreate()
+{
+	PQUEUE_HEAD head = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( PQUEUE_HEAD ), QUEUE_POOL_TAG );
+
+	if ( !head )
+		return NULL;
+
+	head->end = NULL;
+	head->start = NULL;
+
+	KeInitializeSpinLock( head->lock );
+
+	return head;
+}
+
+VOID QueuePush( 
+	_In_ PQUEUE_HEAD Head,
+	_In_ PVOID Data
+)
+{
+	KIRQL irql = KeGetCurrentIrql();
+	KeAcquireSpinLock( Head->lock, &irql );
+
+	PQUEUE_NODE temp = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( QUEUE_NODE ), QUEUE_POOL_TAG );
+
+	if ( !temp )
+		goto end;
+
+	temp->data = Data;
+	temp->lock = Head->lock;
+
+	if ( Head->end != NULL )
+		Head->end->next = temp;
+
+	Head->end = temp;
+
+	if ( Head->start == NULL )
+		Head->start = temp;
+
+end:
+	KeReleaseSpinLock( Head->lock, irql );
+}
+
+PVOID QueuePop(
+	_In_ PQUEUE_HEAD Head
+)
+{
+	KIRQL irql = KeGetCurrentIrql();
+	KeAcquireSpinLock( Head->lock, &irql );
+
+	PVOID data = NULL;
+	PQUEUE_NODE temp = Head->start;
+
+	if ( temp == NULL )
+		goto end;
+
+	data = temp->data;
+	Head->start = temp->next;
+
+	if ( Head->end == temp )
+		Head->end = NULL;
+
+	ExFreePoolWithTag( temp, QUEUE_POOL_TAG );
+
+end:
+	KeReleaseSpinLock( Head->lock, irql );
+	return data;
+}
diff --git a/driver/queue.h b/driver/queue.h
new file mode 100644
index 0000000..bfc06d6
--- /dev/null
+++ b/driver/queue.h
@@ -0,0 +1,37 @@
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include <ntifs.h>
+
+#define QUEUE_POOL_TAG 'qqqq'
+
+typedef struct _QUEUE_NODE
+{
+	struct _QUEUE_NODE* next;
+	PKSPIN_LOCK lock;
+	PVOID data;
+
+}QUEUE_NODE, *PQUEUE_NODE;
+
+typedef struct QUEUE_HEAD
+{
+	struct _QUEUE_NODE* start;
+	struct _QUEUE_NODE* end;
+	PKSPIN_LOCK lock;
+
+}QUEUE_HEAD, *PQUEUE_HEAD;
+
+PQUEUE_NODE QueueCreate();
+
+VOID QueuePush(
+	_In_ PQUEUE_HEAD Head,
+	_In_ PVOID Data
+);
+
+PVOID QueuePop( 
+	_In_ PQUEUE_HEAD Head
+);
+
+
+
+#endif
\ No newline at end of file
diff --git a/service/Types.cs b/service/Types.cs
index ec210e9..8528a51 100644
--- a/service/Types.cs
+++ b/service/Types.cs
@@ -10,16 +10,12 @@ namespace service
 {
     namespace Types
     {
-        [StructLayout(LayoutKind.Explicit)]
+        [StructLayout(LayoutKind.Sequential)]
         public unsafe struct MODULE_VERIFICATION_CHECKSUM_FAILURE
         {
-            [FieldOffset(0)]
             public int ReportCode;
-            [FieldOffset(0)]
             public UInt64 ModuleBaseAddress;
-            [FieldOffset(0)]
             public UInt64 ModuleSize;
-            [FieldOffset(0)]
             public fixed char ModuleName[512];
         }
 
diff --git a/service/Worker.cs b/service/Worker.cs
index c88e48b..699fe2b 100644
--- a/service/Worker.cs
+++ b/service/Worker.cs
@@ -1,4 +1,5 @@
 using System.IO.Pipes;
+using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using service.Types;
 
@@ -193,6 +194,19 @@ namespace service
                 Marshal.FreeHGlobal(ptr);
             }
         }
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        internal static extern bool GetNamedPipeClientProcessId(IntPtr Pipe, out uint ClientProcessId);
+        public static uint GetNamedPipeClientProcId(NamedPipeServerStream PipeServer)
+        {
+            UInt32 procId;
+            IntPtr pipeHandle = PipeServer.SafePipeHandle.DangerousGetHandle();
+
+            if (GetNamedPipeClientProcessId(pipeHandle, out procId))
+                return procId;
+
+            return 0;
+        }
     }
 }
 #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
diff --git a/user/km/driver.cpp b/user/km/driver.cpp
index 8ffe186..6dff5d7 100644
--- a/user/km/driver.cpp
+++ b/user/km/driver.cpp
@@ -130,16 +130,92 @@ void kernelmode::Driver::VerifySystemModules()
 	free( buffer );
 }
 
-void kernelmode::Driver::EnableObRegisterCallbacks()
+/*
+* HOW THIS WILL WORK:
+* 
+* 1. On driver initiation, ObRegisterCallbacks will be registered 
+* 2. Each time a process that is not whitelisted tries to open a handle
+*	 to our game we will store the report in an a report queue
+* 3. the user mode app will then periodically query the driver asking
+*	 how many pending reports there are
+* 4. once the number is received, the app will allocate a buffer large enough
+*	 for all the reports and once again call CompleteQueuedCallbackReports
+* 5. This will then retrieve the reports into the buffer and from there
+*    we can iteratively report them the same way as we do with the system
+*	 modules.
+*/
+
+bool kernelmode::Driver::QueueCallbackReportIrp(PHANDLE Event)
 {
+	if ( !Event )
+		return false;
+
+	OVERLAPPED io;
+	BOOLEAN status;
+	DWORD bytes_returned;
+	global::report_structures::OPEN_HANDLE_FAILURE_REPORT report;
+
+	io.hEvent = *Event;
+
+	status = DeviceIoControl(
+		this->driver_handle,
+		IOCTL_MONITOR_CALLBACKS_FOR_REPORTS,
+		NULL,
+		NULL,
+		&report,
+		sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT ),
+		&bytes_returned,
+		&io
+	);
+
+	if ( status == NULL )
+	{
+		LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() );
+		return false;
+	}
+
+	WaitForSingleObject( io.hEvent, INFINITE );
+
+	/* we EXPECTED to receive bytes so this is an error */
+	if ( bytes_returned == NULL )
+		return false;
+
+
+
 }
 
-void kernelmode::Driver::DisableObRegisterCallbacks()
+void kernelmode::Driver::NotifyDriverOnProcessLaunch()
 {
+	BOOLEAN status;
+	kernelmode::DRIVER_INITIATION_INFORMATION information;
+	information.protected_process_id = GetCurrentProcessId();
+
+	status = DeviceIoControl(
+		this->driver_handle,
+		IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH,
+		&information,
+		sizeof( kernelmode::DRIVER_INITIATION_INFORMATION ),
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	);
+
+	if ( status == NULL )
+		LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() );
+}
+
+void kernelmode::Driver::CompleteQueuedCallbackReports()
+{
+
 }
 
 void kernelmode::Driver::EnableProcessLoadNotifyCallbacks()
 {
+	/* 
+	* note: no need for these since when the dll is loaded it will simply
+	* notify the driver.
+	*/
 }
 
 void kernelmode::Driver::DisableProcessLoadNotifyCallbacks()
@@ -150,10 +226,6 @@ void kernelmode::Driver::ValidateKPRCBThreads()
 {
 }
 
-void kernelmode::Driver::CheckForHypervisor()
-{
-}
-
 void kernelmode::Driver::CheckDriverHeartbeat()
 {
 }
diff --git a/user/km/driver.h b/user/km/driver.h
index dd20d00..64162a1 100644
--- a/user/km/driver.h
+++ b/user/km/driver.h
@@ -8,6 +8,8 @@
 
 #define IOCCTL_RUN_NMI_CALLBACKS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2001, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define IOCTL_VALIDATE_DRIVER_OBJECTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2002, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_MONITOR_CALLBACKS_FOR_REPORTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2003, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2004, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
 namespace kernelmode
 {
@@ -22,15 +24,20 @@ namespace kernelmode
 
 		void RunNmiCallbacks();
 		void VerifySystemModules();
-		void EnableObRegisterCallbacks();
-		void DisableObRegisterCallbacks();
+		bool QueueCallbackReportIrp( PHANDLE Event );
+		void NotifyDriverOnProcessLaunch();
+		void CompleteQueuedCallbackReports();
 		void EnableProcessLoadNotifyCallbacks();
 		void DisableProcessLoadNotifyCallbacks();
 		void ValidateKPRCBThreads();
-		void CheckForHypervisor();
 		void CheckDriverHeartbeat();
 		/* todo: driver integrity check */
 	};
+
+	struct DRIVER_INITIATION_INFORMATION
+	{
+		LONG protected_process_id;
+	};
 }
 
 #endif
diff --git a/user/km/kmanager.cpp b/user/km/kmanager.cpp
index 8400b2f..21a9fc5 100644
--- a/user/km/kmanager.cpp
+++ b/user/km/kmanager.cpp
@@ -15,3 +15,8 @@ void kernelmode::KManager::VerifySystemModules()
 {
 	this->thread_pool->QueueJob( [ this ]() { this->driver_interface->VerifySystemModules(); } );
 }
+
+void kernelmode::KManager::MonitorCallbackReports()
+{
+
+}
diff --git a/user/km/kmanager.h b/user/km/kmanager.h
index 5d1ff9b..857ce55 100644
--- a/user/km/kmanager.h
+++ b/user/km/kmanager.h
@@ -19,6 +19,7 @@ namespace kernelmode
 
 		void RunNmiCallbacks();
 		void VerifySystemModules();
+		void MonitorCallbackReports();
 	};
 }
 
diff --git a/user/report.h b/user/report.h
index 95a5b44..ac8d1c7 100644
--- a/user/report.h
+++ b/user/report.h
@@ -33,7 +33,7 @@ namespace global
 
 		Report( std::shared_ptr<global::ThreadPool> ThreadPool, LPTSTR PipeName );
 
-		/* lock buffer, copy report, send to service then clear buffer */
+		/* lock buffer, attach header, copy report, send to service then clear buffer */
 		template <typename T>
 		void ReportViolation( T* Report )
 		{
@@ -105,6 +105,16 @@ namespace global
 			UINT64 driver_size;
 			CHAR driver_name[ 128 ];
 		};
+
+		struct OPEN_HANDLE_FAILURE_REPORT
+		{
+			INT report_code;
+			INT is_kernel_handle;
+			LONG process_id;
+			LONG thread_id;
+			LONG desired_access;
+			CHAR process_name[ 64 ];
+		};
 	}
 }