This commit is contained in:
lhodges1 2023-08-21 01:04:53 +10:00
parent ef4127c167
commit 0d853853bf
13 changed files with 174 additions and 26 deletions

View file

@ -7,6 +7,8 @@
PQUEUE_HEAD report_queue = NULL; PQUEUE_HEAD report_queue = NULL;
KGUARDED_MUTEX mutex;
VOID InitCallbackReportQueue( PBOOLEAN Status ) VOID InitCallbackReportQueue( PBOOLEAN Status )
{ {
report_queue = QueueCreate(); report_queue = QueueCreate();
@ -14,6 +16,8 @@ VOID InitCallbackReportQueue( PBOOLEAN Status )
if ( report_queue == NULL ) if ( report_queue == NULL )
*Status = FALSE; *Status = FALSE;
KeInitializeGuardedMutex( &mutex );
*Status = TRUE; *Status = TRUE;
} }
@ -22,16 +26,65 @@ VOID DeleteCallbackReportQueueHead()
ExFreePoolWithTag( report_queue, QUEUE_POOL_TAG ); 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 ); QueuePush( report_queue, Report );
} }
PVOID PopFirstReportFromQueue( report_queue ) POPEN_HANDLE_FAILURE_REPORT PopFirstReportFromQueue()
{ {
return QueuePop( report_queue ); 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( VOID ObPostOpCallbackRoutine(
_In_ PVOID RegistrationContext, _In_ PVOID RegistrationContext,
_In_ POB_POST_OPERATION_INFORMATION OperationInformation _In_ POB_POST_OPERATION_INFORMATION OperationInformation
@ -90,9 +143,25 @@ OB_PREOP_CALLBACK_STATUS ObPreOpCallbackRoutine(
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = deny_access; OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = deny_access;
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = deny_access; OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = deny_access;
DEBUG_LOG( "handle stripped from: %s", process_creator_name ); 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; return OB_PREOP_SUCCESS;
} }
@ -133,6 +202,6 @@ VOID ProcessCreateNotifyRoutine(
{ {
parent_process_id = PsGetProcessId( target_process ); parent_process_id = PsGetProcessId( target_process );
UpdateProtectedProcessId( parent_process_id ); 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 );
} }
} }

View file

@ -5,6 +5,20 @@
#include <wdftypes.h> #include <wdftypes.h>
#include <wdf.h> #include <wdf.h>
#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 typedef struct _OPEN_HANDLE_FAILURE_REPORT
{ {
INT report_code; INT report_code;
@ -12,7 +26,7 @@ typedef struct _OPEN_HANDLE_FAILURE_REPORT
LONG process_id; LONG process_id;
LONG thread_id; LONG thread_id;
LONG desired_access; LONG desired_access;
CHAR process_name[ 64 ]; CHAR process_name[ HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH ];
}OPEN_HANDLE_FAILURE_REPORT, *POPEN_HANDLE_FAILURE_REPORT; }OPEN_HANDLE_FAILURE_REPORT, *POPEN_HANDLE_FAILURE_REPORT;
@ -44,4 +58,8 @@ OB_PREOP_CALLBACK_STATUS ObPreOpCallbackRoutine(
VOID InitCallbackReportQueue(PBOOLEAN Status); VOID InitCallbackReportQueue(PBOOLEAN Status);
VOID DeleteCallbackReportQueueHead(); VOID DeleteCallbackReportQueueHead();
NTSTATUS HandlePeriodicCallbackReportQueue(
_In_ PIRP Irp
);
#endif #endif

View file

@ -10,6 +10,9 @@ LONG protected_process_id;
LONG protected_process_parent_id; LONG protected_process_parent_id;
KGUARDED_MUTEX mutex; 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( VOID UpdateProtectedProcessId(
_In_ LONG NewProcessId _In_ LONG NewProcessId
) )

View file

@ -5,9 +5,6 @@
#include <wdftypes.h> #include <wdftypes.h>
#include <wdf.h> #include <wdf.h>
UNICODE_STRING DEVICE_NAME = RTL_CONSTANT_STRING( L"\\Device\\DonnaAC" );
UNICODE_STRING DEVICE_SYMBOLIC_LINK = RTL_CONSTANT_STRING( L"\\??\\DonnaAC" );
VOID UpdateProtectedProcessId( VOID UpdateProtectedProcessId(
_In_ LONG NewProcessId _In_ LONG NewProcessId
); );

View file

@ -5,6 +5,7 @@
#include "nmi.h" #include "nmi.h"
#include "modules.h" #include "modules.h"
#include "driver.h" #include "driver.h"
#include "callbacks.h"
NTSTATUS DeviceControl( NTSTATUS DeviceControl(
_In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_OBJECT DriverObject,
@ -95,6 +96,14 @@ NTSTATUS DeviceControl(
UpdateProtectedProcessId( information->protected_process_id ); UpdateProtectedProcessId( information->protected_process_id );
break; 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: default:
DEBUG_ERROR( "Invalid IOCTL passed to driver" ); DEBUG_ERROR( "Invalid IOCTL passed to driver" );
@ -102,7 +111,6 @@ NTSTATUS DeviceControl(
} }
end: end:
DEBUG_LOG( "completing irp request" );
Irp->IoStatus.Status = status; Irp->IoStatus.Status = status;
IoCompleteRequest( Irp, IO_NO_INCREMENT ); IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status; return status;

View file

@ -10,6 +10,7 @@
#define IOCCTL_RUN_NMI_CALLBACKS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2001, METHOD_BUFFERED, FILE_ANY_ACCESS) #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_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_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 typedef struct _DRIVER_INITIATION_INFORMATION
{ {

View file

@ -1,5 +1,9 @@
#include "queue.h" #include "queue.h"
/*
* Basic thread-safe queue implementation that can be used to create queues for any data.
*/
PQUEUE_HEAD QueueCreate() PQUEUE_HEAD QueueCreate()
{ {
PQUEUE_HEAD head = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( PQUEUE_HEAD ), QUEUE_POOL_TAG ); 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->end = NULL;
head->start = NULL; head->start = NULL;
head->entries = 0;
KeInitializeSpinLock( head->lock ); KeInitializeSpinLock( head->lock );
@ -28,6 +33,8 @@ VOID QueuePush(
if ( !temp ) if ( !temp )
goto end; goto end;
Head->entries += 1;
temp->data = Data; temp->data = Data;
temp->lock = Head->lock; temp->lock = Head->lock;
@ -56,6 +63,8 @@ PVOID QueuePop(
if ( temp == NULL ) if ( temp == NULL )
goto end; goto end;
Head->entries -= 1;
data = temp->data; data = temp->data;
Head->start = temp->next; Head->start = temp->next;

View file

@ -18,10 +18,11 @@ typedef struct QUEUE_HEAD
struct _QUEUE_NODE* start; struct _QUEUE_NODE* start;
struct _QUEUE_NODE* end; struct _QUEUE_NODE* end;
PKSPIN_LOCK lock; PKSPIN_LOCK lock;
INT entries;
}QUEUE_HEAD, *PQUEUE_HEAD; }QUEUE_HEAD, *PQUEUE_HEAD;
PQUEUE_NODE QueueCreate(); PQUEUE_HEAD QueueCreate();
VOID QueuePush( VOID QueuePush(
_In_ PQUEUE_HEAD Head, _In_ PQUEUE_HEAD Head,

View file

@ -1,4 +1,5 @@
using System; using Serilog;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
@ -59,5 +60,17 @@ namespace service
public long DriverSize; public long DriverSize;
public fixed char ModuleName[128]; 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];
}
} }
} }

View file

@ -23,6 +23,7 @@ namespace service
private const int REPORT_PATTERN_SCAN_FAILURE = 40; private const int REPORT_PATTERN_SCAN_FAILURE = 40;
private const int REPORT_NMI_CALLBACK_FAILURE = 50; private const int REPORT_NMI_CALLBACK_FAILURE = 50;
private const int REPORT_KERNEL_MODULE_FAILURE = 60; 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_REPORT = 1;
private const int MESSAGE_TYPE_REQUEST = 2; private const int MESSAGE_TYPE_REQUEST = 2;
@ -170,6 +171,18 @@ namespace service
goto end; goto end;
case REPORT_OPEN_HANDLE_FAILURE_REPORT:
var openHandleFailure = BytesToStructure<OPEN_HANDLE_FAILURE_REPORT>();
_logger.LogInformation("Report code: {0}, ProcessID: {1}, ThreadId: {2}, DesiredAccess{3}",
openHandleFailure.ReportCode,
openHandleFailure.ProcessId,
openHandleFailure.ThreadId,
openHandleFailure.DesiredAccess);
goto end;
default: default:
_logger.LogError("Invalid report code received"); _logger.LogError("Invalid report code received");
goto end; goto end;

View file

@ -145,42 +145,48 @@ void kernelmode::Driver::VerifySystemModules()
* modules. * modules.
*/ */
bool kernelmode::Driver::QueueCallbackReportIrp(PHANDLE Event) void kernelmode::Driver::QueryReportQueue()
{ {
if ( !Event )
return false;
OVERLAPPED io;
BOOLEAN status; BOOLEAN status;
DWORD bytes_returned; DWORD bytes_returned;
PVOID buffer;
LONG buffer_size;
global::report_structures::OPEN_HANDLE_FAILURE_REPORT report; 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( status = DeviceIoControl(
this->driver_handle, this->driver_handle,
IOCTL_MONITOR_CALLBACKS_FOR_REPORTS, IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE,
NULL, NULL,
NULL, NULL,
&report, buffer,
sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT ), buffer_size,
&bytes_returned, &bytes_returned,
&io NULL
); );
if ( status == NULL ) if ( status == NULL )
{ {
LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() ); 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 */ for ( int i = 0; i < header->count; i++ )
if ( bytes_returned == NULL ) {
return false; 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 );
} }

View file

@ -10,6 +10,9 @@
#define IOCTL_VALIDATE_DRIVER_OBJECTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2002, 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_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_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 namespace kernelmode
{ {
@ -24,7 +27,7 @@ namespace kernelmode
void RunNmiCallbacks(); void RunNmiCallbacks();
void VerifySystemModules(); void VerifySystemModules();
bool QueueCallbackReportIrp( PHANDLE Event ); void QueryReportQueue();
void NotifyDriverOnProcessLaunch(); void NotifyDriverOnProcessLaunch();
void CompleteQueuedCallbackReports(); void CompleteQueuedCallbackReports();
void EnableProcessLoadNotifyCallbacks(); void EnableProcessLoadNotifyCallbacks();

View file

@ -17,6 +17,7 @@
#define REPORT_PATTERN_SCAN_FAILURE 40 #define REPORT_PATTERN_SCAN_FAILURE 40
#define REPORT_NMI_CALLBACK_FAILURE 50 #define REPORT_NMI_CALLBACK_FAILURE 50
#define REPORT_MODULE_VALIDATION_FAILURE 60 #define REPORT_MODULE_VALIDATION_FAILURE 60
#define REPORT_ILLEGAL_HANDLE_OPERATION 70
@ -106,6 +107,12 @@ namespace global
CHAR driver_name[ 128 ]; CHAR driver_name[ 128 ];
}; };
struct OPEN_HANDLE_FAILURE_REPORT_HEADER
{
INT count;
};
struct OPEN_HANDLE_FAILURE_REPORT struct OPEN_HANDLE_FAILURE_REPORT
{ {
INT report_code; INT report_code;