excellent progress :)

This commit is contained in:
lhodges1 2023-08-21 00:12:04 +10:00
parent 9e6b71e5df
commit ef4127c167
18 changed files with 884 additions and 15 deletions

138
driver/callbacks.c Normal file
View file

@ -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 );
}
}

47
driver/callbacks.h Normal file
View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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">

View file

@ -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>

View file

@ -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;

View file

@ -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,

70
driver/queue.c Normal file
View file

@ -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;
}

37
driver/queue.h Normal file
View file

@ -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

View file

@ -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];
}

View file

@ -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

View file

@ -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;
}
void kernelmode::Driver::DisableObRegisterCallbacks()
WaitForSingleObject( io.hEvent, INFINITE );
/* we EXPECTED to receive bytes so this is an error */
if ( bytes_returned == NULL )
return false;
}
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()
{
}

View file

@ -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

View file

@ -15,3 +15,8 @@ void kernelmode::KManager::VerifySystemModules()
{
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->VerifySystemModules(); } );
}
void kernelmode::KManager::MonitorCallbackReports()
{
}

View file

@ -19,6 +19,7 @@ namespace kernelmode
void RunNmiCallbacks();
void VerifySystemModules();
void MonitorCallbackReports();
};
}

View file

@ -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 ];
};
}
}