coupley more reports

This commit is contained in:
donnaskiez 2024-05-15 19:48:09 +10:00
parent 3a45a9fe04
commit f7dd6ae97f
7 changed files with 236 additions and 75 deletions

View file

@ -1,6 +1,8 @@
#include "hw.h" #include "hw.h"
#include "modules.h" #include "modules.h"
#include "crypt.h"
#include "imports.h"
#define PCI_VENDOR_ID_OFFSET 0x00 #define PCI_VENDOR_ID_OFFSET 0x00
#define PCI_DEVICE_ID_OFFSET 0x02 #define PCI_DEVICE_ID_OFFSET 0x02
@ -67,11 +69,11 @@ QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
_Out_opt_ PVOID Buffer, _Out_opt_ PVOID Buffer,
_In_ UINT32 BufferLength) _In_ UINT32 BufferLength)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
KEVENT event = {0}; KEVENT event = {0};
IO_STATUS_BLOCK io = {0}; IO_STATUS_BLOCK io = {0};
PIRP irp = NULL; PIRP irp = NULL;
PIO_STACK_LOCATION io_stack_location = NULL; PIO_STACK_LOCATION packet = NULL;
if (BufferLength == 0) if (BufferLength == 0)
return STATUS_BUFFER_TOO_SMALL; return STATUS_BUFFER_TOO_SMALL;
@ -90,13 +92,12 @@ QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
io_stack_location = IoGetNextIrpStackLocation(irp); packet = IoGetNextIrpStackLocation(irp);
io_stack_location->MinorFunction = IRP_MN_READ_CONFIG; packet->MinorFunction = IRP_MN_READ_CONFIG;
io_stack_location->Parameters.ReadWriteConfig.WhichSpace = packet->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG;
PCI_WHICHSPACE_CONFIG; packet->Parameters.ReadWriteConfig.Offset = Offset;
io_stack_location->Parameters.ReadWriteConfig.Offset = Offset; packet->Parameters.ReadWriteConfig.Buffer = Buffer;
io_stack_location->Parameters.ReadWriteConfig.Buffer = Buffer; packet->Parameters.ReadWriteConfig.Length = BufferLength;
io_stack_location->Parameters.ReadWriteConfig.Length = BufferLength;
status = IoCallDriver(DeviceObject, irp); status = IoCallDriver(DeviceObject, irp);
@ -255,6 +256,38 @@ IsPciConfigurationSpaceFlagged(_In_ PPCI_COMMON_HEADER Configuration)
return FALSE; return FALSE;
} }
STATIC
VOID
ReportBlacklistedPcieDevice(_In_ PDEVICE_OBJECT DeviceObject,
_In_ PPCI_COMMON_HEADER Header)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size = CryptRequestRequiredBufferLength(
sizeof(BLACKLISTED_PCIE_DEVICE_REPORT));
PBLACKLISTED_PCIE_DEVICE_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_REPORT_PACKET(report, REPORT_BLACKLISTED_PCIE_DEVICE, 0);
report->device_object = (UINT64)DeviceObject;
report->device_id = Header->DeviceID;
report->vendor_id = Header->VendorID;
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, packet_size);
return;
}
IrpQueueSchedulePacket(report, packet_size);
}
STATIC STATIC
NTSTATUS NTSTATUS
PciDeviceQueryCallback(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context) PciDeviceQueryCallback(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
@ -283,6 +316,7 @@ PciDeviceQueryCallback(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
DeviceObject, DeviceObject,
header.DeviceID, header.DeviceID,
header.VendorID); header.VendorID);
ReportBlacklistedPcieDevice(DeviceObject, &header);
} }
return status; return status;

View file

