refactor the old trash module validation code

This commit is contained in:
donnaskiez 2024-05-05 22:36:25 +10:00
parent e393666166
commit 80b34ea2f1
3 changed files with 80 additions and 283 deletions

View file

@ -2156,6 +2156,12 @@ BuildHeartbeatPacket(_In_ PHEARTBEAT_CONFIGURATION Configuration)
/* This routine always runs at DPC level */ /* This routine always runs at DPC level */
KeAcquireSpinLockAtDpcLevel(&queue->lock); KeAcquireSpinLockAtDpcLevel(&queue->lock);
/*
* Its important to remember that since we query the packet metrics before
* the metrics are incremented for the current packets they will always be 1
* less then whats noted.
*/
packet->total_heartbeats_completed = queue->total_heartbeats_completed; packet->total_heartbeats_completed = queue->total_heartbeats_completed;
packet->total_irps_completed = queue->total_irps_completed; packet->total_irps_completed = queue->total_irps_completed;
packet->total_reports_completed = queue->total_reports_completed; packet->total_reports_completed = queue->total_reports_completed;

View file

@ -43,9 +43,6 @@ CHAR WHITELISTED_MODULES[WHITELISTED_MODULE_COUNT][MODULE_MAX_STRING_SIZE] = {
#define MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE 128 #define MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE 128
#define REASON_NO_BACKING_MODULE 1
#define REASON_INVALID_IOCTL_DISPATCH 2
#define SYSTEM_IDLE_PROCESS_ID 0 #define SYSTEM_IDLE_PROCESS_ID 0
#define SYSTEM_PROCESS_ID 4 #define SYSTEM_PROCESS_ID 4
#define SVCHOST_PROCESS_ID 8 #define SVCHOST_PROCESS_ID 8
@ -77,19 +74,6 @@ typedef struct _NMI_CONTEXT {
} NMI_CONTEXT, *PNMI_CONTEXT; } NMI_CONTEXT, *PNMI_CONTEXT;
typedef struct _INVALID_DRIVER {
struct _INVALID_DRIVER* next;
INT reason;
PDRIVER_OBJECT driver;
} INVALID_DRIVER, *PINVALID_DRIVER;
typedef struct _INVALID_DRIVERS_HEAD {
PINVALID_DRIVER first_entry;
INT count;
} INVALID_DRIVERS_HEAD, *PINVALID_DRIVERS_HEAD;
STATIC STATIC
NTSTATUS NTSTATUS
PopulateWhitelistedModuleBuffer(_Inout_ PVOID Buffer, PopulateWhitelistedModuleBuffer(_Inout_ PVOID Buffer,
@ -97,40 +81,7 @@ PopulateWhitelistedModuleBuffer(_Inout_ PVOID Buffer,
STATIC STATIC
NTSTATUS NTSTATUS
ValidateDriverIOCTLDispatchRegion(_In_ PDRIVER_OBJECT Driver, ValidateDriverObjectsWrapper(_In_ PSYSTEM_MODULES SystemModules);
_In_ PSYSTEM_MODULES Modules,
_In_ PWHITELISTED_REGIONS WhitelistedRegions,
_Out_ PBOOLEAN Flag);
STATIC
VOID
InitDriverList(_Inout_ PINVALID_DRIVERS_HEAD ListHead);
STATIC
NTSTATUS
AddDriverToList(_Inout_ PINVALID_DRIVERS_HEAD InvalidDriversHead,
_In_ PDRIVER_OBJECT Driver,
_In_ INT Reason);
STATIC
VOID
RemoveInvalidDriverFromList(_Inout_ PINVALID_DRIVERS_HEAD InvalidDriversHead);
STATIC
VOID
EnumerateInvalidDrivers(_In_ PINVALID_DRIVERS_HEAD InvalidDriversHead);
STATIC
NTSTATUS
ValidateDriverObjectHasBackingModule(_In_ PSYSTEM_MODULES ModuleInformation,
_In_ PDRIVER_OBJECT DriverObject,
_Out_ PBOOLEAN Result);
STATIC
NTSTATUS
ValidateDriverObjectsWrapper(_In_ PSYSTEM_MODULES SystemModules,
_Inout_ PINVALID_DRIVERS_HEAD
InvalidDriverListHead);
STATIC STATIC
NTSTATUS NTSTATUS
@ -167,12 +118,6 @@ ValidateThreadViaKernelApcCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
# pragma alloc_text(PAGE, FindSystemModuleByName) # pragma alloc_text(PAGE, FindSystemModuleByName)
# pragma alloc_text(PAGE, PopulateWhitelistedModuleBuffer) # pragma alloc_text(PAGE, PopulateWhitelistedModuleBuffer)
# pragma alloc_text(PAGE, ValidateDriverIOCTLDispatchRegion)
# pragma alloc_text(PAGE, InitDriverList)
# pragma alloc_text(PAGE, AddDriverToList)
# pragma alloc_text(PAGE, RemoveInvalidDriverFromList)
# pragma alloc_text(PAGE, EnumerateInvalidDrivers)
# pragma alloc_text(PAGE, ValidateDriverObjectHasBackingModule)
# pragma alloc_text(PAGE, GetSystemModuleInformation) # pragma alloc_text(PAGE, GetSystemModuleInformation)
# pragma alloc_text(PAGE, ValidateDriverObjectsWrapper) # pragma alloc_text(PAGE, ValidateDriverObjectsWrapper)
# pragma alloc_text(PAGE, HandleValidateDriversIOCTL) # pragma alloc_text(PAGE, HandleValidateDriversIOCTL)
@ -267,27 +212,21 @@ GetDriverMajorDispatchFunction(_In_ PDRIVER_OBJECT Driver)
} }
STATIC STATIC
NTSTATUS BOOLEAN
ValidateDriverIOCTLDispatchRegion(_In_ PDRIVER_OBJECT Driver, DoesDriverHaveInvalidDispatchRoutine(_In_ PDRIVER_OBJECT Driver,
_In_ PSYSTEM_MODULES Modules, _In_ PSYSTEM_MODULES Modules,
_In_ PWHITELISTED_REGIONS WhitelistedRegions, _In_ PWHITELISTED_REGIONS Regions)
_Out_ PBOOLEAN Flag)
{ {
PAGED_CODE(); PAGED_CODE();
if (!Modules || !Driver || !Flag || !WhitelistedRegions)
return STATUS_INVALID_PARAMETER;
UINT64 dispatch_function = 0; UINT64 dispatch_function = 0;
UINT64 module_base = 0; UINT64 module_base = 0;
UINT64 module_end = 0; UINT64 module_end = 0;
*Flag = TRUE;
dispatch_function = GetDriverMajorDispatchFunction(Driver); dispatch_function = GetDriverMajorDispatchFunction(Driver);
if (dispatch_function == NULL) if (dispatch_function == NULL)
return STATUS_SUCCESS; return FALSE;
PRTL_MODULE_EXTENDED_INFO module = PRTL_MODULE_EXTENDED_INFO module =
(PRTL_MODULE_EXTENDED_INFO)Modules->address; (PRTL_MODULE_EXTENDED_INFO)Modules->address;
@ -299,14 +238,14 @@ ValidateDriverIOCTLDispatchRegion(_In_ PDRIVER_OBJECT Driver,
/* make sure our driver has a device object which is required /* make sure our driver has a device object which is required
* for IOCTL */ * for IOCTL */
if (Driver->DeviceObject == NULL) if (Driver->DeviceObject == NULL)
return STATUS_SUCCESS; return FALSE;
module_base = (UINT64)module[index].ImageBase; module_base = (UINT64)module[index].ImageBase;
module_end = module_base + module[index].ImageSize; module_end = module_base + module[index].ImageSize;
/* firstly, check if its inside its own module */ /* firstly, check if its inside its own module */
if (dispatch_function >= module_base && dispatch_function <= module_end) if (dispatch_function >= module_base && dispatch_function <= module_end)
return STATUS_SUCCESS; return FALSE;
/* /*
* The WDF framework and other low level drivers often hook the * The WDF framework and other low level drivers often hook the
@ -324,94 +263,28 @@ ValidateDriverIOCTLDispatchRegion(_In_ PDRIVER_OBJECT Driver,
* should implement a function which checks for standard hook * should implement a function which checks for standard hook
* implementations like mov rax jmp rax etc. * implementations like mov rax jmp rax etc.
*/ */
for (INT index = 0; index < WHITELISTED_MODULE_COUNT; index++) { for (UINT32 index = 0; index < WHITELISTED_MODULE_COUNT; index++) {
if (dispatch_function >= WhitelistedRegions[index].base && if (dispatch_function >= Regions[index].base &&
dispatch_function <= WhitelistedRegions[index].end) dispatch_function <= Regions[index].end)
return STATUS_SUCCESS; return FALSE;
} }
DEBUG_WARNING("Driver with invalid dispatch routine found: %s", DEBUG_WARNING("Driver with invalid dispatch routine found: %s",
module[index].FullPathName); module[index].FullPathName);
*Flag = FALSE; return TRUE;
return STATUS_SUCCESS;
} }
return STATUS_SUCCESS; return FALSE;
} }
STATIC STATIC
VOID BOOLEAN
InitDriverList(_Inout_ PINVALID_DRIVERS_HEAD ListHead) DoesDriverObjectHaveBackingModule(_In_ PSYSTEM_MODULES ModuleInformation,
_In_ PDRIVER_OBJECT DriverObject)
{ {
PAGED_CODE(); PAGED_CODE();
ListHead->count = 0;
ListHead->first_entry = NULL;
}
STATIC
NTSTATUS
AddDriverToList(_Inout_ PINVALID_DRIVERS_HEAD InvalidDriversHead,
_In_ PDRIVER_OBJECT Driver,
_In_ INT Reason)
{
PAGED_CODE();
PINVALID_DRIVER new_entry =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(INVALID_DRIVER),
INVALID_DRIVER_LIST_ENTRY_POOL);
if (!new_entry)
return STATUS_MEMORY_NOT_ALLOCATED;
new_entry->driver = Driver;
new_entry->reason = Reason;
new_entry->next = InvalidDriversHead->first_entry;
InvalidDriversHead->first_entry = new_entry;
return STATUS_SUCCESS;
}
STATIC
VOID
RemoveInvalidDriverFromList(_Inout_ PINVALID_DRIVERS_HEAD InvalidDriversHead)
{
PAGED_CODE();
if (InvalidDriversHead->first_entry) {
PINVALID_DRIVER entry = InvalidDriversHead->first_entry;
InvalidDriversHead->first_entry = InvalidDriversHead->first_entry->next;
ImpExFreePoolWithTag(entry, INVALID_DRIVER_LIST_ENTRY_POOL);
}
}
STATIC
VOID
EnumerateInvalidDrivers(_In_ PINVALID_DRIVERS_HEAD InvalidDriversHead)
{
PAGED_CODE();
PINVALID_DRIVER entry = InvalidDriversHead->first_entry;
while (entry != NULL) {
DEBUG_VERBOSE("Invalid Driver: %wZ", entry->driver->DriverName);
entry = entry->next;
}
}
STATIC
NTSTATUS
ValidateDriverObjectHasBackingModule(_In_ PSYSTEM_MODULES ModuleInformation,
_In_ PDRIVER_OBJECT DriverObject,
_Out_ PBOOLEAN Result)
{
PAGED_CODE();
if (!ModuleInformation || !DriverObject || !Result)
return STATUS_INVALID_PARAMETER;
PRTL_MODULE_EXTENDED_INFO module = PRTL_MODULE_EXTENDED_INFO module =
(PRTL_MODULE_EXTENDED_INFO)ModuleInformation->address; (PRTL_MODULE_EXTENDED_INFO)ModuleInformation->address;
@ -420,16 +293,14 @@ ValidateDriverObjectHasBackingModule(_In_ PSYSTEM_MODULES ModuleInformation,
return STATUS_INVALID_MEMBER; return STATUS_INVALID_MEMBER;
if (module[index].ImageBase == DriverObject->DriverStart) { if (module[index].ImageBase == DriverObject->DriverStart) {
*Result = TRUE; return TRUE;
return STATUS_SUCCESS;
} }
} }
DEBUG_WARNING("Driver found with no backing system image at address: %llx", DEBUG_WARNING("Driver found with no backing system image at address: %llx",
(UINT64)DriverObject->DriverStart); (UINT64)DriverObject->DriverStart);
*Result = FALSE; return FALSE;
return STATUS_SUCCESS;
} }
FORCEINLINE FORCEINLINE
@ -489,58 +360,63 @@ GetSystemModuleInformation(_Out_ PSYSTEM_MODULES ModuleInformation)
STATIC STATIC
VOID VOID
ValidateDriverObjects(_In_ PSYSTEM_MODULES SystemModules, ReportInvalidDriverObject(_In_ PDRIVER_OBJECT Driver, _In_ UINT32 ReportSubType)
_In_ POBJECT_DIRECTORY_ENTRY Entry,
_Inout_ PINVALID_DRIVERS_HEAD Head,
_In_ PVOID Whitelist)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; PMODULE_VALIDATION_FAILURE report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(MODULE_VALIDATION_FAILURE),
POOL_TAG_INTEGRITY);
if (!Entry) if (!report)
return; return;
POBJECT_DIRECTORY_ENTRY sub_entry = Entry; INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header,
REPORT_MODULE_VALIDATION_FAILURE,
ReportSubType);
while (sub_entry) { report->driver_base_address = Driver->DriverStart;
BOOLEAN flag = FALSE; report->driver_size = Driver->DriverSize;
PDRIVER_OBJECT current_driver = sub_entry->Object;
status = ValidateDriverObjectHasBackingModule( ANSI_STRING string = {0};
SystemModules, current_driver, &flag); string.Length = 0;
string.MaximumLength = MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE;
string.Buffer = &report->driver_name;
if (!NT_SUCCESS(status)) { /* Continue regardless of result */
DEBUG_ERROR( ImpRtlUnicodeStringToAnsiString(&string, &Driver->DriverName, FALSE);
"ValidateDriverObjectHasBackingModule failed with status %x", IrpQueueCompletePacket(report, sizeof(MODULE_VALIDATION_FAILURE));
status); }
return;
FORCEINLINE
STATIC
POBJECT_DIRECTORY_ENTRY
GetNextObject(_In_ POBJECT_DIRECTORY_ENTRY Entry)
{
return Entry->ChainLink;
}
STATIC
VOID
ValidateDriverObjects(_In_ PSYSTEM_MODULES Modules,
_In_ POBJECT_DIRECTORY_ENTRY Entry,
_In_ PVOID Whitelist)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
POBJECT_DIRECTORY_ENTRY entry = Entry;
while (entry) {
PDRIVER_OBJECT driver = entry->Object;
if (!DoesDriverObjectHaveBackingModule(Modules, driver)) {
ReportInvalidDriverObject(driver, REPORT_SUBTYPE_NO_BACKING_MODULE);
} }
if (!flag) { if (!DoesDriverHaveInvalidDispatchRoutine(driver, Modules, Whitelist)) {
status = ReportInvalidDriverObject(driver, REPORT_SUBTYPE_INVALID_DISPATCH);
AddDriverToList(Head, current_driver, REASON_NO_BACKING_MODULE);
if (NT_SUCCESS(status))
Head->count++;
} }
status = ValidateDriverIOCTLDispatchRegion( entry = GetNextObject(entry);
current_driver, SystemModules, Whitelist, &flag);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR(
"ValidateDriverIOCTLDispatchRegion failed with status %x",
status);
return;
}
if (!flag) {
status = AddDriverToList(
Head, current_driver, REASON_INVALID_IOCTL_DISPATCH);
if (NT_SUCCESS(status))
Head->count++;
}
sub_entry = sub_entry->ChainLink;
} }
} }
@ -550,14 +426,10 @@ ValidateDriverObjects(_In_ PSYSTEM_MODULES SystemModules,
*/ */
STATIC STATIC
NTSTATUS NTSTATUS
ValidateDriverObjectsWrapper(_In_ PSYSTEM_MODULES SystemModules, ValidateDriverObjectsWrapper(_In_ PSYSTEM_MODULES SystemModules)
_Inout_ PINVALID_DRIVERS_HEAD Head)
{ {
PAGED_CODE(); PAGED_CODE();
if (!SystemModules || !Head)
return STATUS_INVALID_PARAMETER;
HANDLE handle = NULL; HANDLE handle = NULL;
OBJECT_ATTRIBUTES attributes = {0}; OBJECT_ATTRIBUTES attributes = {0};
PVOID directory = {0}; PVOID directory = {0};
@ -624,8 +496,7 @@ ValidateDriverObjectsWrapper(_In_ PSYSTEM_MODULES SystemModules,
for (INT index = 0; index < NUMBER_HASH_BUCKETS; index++) { for (INT index = 0; index < NUMBER_HASH_BUCKETS; index++) {
POBJECT_DIRECTORY_ENTRY entry = directory_object->HashBuckets[index]; POBJECT_DIRECTORY_ENTRY entry = directory_object->HashBuckets[index];
ValidateDriverObjects( ValidateDriverObjects(SystemModules, entry, whitelisted_regions_buffer);
SystemModules, entry, Head, whitelisted_regions_buffer);
} }
end: end:
@ -640,61 +511,14 @@ end:
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
FORCEINLINE
STATIC
INT
GetModuleCount(_In_ PINVALID_DRIVERS_HEAD Head)
{
return Head->count >= MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT
? MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT
: Head->count;
}
STATIC
VOID
ReportInvalidDriverObject(_In_ PINVALID_DRIVERS_HEAD Head)
{
PMODULE_VALIDATION_FAILURE report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(MODULE_VALIDATION_FAILURE),
POOL_TAG_INTEGRITY);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header,
REPORT_MODULE_VALIDATION_FAILURE,
Head->first_entry->reason);
DEBUG_INFO("packet type: %hx", report->header.packet_type);
DEBUG_INFO("report code: %lx", report->report_header.report_code);
DEBUG_INFO("report subcode: %lx", report->report_header.report_sub_type);
report->driver_base_address = Head->first_entry->driver->DriverStart;
report->driver_size = Head->first_entry->driver->DriverSize;
ANSI_STRING string = {0};
string.Length = 0;
string.MaximumLength = MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE;
string.Buffer = &report->driver_name;
/* Continue regardless of result */
ImpRtlUnicodeStringToAnsiString(
&string, &Head->first_entry->driver->DriverName, FALSE);
IrpQueueCompletePacket(report, sizeof(MODULE_VALIDATION_FAILURE));
}
NTSTATUS NTSTATUS
HandleValidateDriversIOCTL() HandleValidateDriversIOCTL()
{ {
PAGED_CODE(); PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG buffer_size = 0; ULONG buffer_size = 0;
SYSTEM_MODULES system_modules = {0}; SYSTEM_MODULES system_modules = {0};
PINVALID_DRIVERS_HEAD head = NULL;
/* Fix annoying visual studio linting error */ /* Fix annoying visual studio linting error */
RtlZeroMemory(&system_modules, sizeof(SYSTEM_MODULES)); RtlZeroMemory(&system_modules, sizeof(SYSTEM_MODULES));
@ -706,52 +530,16 @@ HandleValidateDriversIOCTL()
return status; return status;
} }
head = ImpExAllocatePool2(POOL_FLAG_NON_PAGED, status = ValidateDriverObjectsWrapper(&system_modules);
sizeof(INVALID_DRIVERS_HEAD),
INVALID_DRIVER_LIST_HEAD_POOL);
if (!head) {
ImpExFreePoolWithTag(system_modules.address, SYSTEM_MODULES_POOL);
return STATUS_MEMORY_NOT_ALLOCATED;
}
/*
* Use a linked list here so that so we have easy access to the invalid
* drivers which we can then use to copy the drivers logic for further
* analysis in identifying drivers specifically used for the purpose of
* cheating
*/
InitDriverList(head);
status = ValidateDriverObjectsWrapper(&system_modules, head);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ValidateDriverObjects failed with status %x", status); DEBUG_ERROR("ValidateDriverObjects failed with status %x", status);
goto end; goto end;
} }
if (head->count == 0) {
DEBUG_INFO("Found no invalid drivers on the system.");
goto end;
}
for (INT index = 0; index < head->count; index++) {
/* make sure we free any non reported modules */
if (index >= MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT) {
RemoveInvalidDriverFromList(head);
continue;
}
ReportInvalidDriverObject(head);
RemoveInvalidDriverFromList(head);
}
end: end:
ImpExFreePoolWithTag(head, INVALID_DRIVER_LIST_HEAD_POOL);
ImpExFreePoolWithTag(system_modules.address, SYSTEM_MODULES_POOL); ImpExFreePoolWithTag(system_modules.address, SYSTEM_MODULES_POOL);
return status; return status;
} }

View file

@ -14,6 +14,9 @@
#define REPORT_DATA_TABLE_ROUTINE 130 #define REPORT_DATA_TABLE_ROUTINE 130
#define REPORT_INVALID_PROCESS_MODULE 140 #define REPORT_INVALID_PROCESS_MODULE 140
#define REPORT_SUBTYPE_NO_BACKING_MODULE 0x0
#define REPORT_SUBTYPE_INVALID_DISPATCH 0x1
#define PACKET_TYPE_REPORT 0x0 #define PACKET_TYPE_REPORT 0x0
#define PACKET_TYPE_HEARTBEAT 0x1 #define PACKET_TYPE_HEARTBEAT 0x1