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

View file

@ -5,6 +5,20 @@
#include <wdftypes.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
{
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

View file

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

View file

@ -5,9 +5,6 @@
#include <wdftypes.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(
_In_ LONG NewProcessId
);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<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:
_logger.LogError("Invalid report code received");
goto end;

View file

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

View file

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

View file

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