@ -1609,7 +1609,7 @@ end:
*/ */
STATIC STATIC
VOID VOID
ReportInvalidSystemModule(_In_ PRTL_MODULE_EXTENDED_INFO Module) ReportModifiedSystemImage(_In_ PRTL_MODULE_EXTENDED_INFO Module)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size = CryptRequestRequiredBufferLength( UINT32 packet_size = CryptRequestRequiredBufferLength(
@ -1684,7 +1684,7 @@ ValidateSystemModule(_In_ PRTL_MODULE_EXTENDED_INFO Module)
else { else {
DEBUG_WARNING("**!!** Module: %s text regions are NOT valid **!!**", DEBUG_WARNING("**!!** Module: %s text regions are NOT valid **!!**",
Module->FullPathName); Module->FullPathName);
ReportInvalidSystemModule(Module); ReportModifiedSystemImage(Module);
} }
end: end:
@ -1693,6 +1693,39 @@ end:
ExFreePoolWithTag(hash, POOL_TAG_INTEGRITY); ExFreePoolWithTag(hash, POOL_TAG_INTEGRITY);
} }
STATIC
VOID
ReportModifiedSelfDriverImage(_In_ PRTL_MODULE_EXTENDED_INFO Module)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size = CryptRequestRequiredBufferLength(
sizeof(DRIVER_SELF_INTEGRITY_CHECK_REPORT));
PDRIVER_SELF_INTEGRITY_CHECK_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_REPORT_PACKET(report, REPORT_SELF_DRIVER_PATCHED, 0);
report->image_base = Module->ImageBase;
report->image_size = Module->ImageSize;
RtlCopyMemory(
report->path_name, Module->FullPathName, sizeof(report->path_name));
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, packet_size);
return;
}
IrpQueueSchedulePacket(report, packet_size);
}
NTSTATUS NTSTATUS
ValidateOurDriverImage() ValidateOurDriverImage()
{ {
@ -1750,10 +1783,13 @@ ValidateOurDriverImage()
* module error and stop the users game session ? since module .text * module error and stop the users game session ? since module .text
* section error would be a large red flag * section error would be a large red flag
*/ */
if (CompareHashes(memory_hash, entry->text_hash, SHA_256_HASH_LENGTH)) if (CompareHashes(memory_hash, entry->text_hash, SHA_256_HASH_LENGTH)) {
DEBUG_VERBOSE("Driver image is valid. Integrity check complete"); DEBUG_VERBOSE("Driver image is valid. Integrity check complete");
else }
else {
DEBUG_WARNING("**!!** Driver image is NOT valid. **!!**"); DEBUG_WARNING("**!!** Driver image is NOT valid. **!!**");
ReportModifiedSelfDriverImage(module_info);
}
end: end:
@ -2312,7 +2348,7 @@ end:
* the right direction. * the right direction.
*/ */
NTSTATUS NTSTATUS
InitialiseHeartbeatConfiguration(_Inout_ PHEARTBEAT_CONFIGURATION Configuration) InitialiseHeartbeatConfiguration(_Out_ PHEARTBEAT_CONFIGURATION Configuration)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;

View file

@ -123,7 +123,7 @@ FindWinLogonProcess(_In_ PPROCESS_LIST_ENTRY Entry, _In_opt_ PVOID Context);
NTSTATUS NTSTATUS
InitialiseHeartbeatConfiguration( InitialiseHeartbeatConfiguration(
_Inout_ PHEARTBEAT_CONFIGURATION Configuration); _Out_ PHEARTBEAT_CONFIGURATION Configuration);
VOID VOID
FreeHeartbeatConfiguration(_Inout_ PHEARTBEAT_CONFIGURATION Configuration); FreeHeartbeatConfiguration(_Inout_ PHEARTBEAT_CONFIGURATION Configuration);

View file

@ -337,12 +337,12 @@ IrpQueueCompletePacket(_In_ PVOID Buffer, _In_ ULONG BufferSize)
} }
/* /*
* Not only does this allow reporting threads to continue execution once the * Due to the fact that many reporting structures are holding a mutex when
* report is scheduled (which in some cases such as handle reporting is very * scheduling a report packet, we need an alternative queueing option from DPCs
* important for performance reasons), but it allows us to safely report from * and spinlocks. Here we will use an array of work items (
* within a region guarded by a mutex as we use a spinlock here (for performance *
* reasons, we dont need certain time critical threads being slept whilst we * Hmm this is an interesting issue. Not sure how we shall resolve this, for now
* wait). * this works well enough.
*/ */
VOID VOID
IrpQueueSchedulePacket(_In_ PVOID Buffer, _In_ UINT32 BufferLength) IrpQueueSchedulePacket(_In_ PVOID Buffer, _In_ UINT32 BufferLength)

View file

