From 0d853853bf2e71f6bd5d88cb4ffa8a186806694d Mon Sep 17 00:00:00 2001 From: lhodges1 Date: Mon, 21 Aug 2023 01:04:53 +1000 Subject: [PATCH] eee --- driver/callbacks.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-- driver/callbacks.h | 20 ++++++++++++- driver/driver.c | 3 ++ driver/driver.h | 3 -- driver/ioctl.c | 10 ++++++- driver/ioctl.h | 1 + driver/queue.c | 9 ++++++ driver/queue.h | 3 +- service/Types.cs | 15 +++++++++- service/Worker.cs | 13 ++++++++ user/km/driver.cpp | 36 ++++++++++++---------- user/km/driver.h | 5 +++- user/report.h | 7 +++++ 13 files changed, 174 insertions(+), 26 deletions(-) diff --git a/driver/callbacks.c b/driver/callbacks.c index da1d6a0..6331cc8 100644 --- a/driver/callbacks.c +++ b/driver/callbacks.c @@ -7,6 +7,8 @@ PQUEUE_HEAD report_queue = NULL; +KGUARDED_MUTEX mutex; + VOID InitCallbackReportQueue( PBOOLEAN Status ) { report_queue = QueueCreate(); @@ -14,6 +16,8 @@ VOID InitCallbackReportQueue( PBOOLEAN Status ) if ( report_queue == NULL ) *Status = FALSE; + KeInitializeGuardedMutex( &mutex ); + *Status = TRUE; } @@ -22,16 +26,65 @@ VOID DeleteCallbackReportQueueHead() ExFreePoolWithTag( report_queue, QUEUE_POOL_TAG ); } -VOID InsertReportToQueue( POPEN_HANDLE_FAILURE_REPORT Report ) +VOID InsertReportToQueue( + _In_ POPEN_HANDLE_FAILURE_REPORT Report +) { QueuePush( report_queue, Report ); } -PVOID PopFirstReportFromQueue( report_queue ) +POPEN_HANDLE_FAILURE_REPORT PopFirstReportFromQueue() { return QueuePop( report_queue ); } +NTSTATUS HandlePeriodicCallbackReportQueue( + _In_ PIRP Irp +) +{ + PVOID report = NULL; + INT count = 0; + OPEN_HANDLE_FAILURE_REPORT_HEADER header; + + KeAcquireGuardedMutex( &mutex ); + report = PopFirstReportFromQueue(); + + if ( report == NULL ) + { + DEBUG_LOG( "callback report queue is empty, returning" ); + KeReleaseGuardedMutex( &mutex ); + Irp->IoStatus.Information = NULL; + return STATUS_SUCCESS; + } + + Irp->IoStatus.Information = sizeof( OPEN_HANDLE_FAILURE_REPORT ) * MAX_HANDLE_REPORTS_PER_IRP + + sizeof( OPEN_HANDLE_FAILURE_REPORT_HEADER ); + + while ( report != NULL ) + { + if ( count >= MAX_HANDLE_REPORTS_PER_IRP ) + goto end; + + RtlCopyMemory( + ( ( UINT64 )Irp->AssociatedIrp.SystemBuffer + sizeof( OPEN_HANDLE_FAILURE_REPORT_HEADER ) ) + count * sizeof( OPEN_HANDLE_FAILURE_REPORT ), + report, + sizeof( OPEN_HANDLE_FAILURE_REPORT ) + ); + + report = PopFirstReportFromQueue(); + count += 1; + } + + header.count = count; + RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &header, sizeof( OPEN_HANDLE_FAILURE_REPORT_HEADER )); + + DEBUG_LOG( "Moved all reports into the IRP, sending !" ); + +end: + KeReleaseGuardedMutex( &mutex ); + return STATUS_SUCCESS; +} + VOID ObPostOpCallbackRoutine( _In_ PVOID RegistrationContext, _In_ POB_POST_OPERATION_INFORMATION OperationInformation @@ -90,9 +143,25 @@ OB_PREOP_CALLBACK_STATUS ObPreOpCallbackRoutine( OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = deny_access; OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = deny_access; DEBUG_LOG( "handle stripped from: %s", process_creator_name ); + + POPEN_HANDLE_FAILURE_REPORT report = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( OPEN_HANDLE_FAILURE_REPORT ), REPORT_POOL_TAG ); + + if ( !report ) + goto end; + + report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION; + report->desired_access = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess; + report->is_kernel_handle = OperationInformation->KernelHandle; + report->process_id = process_creator_id; + report->thread_id = PsGetCurrentThreadId(); + memcpy( report->process_name, process_creator_name, HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH ); + + InsertReportToQueue( report ); } } +end: + return OB_PREOP_SUCCESS; } @@ -133,6 +202,6 @@ VOID ProcessCreateNotifyRoutine( { parent_process_id = PsGetProcessId( target_process ); UpdateProtectedProcessId( parent_process_id ); - LOG_INFO( "Protected process parent proc id: %lx", parent_process_id ); + DEBUG_LOG( "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 index 1d0e860..6ccb9d6 100644 --- a/driver/callbacks.h +++ b/driver/callbacks.h @@ -5,6 +5,20 @@ #include #include +#define REPORT_ILLEGAL_HANDLE_OPERATION 70 + +#define HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH 64 + +#define REPORT_POOL_TAG 'repo' + +#define MAX_HANDLE_REPORTS_PER_IRP 10 + +typedef struct _OPEN_HANDLE_FAILURE_REPORT_HEADER +{ + INT count; + +}OPEN_HANDLE_FAILURE_REPORT_HEADER, *POPEN_HANDLE_FAILURE_REPORT_HEADER; + typedef struct _OPEN_HANDLE_FAILURE_REPORT { INT report_code; @@ -12,7 +26,7 @@ typedef struct _OPEN_HANDLE_FAILURE_REPORT LONG process_id; LONG thread_id; LONG desired_access; - CHAR process_name[ 64 ]; + CHAR process_name[ HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH ]; }OPEN_HANDLE_FAILURE_REPORT, *POPEN_HANDLE_FAILURE_REPORT; @@ -44,4 +58,8 @@ OB_PREOP_CALLBACK_STATUS ObPreOpCallbackRoutine( VOID InitCallbackReportQueue(PBOOLEAN Status); VOID DeleteCallbackReportQueueHead(); +NTSTATUS HandlePeriodicCallbackReportQueue( + _In_ PIRP Irp +); + #endif diff --git a/driver/driver.c b/driver/driver.c index f49b92f..d5a1f67 100644 --- a/driver/driver.c +++ b/driver/driver.c @@ -10,6 +10,9 @@ LONG protected_process_id; LONG protected_process_parent_id; KGUARDED_MUTEX mutex; +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 ) diff --git a/driver/driver.h b/driver/driver.h index d30eb32..2fb1400 100644 --- a/driver/driver.h +++ b/driver/driver.h @@ -5,9 +5,6 @@ #include #include -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 ); diff --git a/driver/ioctl.c b/driver/ioctl.c index 516591e..f848b39 100644 --- a/driver/ioctl.c +++ b/driver/ioctl.c @@ -5,6 +5,7 @@ #include "nmi.h" #include "modules.h" #include "driver.h" +#include "callbacks.h" NTSTATUS DeviceControl( _In_ PDRIVER_OBJECT DriverObject, @@ -95,6 +96,14 @@ NTSTATUS DeviceControl( UpdateProtectedProcessId( information->protected_process_id ); break; + case IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE: + + status = HandlePeriodicCallbackReportQueue(Irp); + + if ( !NT_SUCCESS( status ) ) + DEBUG_ERROR( "Failed to handle period callback report queue" ); + + break; default: DEBUG_ERROR( "Invalid IOCTL passed to driver" ); @@ -102,7 +111,6 @@ NTSTATUS DeviceControl( } end: - DEBUG_LOG( "completing irp request" ); Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; diff --git a/driver/ioctl.h b/driver/ioctl.h index 18fb8ba..e8e8fb0 100644 --- a/driver/ioctl.h +++ b/driver/ioctl.h @@ -10,6 +10,7 @@ #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) +#define IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2005, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct _DRIVER_INITIATION_INFORMATION { diff --git a/driver/queue.c b/driver/queue.c index 7a5f9e8..f977349 100644 --- a/driver/queue.c +++ b/driver/queue.c @@ -1,5 +1,9 @@ #include "queue.h" +/* +* Basic thread-safe queue implementation that can be used to create queues for any data. +*/ + PQUEUE_HEAD QueueCreate() { PQUEUE_HEAD head = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( PQUEUE_HEAD ), QUEUE_POOL_TAG ); @@ -9,6 +13,7 @@ PQUEUE_HEAD QueueCreate() head->end = NULL; head->start = NULL; + head->entries = 0; KeInitializeSpinLock( head->lock ); @@ -28,6 +33,8 @@ VOID QueuePush( if ( !temp ) goto end; + Head->entries += 1; + temp->data = Data; temp->lock = Head->lock; @@ -56,6 +63,8 @@ PVOID QueuePop( if ( temp == NULL ) goto end; + Head->entries -= 1; + data = temp->data; Head->start = temp->next; diff --git a/driver/queue.h b/driver/queue.h index bfc06d6..6f0f684 100644 --- a/driver/queue.h +++ b/driver/queue.h @@ -18,10 +18,11 @@ typedef struct QUEUE_HEAD struct _QUEUE_NODE* start; struct _QUEUE_NODE* end; PKSPIN_LOCK lock; + INT entries; }QUEUE_HEAD, *PQUEUE_HEAD; -PQUEUE_NODE QueueCreate(); +PQUEUE_HEAD QueueCreate(); VOID QueuePush( _In_ PQUEUE_HEAD Head, diff --git a/service/Types.cs b/service/Types.cs index 8528a51..9453cda 100644 --- a/service/Types.cs +++ b/service/Types.cs @@ -1,4 +1,5 @@ -using System; +using Serilog; +using System; using System.Collections.Generic; using System.Linq; using System.Numerics; @@ -59,5 +60,17 @@ namespace service public long DriverSize; public fixed char ModuleName[128]; } + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct OPEN_HANDLE_FAILURE_REPORT + { + public int ReportCode; + public int IsKernelHandle; + public long ProcessId; + public long ThreadId; + public long DesiredAccess; + public fixed char ProcessName[64]; + + } } } diff --git a/service/Worker.cs b/service/Worker.cs index 699fe2b..0bb969e 100644 --- a/service/Worker.cs +++ b/service/Worker.cs @@ -23,6 +23,7 @@ namespace service private const int REPORT_PATTERN_SCAN_FAILURE = 40; private const int REPORT_NMI_CALLBACK_FAILURE = 50; private const int REPORT_KERNEL_MODULE_FAILURE = 60; + private const int REPORT_OPEN_HANDLE_FAILURE_REPORT = 70; private const int MESSAGE_TYPE_REPORT = 1; private const int MESSAGE_TYPE_REQUEST = 2; @@ -170,6 +171,18 @@ namespace service goto end; + case REPORT_OPEN_HANDLE_FAILURE_REPORT: + + var openHandleFailure = BytesToStructure(); + + _logger.LogInformation("Report code: {0}, ProcessID: {1}, ThreadId: {2}, DesiredAccess{3}", + openHandleFailure.ReportCode, + openHandleFailure.ProcessId, + openHandleFailure.ThreadId, + openHandleFailure.DesiredAccess); + + goto end; + default: _logger.LogError("Invalid report code received"); goto end; diff --git a/user/km/driver.cpp b/user/km/driver.cpp index 6dff5d7..152beab 100644 --- a/user/km/driver.cpp +++ b/user/km/driver.cpp @@ -145,42 +145,48 @@ void kernelmode::Driver::VerifySystemModules() * modules. */ -bool kernelmode::Driver::QueueCallbackReportIrp(PHANDLE Event) +void kernelmode::Driver::QueryReportQueue() { - if ( !Event ) - return false; - - OVERLAPPED io; BOOLEAN status; DWORD bytes_returned; + PVOID buffer; + LONG buffer_size; global::report_structures::OPEN_HANDLE_FAILURE_REPORT report; - io.hEvent = *Event; + buffer_size = sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT ) * MAX_HANDLE_REPORTS_PER_IRP ; + buffer = malloc( buffer_size ); status = DeviceIoControl( this->driver_handle, - IOCTL_MONITOR_CALLBACKS_FOR_REPORTS, + IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE, NULL, NULL, - &report, - sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT ), + buffer, + buffer_size, &bytes_returned, - &io + NULL ); if ( status == NULL ) { LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() ); - return false; + return; } - WaitForSingleObject( io.hEvent, INFINITE ); + global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER* header = + ( global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER* )buffer; - /* we EXPECTED to receive bytes so this is an error */ - if ( bytes_returned == NULL ) - return false; + for ( int i = 0; i < header->count; i++ ) + { + global::report_structures::OPEN_HANDLE_FAILURE_REPORT* report = + ( global::report_structures::OPEN_HANDLE_FAILURE_REPORT* )( + ( UINT64 )buffer + sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER ) + + i * sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT ) ); + this->report_interface->ReportViolation( report ); + } + free( buffer ); } diff --git a/user/km/driver.h b/user/km/driver.h index 64162a1..ab60d30 100644 --- a/user/km/driver.h +++ b/user/km/driver.h @@ -10,6 +10,9 @@ #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) +#define IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2005, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define MAX_HANDLE_REPORTS_PER_IRP 10 namespace kernelmode { @@ -24,7 +27,7 @@ namespace kernelmode void RunNmiCallbacks(); void VerifySystemModules(); - bool QueueCallbackReportIrp( PHANDLE Event ); + void QueryReportQueue(); void NotifyDriverOnProcessLaunch(); void CompleteQueuedCallbackReports(); void EnableProcessLoadNotifyCallbacks(); diff --git a/user/report.h b/user/report.h index ac8d1c7..9be491b 100644 --- a/user/report.h +++ b/user/report.h @@ -17,6 +17,7 @@ #define REPORT_PATTERN_SCAN_FAILURE 40 #define REPORT_NMI_CALLBACK_FAILURE 50 #define REPORT_MODULE_VALIDATION_FAILURE 60 +#define REPORT_ILLEGAL_HANDLE_OPERATION 70 @@ -106,6 +107,12 @@ namespace global CHAR driver_name[ 128 ]; }; + struct OPEN_HANDLE_FAILURE_REPORT_HEADER + { + INT count; + + }; + struct OPEN_HANDLE_FAILURE_REPORT { INT report_code;