This commit is contained in:
lhodges1 2023-08-19 19:44:42 +10:00
parent 63a13f0c4d
commit 4321236a0f
8 changed files with 137 additions and 11 deletions

View file

@ -30,6 +30,7 @@ NTSTATUS DeviceControl(
case IOCTL_VALIDATE_DRIVER_OBJECTS:
/* KeWaitForSingleObject with infinite time must be called from IRQL <= APC_LEVEL */
PAGED_CODE();
/*

View file

@ -3,6 +3,47 @@
#include "nmi.h"
#include "common.h"
NTSTATUS ValidateDriverIOCTLDispatchRegion(
_In_ PDRIVER_OBJECT Driver,
_In_ PSYSTEM_MODULES Modules,
_In_ PBOOLEAN Flag
)
{
NTSTATUS status;
UINT64 current_function;
UINT64 base = ( UINT64 )Driver->DriverStart;
UINT64 end = base + Driver->DriverSize;
*Flag = TRUE;
/*
* If the dispatch routine points to a location that is not in the confines of
* the module, report it. Basic check but every effective for catching driver
* dispatch hooking.
*/
for ( INT index = 0; index < IRP_MJ_MAXIMUM_FUNCTION + 1; index++ )
{
current_function = *(UINT64*)
( ( UINT64 )Driver->MajorFunction + index * sizeof( PVOID ) );
DEBUG_LOG( "Current function: %llx", current_function );
if ( current_function == NULL )
continue;
if ( current_function >= base && current_function <= end )
{
DEBUG_LOG( "THIS ADDRESS IS INSIDE ITS REGIUON :)" );
continue;
}
DEBUG_ERROR( "Driver with invalid IOCTL dispatch routine found" );
*Flag = FALSE;
}
}
VOID InitDriverList(
_In_ PINVALID_DRIVERS_HEAD ListHead
)
@ -13,7 +54,8 @@ VOID InitDriverList(
VOID AddDriverToList(
_In_ PINVALID_DRIVERS_HEAD InvalidDriversHead,
_In_ PDRIVER_OBJECT Driver
_In_ PDRIVER_OBJECT Driver,
_In_ INT Reason
)
{
PINVALID_DRIVER new_entry = ExAllocatePool2(
@ -26,6 +68,7 @@ VOID AddDriverToList(
return;
new_entry->driver = Driver;
new_entry->reason = Reason;
new_entry->next = InvalidDriversHead->first_entry;
InvalidDriversHead->first_entry = new_entry;
}
@ -215,6 +258,8 @@ NTSTATUS ValidateDriverObjects(
PDRIVER_OBJECT current_driver = sub_entry->Object;
BOOLEAN flag;
/* validate driver has backing module */
if ( !NT_SUCCESS( ValidateDriverObjectHasBackingModule(
SystemModules,
current_driver,
@ -231,7 +276,32 @@ NTSTATUS ValidateDriverObjects(
if ( !flag )
{
InvalidDriverListHead->count += 1;
AddDriverToList( InvalidDriverListHead, current_driver );
AddDriverToList( InvalidDriverListHead, current_driver, REASON_NO_BACKING_MODULE );
}
/* validate drivers IOCTL dispatch routines */
if ( !NT_SUCCESS( ValidateDriverIOCTLDispatchRegion(
current_driver,
SystemModules,
&flag
) ) )
{
DEBUG_LOG( "Error validating drivers IOCTL routines" );
ExReleasePushLockExclusiveEx( &directory_object->Lock, 0 );
ObDereferenceObject( directory );
ZwClose( handle );
return STATUS_ABANDONED;
}
if ( !flag )
{
InvalidDriverListHead->count += 1;
AddDriverToList( InvalidDriverListHead, current_driver, REASON_INVALID_IOCTL_DISPATCH );
}
else
{
DEBUG_LOG( "All drivers have valid dispatch routines :)" );
}
sub_entry = sub_entry->ChainLink;
@ -310,6 +380,7 @@ NTSTATUS HandleValidateDriversIOCTL(
MODULE_VALIDATION_FAILURE report;
report.report_code = REPORT_MODULE_VALIDATION_FAILURE;
report.report_type = head->first_entry->reason;
report.driver_base_address = head->first_entry->driver->DriverStart;
report.driver_size = head->first_entry->driver->Size;

View file

@ -9,6 +9,9 @@
#define MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE 128
#define REASON_NO_BACKING_MODULE 1
#define REASON_INVALID_IOCTL_DISPATCH 2
typedef struct _MODULE_VALIDATION_FAILURE_HEADER
{
INT module_count;
@ -18,6 +21,7 @@ typedef struct _MODULE_VALIDATION_FAILURE_HEADER
typedef struct _MODULE_VALIDATION_FAILURE
{
INT report_code;
INT report_type;
UINT64 driver_base_address;
UINT64 driver_size;
PCHAR driver_name[ 128 ];
@ -27,6 +31,7 @@ typedef struct _MODULE_VALIDATION_FAILURE
typedef struct _INVALID_DRIVER
{
struct _INVALID_DRIVER* next;
INT reason;
PDRIVER_OBJECT driver;
}INVALID_DRIVER, * PINVALID_DRIVER;

View file

@ -44,5 +44,28 @@ namespace service
public int SignatureId;
public UInt64 Address;
}
public struct NMI_CALLBACK_FAILURE
{
public int ReportCode;
public int WereNmisDisabled;
public UInt64 KThreadAddress;
public UInt64 InvalidRip;
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct MODULE_VALIDATION_FAILURE
{
[FieldOffset(0)]
public int ReportCode;
[FieldOffset(0)]
public int ReportType;
[FieldOffset(0)]
public UInt64 DriverBaseAddress;
[FieldOffset(0)]
public UInt64 DriverSize;
[FieldOffset(0)]
public fixed char ModuleName[128];
}
}
}

View file

@ -16,10 +16,12 @@ namespace service
private byte[] _headerBuf;
private int _headerBufSize;
private const int REPORT_CODE_MODULE_VERIFICATION = 10;
private const int REPORT_CODE_START_ADDRESS_VERIFICATION = 20;
private const int REPORT_PROCESS_MODULE_FAILURE = 10;
private const int REPORT_PROCESS_THREAD_START_ADDRESS_FAILURE = 20;
private const int REPORT_PAGE_PROTECTION_VERIFICATION = 30;
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 MESSAGE_TYPE_REPORT = 1;
private const int MESSAGE_TYPE_REQUEST = 2;
@ -94,7 +96,7 @@ namespace service
switch (reportCode)
{
case REPORT_CODE_MODULE_VERIFICATION:
case REPORT_PROCESS_MODULE_FAILURE:
var checksumFailurePacket = BytesToStructure<MODULE_VERIFICATION_CHECKSUM_FAILURE>();
@ -108,7 +110,7 @@ namespace service
goto end;
case REPORT_CODE_START_ADDRESS_VERIFICATION:
case REPORT_PROCESS_THREAD_START_ADDRESS_FAILURE:
var startAddressFailurePacket = BytesToStructure<PROCESS_THREAD_START_FAILURE>();
@ -143,6 +145,29 @@ namespace service
goto end;
case REPORT_NMI_CALLBACK_FAILURE:
var nmiCallbackFailure = BytesToStructure<NMI_CALLBACK_FAILURE>();
_logger.LogInformation("Report code: {0}, WereNmisDisabled: {1}, KThreadAddress: {2}, InvalidRip: {3}",
nmiCallbackFailure.ReportCode,
nmiCallbackFailure.WereNmisDisabled,
nmiCallbackFailure.KThreadAddress,
nmiCallbackFailure.InvalidRip);
goto end;
case REPORT_KERNEL_MODULE_FAILURE:
var kernelModuleFailure = BytesToStructure<MODULE_VALIDATION_FAILURE>();
_logger.LogInformation("Report code: {0}, DriverBaseAddress: {1}, DriverSize: {2}",
kernelModuleFailure.ReportCode,
kernelModuleFailure.DriverBaseAddress,
kernelModuleFailure.DriverSize);
goto end;
default:
_logger.LogError("Invalid report code received");
goto end;

View file

@ -53,6 +53,11 @@ void kernelmode::Driver::RunNmiCallbacks()
this->report_interface->ReportViolation( &report );
}
/*
* 1. Checks that every device object has a system module to back it
* 2. Checks the IOCTL dispatch routines to ensure they lie within the module
*/
void kernelmode::Driver::VerifySystemModules()
{
BOOLEAN status;
@ -154,10 +159,6 @@ void kernelmode::Driver::CheckForHypervisor()
{
}
void kernelmode::Driver::VerifySystemModulesIOCTLDispatchHandler()
{
}
void kernelmode::Driver::CheckDriverHeartbeat()
{
}

View file

@ -28,7 +28,6 @@ namespace kernelmode
void DisableProcessLoadNotifyCallbacks();
void ValidateKPRCBThreads();
void CheckForHypervisor();
void VerifySystemModulesIOCTLDispatchHandler();
void CheckDriverHeartbeat();
/* todo: driver integrity check */
};

View file

@ -100,6 +100,7 @@ namespace global
struct MODULE_VALIDATION_FAILURE
{
INT report_code;
INT report_type;
UINT64 driver_base_address;
UINT64 driver_size;
BYTE driver_name[ 128 ];