@ -13,7 +13,9 @@
#define REPORT_DPC_STACKWALK 120 #define REPORT_DPC_STACKWALK 120
#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_PATCHED_SYSTEM_MODULE 150 #define REPORT_PATCHED_SYSTEM_MODULE 150
#define REPORT_SELF_DRIVER_PATCHED 160
#define REPORT_BLACKLISTED_PCIE_DEVICE 170
#define REPORT_SUBTYPE_NO_BACKING_MODULE 0x0 #define REPORT_SUBTYPE_NO_BACKING_MODULE 0x0
#define REPORT_SUBTYPE_INVALID_DISPATCH 0x1 #define REPORT_SUBTYPE_INVALID_DISPATCH 0x1
@ -198,4 +200,20 @@ typedef struct _SYSTEM_MODULE_INTEGRITY_CHECK_REPORT {
} SYSTEM_MODULE_INTEGRITY_CHECK_REPORT, *PSYSTEM_MODULE_INTEGRITY_CHECK_REPORT; } SYSTEM_MODULE_INTEGRITY_CHECK_REPORT, *PSYSTEM_MODULE_INTEGRITY_CHECK_REPORT;
typedef struct _DRIVER_SELF_INTEGRITY_CHECK_REPORT {
REPORT_PACKET_HEADER header;
UINT64 image_base;
UINT32 image_size;
CHAR path_name[0x100];
} DRIVER_SELF_INTEGRITY_CHECK_REPORT, *PDRIVER_SELF_INTEGRITY_CHECK_REPORT;
typedef struct _BLACKLISTED_PCIE_DEVICE_REPORT {
REPORT_PACKET_HEADER header;
UINT64 device_object;
UINT16 device_id;
UINT16 vendor_id;
} BLACKLISTED_PCIE_DEVICE_REPORT, *PBLACKLISTED_PCIE_DEVICE_REPORT;
#endif #endif

View file

@ -5,50 +5,64 @@
#include "crypt/crypt.h" #include "crypt/crypt.h"
void helper::generate_rand_seed() { srand(time(0)); } void
helper::generate_rand_seed()
int helper::generate_rand_int(int max) { return std::rand() % max; } {
srand(time(0));
void helper::sleep_thread(int seconds) {
std::this_thread::sleep_for(std::chrono::seconds(seconds));
} }
int helper::get_report_id_from_buffer(void *buffer) { int
kernel_interface::report_header *header = helper::generate_rand_int(int max)
reinterpret_cast<kernel_interface::report_header *>( {
(uint64_t)buffer + sizeof(kernel_interface::report_header)); return std::rand() % max;
return header->report_code;
} }
kernel_interface::report_id helper::get_kernel_report_type(void *buffer) { void
switch (helper::get_report_id_from_buffer(buffer)) { helper::sleep_thread(int seconds)
case kernel_interface::report_id::report_nmi_callback_failure: {
return kernel_interface::report_id::report_nmi_callback_failure; std::this_thread::sleep_for(std::chrono::seconds(seconds));
}
case kernel_interface::report_id::report_module_validation_failure: int
return kernel_interface::report_id::report_module_validation_failure; helper::get_report_id_from_buffer(void* buffer)
{
kernel_interface::report_header* header =
reinterpret_cast<kernel_interface::report_header*>(
(uint64_t)buffer + sizeof(kernel_interface::report_header));
return header->report_code;
}
case kernel_interface::report_id::report_illegal_handle_operation: kernel_interface::report_id
return kernel_interface::report_id::report_illegal_handle_operation; helper::get_kernel_report_type(void* buffer)
{
switch (helper::get_report_id_from_buffer(buffer)) {
case kernel_interface::report_id::report_nmi_callback_failure:
return kernel_interface::report_id::report_nmi_callback_failure;
case kernel_interface::report_id::report_invalid_process_allocation: case kernel_interface::report_id::report_module_validation_failure:
return kernel_interface::report_id::report_invalid_process_allocation; return kernel_interface::report_id::report_module_validation_failure;
case kernel_interface::report_id::report_hidden_system_thread: case kernel_interface::report_id::report_illegal_handle_operation:
return kernel_interface::report_id::report_hidden_system_thread; return kernel_interface::report_id::report_illegal_handle_operation;
case kernel_interface::report_id::report_illegal_attach_process: case kernel_interface::report_id::report_invalid_process_allocation:
return kernel_interface::report_id::report_illegal_attach_process; return kernel_interface::report_id::report_invalid_process_allocation;
case kernel_interface::report_id::report_apc_stackwalk: case kernel_interface::report_id::report_hidden_system_thread:
return kernel_interface::report_id::report_apc_stackwalk; return kernel_interface::report_id::report_hidden_system_thread;
case kernel_interface::report_id::report_dpc_stackwalk: case kernel_interface::report_id::report_illegal_attach_process:
return kernel_interface::report_id::report_dpc_stackwalk; return kernel_interface::report_id::report_illegal_attach_process;
case kernel_interface::report_id::report_data_table_routine: case kernel_interface::report_id::report_apc_stackwalk:
return kernel_interface::report_id::report_data_table_routine; return kernel_interface::report_id::report_apc_stackwalk;
}
case kernel_interface::report_id::report_dpc_stackwalk:
return kernel_interface::report_id::report_dpc_stackwalk;
case kernel_interface::report_id::report_data_table_routine:
return kernel_interface::report_id::report_data_table_routine;
}
} }
void void
@ -156,6 +170,37 @@ print_report_packet(void* buffer)
LOG_INFO("********************************"); LOG_INFO("********************************");
break; break;
} }
case kernel_interface::report_id::report_patched_system_module: {
kernel_interface::system_module_integrity_check_report* r11 =
reinterpret_cast<
kernel_interface::system_module_integrity_check_report*>(
buffer);
LOG_INFO("image_base: %llx", r11->image_base);
LOG_INFO("image_size: %lx", r11->image_size);
LOG_INFO("path_name: %s", r11->path_name);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_self_driver_patched: {
kernel_interface::driver_self_integrity_check_report* r12 =
reinterpret_cast<
kernel_interface::driver_self_integrity_check_report*>(buffer);
LOG_INFO("image_base: %llx", r12->image_base);
LOG_INFO("image_size: %lx", r12->image_size);
LOG_INFO("path_name: %s", r12->path_name);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_blacklisted_pcie_device: {
kernel_interface::blacklisted_pcie_device_report* r13 =
reinterpret_cast<kernel_interface::blacklisted_pcie_device_report*>(
buffer);
LOG_INFO("device_object: %llx", r13->device_object);
LOG_INFO("device_id: %x", r13->device_id);
LOG_INFO("vendor_id: %x", r13->vendor_id);
LOG_INFO("********************************");
break;
}
default: LOG_INFO("Invalid report type."); break; default: LOG_INFO("Invalid report type."); break;
} }
} }
@ -172,28 +217,32 @@ print_heartbeat_packet(void* buffer)
LOG_INFO("********************************"); LOG_INFO("********************************");
} }
void helper::print_kernel_report(void *buffer) { void
uint32_t size = crypt::get_padded_packet_size( helper::print_kernel_report(void* buffer)
sizeof(kernel_interface::open_handle_failure_report)); {
crypt::decrypt_packet(buffer, size); uint32_t size = crypt::get_padded_packet_size(
sizeof(kernel_interface::open_handle_failure_report));
crypt::decrypt_packet(buffer, size);
kernel_interface::packet_header *header = kernel_interface::packet_header* header =
reinterpret_cast<kernel_interface::packet_header *>(buffer); reinterpret_cast<kernel_interface::packet_header*>(buffer);
LOG_INFO("packet type: %lx", header->packet_type); LOG_INFO("packet type: %lx", header->packet_type);
switch (header->packet_type) switch (header->packet_type) {
{ case 0: print_report_packet(buffer); break;
case 0: print_report_packet(buffer); break; case 1: print_heartbeat_packet(buffer); break;
case 1: print_heartbeat_packet(buffer); break; }
}
} }
unsigned __int64 helper::seconds_to_nanoseconds(int seconds) { unsigned __int64
return ABSOLUTE(SECONDS(seconds)); helper::seconds_to_nanoseconds(int seconds)
{
return ABSOLUTE(SECONDS(seconds));
} }
unsigned __int32 helper::seconds_to_milliseconds(int seconds) { unsigned __int32
return seconds * 1000; helper::seconds_to_milliseconds(int seconds)
{
return seconds * 1000;
} }

View file

@ -22,7 +22,10 @@ enum report_id {
report_apc_stackwalk = 110, report_apc_stackwalk = 110,
report_dpc_stackwalk = 120, report_dpc_stackwalk = 120,
report_data_table_routine = 130, report_data_table_routine = 130,
report_invalid_process_module = 140 report_invalid_process_module = 140,
report_patched_system_module = 150,
report_self_driver_patched = 160,
report_blacklisted_pcie_device = 170
}; };
#define AES_256_BLOCK_SIZE 16 #define AES_256_BLOCK_SIZE 16
@ -126,6 +129,20 @@ struct process_module_validation_report {
wchar_t module_path[MODULE_PATH_LEN]; wchar_t module_path[MODULE_PATH_LEN];
}; };
struct system_module_integrity_check_report {
report_header header;
uint64_t image_base;
uint32_t image_size;
char path_name[0x100];
};
struct driver_self_integrity_check_report {
report_header header;
uint64_t image_base;
uint32_t image_size;
char path_name[0x100];
};
struct heartbeat_packet { struct heartbeat_packet {
heartbeat_header header; heartbeat_header header;
uint32_t heartbeat_count; uint32_t heartbeat_count;
@ -134,6 +151,13 @@ struct heartbeat_packet {
uint32_t total_heartbeats_completed; uint32_t total_heartbeats_completed;
}; };
struct blacklisted_pcie_device_report {
report_header header;
uint64_t device_object;
uint16_t device_id;
uint16_t vendor_id;
};
enum apc_operation { operation_stackwalk = 0x1 }; enum apc_operation { operation_stackwalk = 0x1 };
// clang-format off // clang-format off