mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
c:
This commit is contained in:
parent
893104cfe5
commit
44e5ed6232
14 changed files with 210 additions and 305 deletions
|
@ -990,6 +990,12 @@ typedef struct _RAW_SMBIOS_TABLE_02 {
|
|||
|
||||
}RAW_SMBIOS_TABLE_02, *PRAW_SMBIOS_TABLE_02;
|
||||
|
||||
typedef struct _RTL_RELATIVE_NAME {
|
||||
UNICODE_STRING RelativeName;
|
||||
HANDLE ContainingDirectory;
|
||||
void* CurDirRef;
|
||||
} RTL_RELATIVE_NAME, * PRTL_RELATIVE_NAME;
|
||||
|
||||
NTKERNELAPI
|
||||
BOOLEAN
|
||||
ExEnumHandleTable(
|
||||
|
@ -1066,6 +1072,13 @@ KeCapturePersistentThreadState(
|
|||
__in PDUMP_HEADER DumpHeader
|
||||
);
|
||||
|
||||
BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_U(
|
||||
_In_ PCWSTR DosFileName,
|
||||
_Out_ PUNICODE_STRING NtFileName,
|
||||
_Out_opt_ PWSTR* FilePath,
|
||||
_Out_opt_ PRTL_RELATIVE_NAME RelativeName
|
||||
);
|
||||
|
||||
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, Signature ) == 0 );
|
||||
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, ValidDump ) == 4 );
|
||||
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MajorVersion ) == 8 );
|
||||
|
|
|
@ -332,17 +332,15 @@ NTSTATUS DriverEntry(
|
|||
BOOLEAN flag = FALSE;
|
||||
NTSTATUS status;
|
||||
|
||||
//status = InitialiseDriverConfigOnDriverEntry( RegistryPath );
|
||||
status = InitialiseDriverConfigOnDriverEntry( RegistryPath );
|
||||
|
||||
//if ( !NT_SUCCESS( status ) )
|
||||
//{
|
||||
// DEBUG_ERROR( "InitialiseDriverConfigOnDriverEntry failed with status %x", status );
|
||||
// return status;
|
||||
//}
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "InitialiseDriverConfigOnDriverEntry failed with status %x", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
//InitialiseProcessConfigOnDriverEntry();
|
||||
|
||||
QueryDiskDriverForDiskInformation();
|
||||
InitialiseProcessConfigOnDriverEntry();
|
||||
|
||||
status = IoCreateDevice(
|
||||
DriverObject,
|
||||
|
|
|
@ -146,8 +146,6 @@ NTSTATUS StoreModuleExecutableRegionsInBuffer(
|
|||
|
||||
for ( ULONG index = 0; index < num_sections; index++ )
|
||||
{
|
||||
DEBUG_LOG( "section name: %s, size: %lx", section->Name, section->SizeOfRawData );
|
||||
|
||||
if ( section->Characteristics & IMAGE_SCN_MEM_EXECUTE )
|
||||
{
|
||||
/*
|
||||
|
@ -726,7 +724,7 @@ NTSTATUS RetrieveInMemoryModuleExecutableSections(
|
|||
* 729 system- and OEM-specific structures and allows upper-level software to easily traverse the
|
||||
* 730 structure table. (See structure-termination examples later in this clause.)
|
||||
*
|
||||
* TLDR is that if the first character proceeding the structure is a null byte, then there are no strings,
|
||||
* TLDR is that if the first two characters proceeding the structure are null terminators, then there are no strings,
|
||||
* otherwise to find the end of the string section simply iterate until there is a double null terminator.
|
||||
*
|
||||
* source: https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
|
||||
|
@ -824,7 +822,7 @@ NTSTATUS ParseSMBIOSTable(
|
|||
SMBIOS_TABLE,
|
||||
NULL,
|
||||
NULL,
|
||||
firmware_table_buffer_size,
|
||||
NULL,
|
||||
&firmware_table_buffer_size
|
||||
);
|
||||
|
||||
|
@ -861,17 +859,17 @@ NTSTATUS ParseSMBIOSTable(
|
|||
smbios_table_header = ( PSMBIOS_TABLE_HEADER )(&smbios_data->SMBIOSTableData[0] );
|
||||
|
||||
/*
|
||||
* The System Information table is equal to Type == 1 and contains the UUID of the motherboard
|
||||
* The System Information table is equal to Type == 2 and contains the serial number of the motherboard
|
||||
* in the computer among various other things.
|
||||
*
|
||||
* source: https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf line 823
|
||||
*/
|
||||
while ( smbios_table_header->Type != SMBIOS_SYSTEM_INFORMATION_TYPE_2_TABLE )
|
||||
while ( smbios_table_header->Type != VMWARE_SMBIOS_TABLE )
|
||||
GetNextSMBIOSStructureInTable( &smbios_table_header );
|
||||
|
||||
status = GetStringAtIndexFromSMBIOSTable(
|
||||
smbios_table_header,
|
||||
MOTHERBOARD_SERIAL_CODE_TABLE_INDEX,
|
||||
VMWARE_SMBIOS_TABLE_INDEX,
|
||||
ConfigMotherboardSerialNumber,
|
||||
ConfigMotherboardSerialNumberSize
|
||||
);
|
||||
|
@ -891,97 +889,96 @@ end:
|
|||
}
|
||||
|
||||
/*
|
||||
* WIP
|
||||
* Because the infrastructure has already been setup to validate modules in the driver, that
|
||||
* is how I will validate the usermode modules as well. Another reason is that the win32 api
|
||||
* makes it very easy to take a snapshot of the modules and enumerate them with easy to use
|
||||
* functions and macros.
|
||||
*
|
||||
* 1. Take a snapshot of the modules in the process from our dll
|
||||
* 2. pass the image base, image size and the image path to our driver via an IRP
|
||||
* 3. from our driver, to first verify the in memory module, attach to our protected process
|
||||
* and using the base + size simply use StoreModuleExecutableRegionsInBuffer()
|
||||
* 4. Next we use the path to map the image on disk into memory, and pass the image to
|
||||
* StoreModuleExecutableRegionsInBuffer() just as we did before.
|
||||
* 5. With the 2 buffers that contain both images executable regions, we hash them and compare
|
||||
* for anomalies.
|
||||
*/
|
||||
NTSTATUS QueryDiskDriverForDiskInformation()
|
||||
NTSTATUS ValidateProcessLoadedModule(
|
||||
_In_ PIRP Irp
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE handle;
|
||||
PVOID buffer = NULL;
|
||||
OBJECT_ATTRIBUTES object_attributes;
|
||||
PIO_STATUS_BLOCK status_block = { 0 };
|
||||
STORAGE_DESCRIPTOR_HEADER storage_descriptor_header = { 0 };
|
||||
PSTORAGE_DEVICE_DESCRIPTOR storage_device_descriptor = NULL;
|
||||
UNICODE_STRING physical_drive_path;
|
||||
BOOLEAN bstatus;
|
||||
PROCESS_MODULE_VALIDATION_RESULT validation_result;
|
||||
PPROCESS_MODULE_INFORMATION module_info;
|
||||
PKPROCESS process;
|
||||
KAPC_STATE apc_state;
|
||||
PVOID in_memory_buffer = NULL;
|
||||
PVOID disk_buffer = NULL;
|
||||
PVOID in_memory_hash = NULL;
|
||||
PVOID disk_hash = NULL;
|
||||
ULONG in_memory_hash_size = NULL;
|
||||
ULONG disk_hash_size = NULL;
|
||||
SIZE_T bytes_written = NULL;
|
||||
UNICODE_STRING module_path;
|
||||
|
||||
RtlInitUnicodeString( &physical_drive_path, L"\\DosDevices\\PhysicalDrive0" );
|
||||
module_info = ( PPROCESS_MODULE_INFORMATION )Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&object_attributes,
|
||||
&physical_drive_path,
|
||||
OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
GetProtectedProcessEProcess( &process );
|
||||
|
||||
status = ZwOpenFile(
|
||||
&handle,
|
||||
FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
||||
&object_attributes,
|
||||
&status_block,
|
||||
FILE_SHARE_READ,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT
|
||||
in_memory_buffer = ExAllocatePool2( POOL_FLAG_NON_PAGED, module_info->module_size, POOL_TAG_INTEGRITY );
|
||||
|
||||
if ( !in_memory_buffer )
|
||||
return STATUS_ABANDONED;
|
||||
|
||||
KeStackAttachProcess( process, &apc_state );
|
||||
|
||||
status = StoreModuleExecutableRegionsInBuffer(
|
||||
&in_memory_buffer,
|
||||
module_info->module_base,
|
||||
module_info->module_size,
|
||||
&bytes_written
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "Failed to open handle to PhysicalDrive0 with status %x", status );
|
||||
return status;
|
||||
DEBUG_ERROR( "StoreModuleExecutableRegionsInBuffer failed with status %x", status );
|
||||
KeUnstackDetachProcess( &apc_state );
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = ZwDeviceIoControlFile(
|
||||
handle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&status_block,
|
||||
IOCTL_STORAGE_QUERY_PROPERTY,
|
||||
NULL,
|
||||
NULL,
|
||||
&storage_descriptor_header,
|
||||
sizeof( storage_descriptor_header )
|
||||
KeUnstackDetachProcess( &apc_state );
|
||||
|
||||
status = ComputeHashOfBuffer(
|
||||
in_memory_buffer,
|
||||
bytes_written,
|
||||
&in_memory_hash,
|
||||
&in_memory_hash_size
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "ZwDeviceIoControlFile failed with status %x", status );
|
||||
DEBUG_ERROR( "ComputeHashOfBuffer failed with status %x:", status );
|
||||
goto end;
|
||||
}
|
||||
|
||||
buffer = ExAllocatePool2( POOL_FLAG_NON_PAGED, storage_descriptor_header.Size, POOL_TAG_INTEGRITY );
|
||||
RtlInitUnicodeString( &module_path, &module_info->module_path );
|
||||
|
||||
if ( !buffer )
|
||||
goto end;
|
||||
validation_result.is_module_valid = TRUE;
|
||||
Irp->IoStatus.Information = sizeof( PROCESS_MODULE_VALIDATION_RESULT );
|
||||
|
||||
status = ZwDeviceIoControlFile(
|
||||
handle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&status_block,
|
||||
IOCTL_STORAGE_QUERY_PROPERTY,
|
||||
NULL,
|
||||
NULL,
|
||||
buffer,
|
||||
storage_descriptor_header.Size
|
||||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
&validation_result,
|
||||
sizeof( PROCESS_MODULE_VALIDATION_RESULT )
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "ZwDeviceIoControlFile failed with status %x", status );
|
||||
goto end;
|
||||
}
|
||||
|
||||
DEBUG_LOG( "Storage descritpr size: %lx", storage_descriptor_header.Size );
|
||||
|
||||
storage_device_descriptor = ( PSTORAGE_DEVICE_DESCRIPTOR )buffer;
|
||||
|
||||
DEBUG_LOG( "Serial number offset: %lx", storage_device_descriptor->SerialNumberOffset );
|
||||
|
||||
end:
|
||||
|
||||
if ( buffer )
|
||||
ExFreePoolWithTag( buffer, POOL_TAG_INTEGRITY );
|
||||
if ( in_memory_buffer )
|
||||
ExFreePoolWithTag( in_memory_buffer, POOL_TAG_INTEGRITY );
|
||||
|
||||
if ( in_memory_hash )
|
||||
ExFreePoolWithTag( in_memory_hash, POOL_TAG_INTEGRITY );
|
||||
|
||||
ZwClose( handle );
|
||||
}
|
|
@ -4,152 +4,30 @@
|
|||
#include <ntifs.h>
|
||||
#include "common.h"
|
||||
|
||||
#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(0x0000002d, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define SMBIOS_TABLE 'RSMB'
|
||||
#define SMBIOS_SYSTEM_INFORMATION_TYPE_2_TABLE 2
|
||||
#define NULL_TERMINATOR '\0'
|
||||
#define MOTHERBOARD_SERIAL_CODE_TABLE_INDEX 4
|
||||
|
||||
typedef enum _STORAGE_BUS_TYPE {
|
||||
BusTypeUnknown = 0x00,
|
||||
BusTypeScsi,
|
||||
BusTypeAtapi,
|
||||
BusTypeAta,
|
||||
BusType1394,
|
||||
BusTypeSsa,
|
||||
BusTypeFibre,
|
||||
BusTypeUsb,
|
||||
BusTypeRAID,
|
||||
BusTypeiScsi,
|
||||
BusTypeSas,
|
||||
BusTypeSata,
|
||||
BusTypeSd,
|
||||
BusTypeMmc,
|
||||
BusTypeVirtual,
|
||||
BusTypeFileBackedVirtual,
|
||||
BusTypeSpaces,
|
||||
BusTypeNvme,
|
||||
BusTypeSCM,
|
||||
BusTypeUfs,
|
||||
BusTypeMax,
|
||||
BusTypeMaxReserved = 0x7F
|
||||
} STORAGE_BUS_TYPE, * PSTORAGE_BUS_TYPE;
|
||||
/* for testing purposes */
|
||||
#define VMWARE_SMBIOS_TABLE 1
|
||||
#define VMWARE_SMBIOS_TABLE_INDEX 3
|
||||
|
||||
//
|
||||
// Standard property descriptor header. All property pages should use this
|
||||
// as their first element or should contain these two elements
|
||||
//
|
||||
#define MAX_MODULE_PATH 256
|
||||
|
||||
typedef struct _STORAGE_DESCRIPTOR_HEADER {
|
||||
typedef struct _PROCESS_MODULE_INFORMATION
|
||||
{
|
||||
PVOID module_base;
|
||||
SIZE_T module_size;
|
||||
WCHAR module_path[ MAX_MODULE_PATH ];
|
||||
|
||||
UINT32 Version;
|
||||
}PROCESS_MODULE_INFORMATION, *PPROCESS_MODULE_INFORMATION;
|
||||
|
||||
UINT32 Size;
|
||||
typedef struct _PROCESS_MODULE_VALIDATION_RESULT
|
||||
{
|
||||
INT is_module_valid;
|
||||
|
||||
} STORAGE_DESCRIPTOR_HEADER, * PSTORAGE_DESCRIPTOR_HEADER;
|
||||
|
||||
//
|
||||
// Device property descriptor - this is really just a rehash of the inquiry
|
||||
// data retrieved from a scsi device
|
||||
//
|
||||
// This may only be retrieved from a target device. Sending this to the bus
|
||||
// will result in an error
|
||||
//
|
||||
|
||||
typedef struct _STORAGE_DEVICE_DESCRIPTOR {
|
||||
|
||||
//
|
||||
// Sizeof(STORAGE_DEVICE_DESCRIPTOR)
|
||||
//
|
||||
|
||||
UINT32 Version;
|
||||
|
||||
//
|
||||
// Total size of the descriptor, including the space for additional
|
||||
// data and id strings
|
||||
//
|
||||
|
||||
UINT32 Size;
|
||||
|
||||
//
|
||||
// The SCSI-2 device type
|
||||
//
|
||||
|
||||
BYTE DeviceType;
|
||||
|
||||
//
|
||||
// The SCSI-2 device type modifier (if any) - this may be zero
|
||||
//
|
||||
|
||||
BYTE DeviceTypeModifier;
|
||||
|
||||
//
|
||||
// Flag indicating whether the device's media (if any) is removable. This
|
||||
// field should be ignored for media-less devices
|
||||
//
|
||||
|
||||
BOOLEAN RemovableMedia;
|
||||
|
||||
//
|
||||
// Flag indicating whether the device can support mulitple outstanding
|
||||
// commands. The actual synchronization in this case is the responsibility
|
||||
// of the port driver.
|
||||
//
|
||||
|
||||
BOOLEAN CommandQueueing;
|
||||
|
||||
//
|
||||
// Byte offset to the zero-terminated ascii string containing the device's
|
||||
// vendor id string. For devices with no such ID this will be zero
|
||||
//
|
||||
|
||||
UINT32 VendorIdOffset;
|
||||
|
||||
//
|
||||
// Byte offset to the zero-terminated ascii string containing the device's
|
||||
// product id string. For devices with no such ID this will be zero
|
||||
//
|
||||
|
||||
UINT32 ProductIdOffset;
|
||||
|
||||
//
|
||||
// Byte offset to the zero-terminated ascii string containing the device's
|
||||
// product revision string. For devices with no such string this will be
|
||||
// zero
|
||||
//
|
||||
|
||||
UINT32 ProductRevisionOffset;
|
||||
|
||||
//
|
||||
// Byte offset to the zero-terminated ascii string containing the device's
|
||||
// serial number. For devices with no serial number this will be zero
|
||||
//
|
||||
|
||||
UINT32 SerialNumberOffset;
|
||||
|
||||
//
|
||||
// Contains the bus type (as defined above) of the device. It should be
|
||||
// used to interpret the raw device properties at the end of this structure
|
||||
// (if any)
|
||||
//
|
||||
|
||||
STORAGE_BUS_TYPE BusType;
|
||||
|
||||
//
|
||||
// The number of bytes of bus-specific data which have been appended to
|
||||
// this descriptor
|
||||
//
|
||||
|
||||
UINT32 RawPropertiesLength;
|
||||
|
||||
//
|
||||
// Place holder for the first byte of the bus specific property data
|
||||
//
|
||||
|
||||
BYTE RawDeviceProperties[ 1 ];
|
||||
|
||||
} STORAGE_DEVICE_DESCRIPTOR, * PSTORAGE_DEVICE_DESCRIPTOR;
|
||||
}PROCESS_MODULE_VALIDATION_RESULT, *PPROCESS_MODULE_VALIDATION_RESULT;
|
||||
|
||||
NTSTATUS CopyDriverExecutableRegions(
|
||||
_In_ PIRP Irp
|
||||
|
@ -172,6 +50,8 @@ NTSTATUS ParseSMBIOSTable(
|
|||
_In_ SIZE_T ConfigMotherboardSerialNumberSize
|
||||
);
|
||||
|
||||
NTSTATUS QueryDiskDriverForDiskInformation();
|
||||
NTSTATUS ValidateProcessLoadedModule(
|
||||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -241,6 +241,15 @@ NTSTATUS DeviceControl(
|
|||
|
||||
break;
|
||||
|
||||
case IOCTL_VALIDATE_PROCESS_LOADED_MODULE:
|
||||
|
||||
status = ValidateProcessLoadedModule( Irp );
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
DEBUG_ERROR( "ValidateProcessLoadedModule failed with status %x", status );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR( "Invalid IOCTL passed to driver" );
|
||||
break;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define IOCTL_VALIDATE_KPRCB_CURRENT_THREAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2012, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_PERFORM_INTEGRITY_CHECK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2013, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_DETECT_ATTACHED_THREADS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2014, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_VALIDATE_PROCESS_LOADED_MODULE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2015, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
typedef struct _DRIVER_INITIATION_INFORMATION
|
||||
{
|
||||
|
|
|
@ -511,3 +511,71 @@ VOID kernelmode::Driver::CheckDriverHeartbeat()
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
VOID kernelmode::Driver::VerifyProcessLoadedModuleExecutableRegions()
|
||||
{
|
||||
HANDLE process_modules_handle;
|
||||
MODULEENTRY32 module_entry;
|
||||
BOOLEAN status;
|
||||
PROCESS_MODULE_INFORMATION module_information;
|
||||
PROCESS_MODULE_VALIDATION_RESULT validation_result;
|
||||
DWORD bytes_returned;
|
||||
|
||||
process_modules_handle = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, GetCurrentProcessId() );
|
||||
|
||||
if ( process_modules_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
LOG_ERROR( "CreateToolHelp32Snapshot with TH32CS_SNAPMODULE failed with status 0x%x", GetLastError() );
|
||||
return;
|
||||
}
|
||||
|
||||
module_entry.dwSize = sizeof( MODULEENTRY32 );
|
||||
|
||||
if ( !Module32First( process_modules_handle, &module_entry ) )
|
||||
{
|
||||
LOG_ERROR( "Module32First failed with status 0x%x", GetLastError() );
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
module_information.module_base = module_entry.modBaseAddr;
|
||||
module_information.module_size = module_entry.modBaseSize;
|
||||
memcpy( module_information.module_path, module_entry.szExePath, MAX_MODULE_PATH );
|
||||
|
||||
status = DeviceIoControl(
|
||||
this->driver_handle,
|
||||
IOCTL_VALIDATE_PROCESS_LOADED_MODULE,
|
||||
&module_information,
|
||||
sizeof( module_information ),
|
||||
&validation_result,
|
||||
sizeof( validation_result ),
|
||||
&bytes_returned,
|
||||
NULL
|
||||
);
|
||||
|
||||
if ( status == NULL || bytes_returned == NULL )
|
||||
{
|
||||
LOG_ERROR( "failed to validate process module with status %x", GetLastError() );
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_INFO( "Bytes returned: %lx", bytes_returned );
|
||||
|
||||
/* compare the current checksum to the previously calculated checksum */
|
||||
//if ( this->in_memory_module_checksums[ index ] != in_memory_check_sum )
|
||||
//{
|
||||
// global::report_structures::MODULE_VERIFICATION_CHECKSUM_FAILURE report;
|
||||
// report.report_code = REPORT_CODE_MODULE_VERIFICATION;
|
||||
// report.module_base_address = (UINT64)module_entry.modBaseAddr;
|
||||
// report.module_size = module_entry.modBaseSize;
|
||||
// std::wstring wstr( module_entry.szModule );
|
||||
// report.module_name = std::string( wstr.begin(), wstr.end() );
|
||||
// this->report_interface->ReportViolation( &report );
|
||||
//}
|
||||
|
||||
} while ( Module32Next( process_modules_handle, &module_entry ) );
|
||||
|
||||
end:
|
||||
CloseHandle( process_modules_handle );
|
||||
}
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
#define IOCTL_VALIDATE_KPRCB_CURRENT_THREAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2012, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_PERFORM_INTEGRITY_CHECK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2013, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_DETECT_ATTACHED_THREADS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2014, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_VALIDATE_PROCESS_LOADED_MODULE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2015, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define MAX_REPORTS_PER_IRP 20
|
||||
|
||||
#define MAX_MODULE_PATH 256
|
||||
|
||||
namespace kernelmode
|
||||
{
|
||||
class Driver
|
||||
|
@ -51,6 +54,7 @@ namespace kernelmode
|
|||
VOID ScanForUnlinkedProcess();
|
||||
VOID PerformIntegrityCheck();
|
||||
VOID CheckForAttachedThreads();
|
||||
VOID VerifyProcessLoadedModuleExecutableRegions();
|
||||
};
|
||||
|
||||
struct DRIVER_INITIATION_INFORMATION
|
||||
|
@ -63,6 +67,18 @@ namespace kernelmode
|
|||
INT aperf_msr_timing_check;
|
||||
INT invd_emulation_check;
|
||||
};
|
||||
|
||||
struct PROCESS_MODULE_INFORMATION
|
||||
{
|
||||
PVOID module_base;
|
||||
SIZE_T module_size;
|
||||
WCHAR module_path[ MAX_MODULE_PATH ];
|
||||
};
|
||||
|
||||
struct PROCESS_MODULE_VALIDATION_RESULT
|
||||
{
|
||||
INT is_module_valid;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,3 +50,8 @@ VOID kernelmode::KManager::CheckForAttachedThreads()
|
|||
{
|
||||
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->CheckForAttachedThreads(); } );
|
||||
}
|
||||
|
||||
VOID kernelmode::KManager::ValidateProcessModules()
|
||||
{
|
||||
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->VerifyProcessLoadedModuleExecutableRegions(); } );
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace kernelmode
|
|||
VOID ScanPoolsForUnlinkedProcesses();
|
||||
VOID PerformIntegrityCheck();
|
||||
VOID CheckForAttachedThreads();
|
||||
VOID ValidateProcessModules();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ DWORD WINAPI Init(HINSTANCE hinstDLL)
|
|||
|
||||
while ( !GetAsyncKeyState( VK_DELETE ) )
|
||||
{
|
||||
kmanager.MonitorCallbackReports();
|
||||
kmanager.ValidateProcessModules();
|
||||
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 10000 ) );
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ usermode::Process::Process( std::shared_ptr<global::Client> ReportInterface )
|
|||
this->process_handle = GetCurrentProcess();
|
||||
this->process_id = GetCurrentProcessId();
|
||||
this->function_imports = std::make_unique<Imports>();
|
||||
this->VerifyLoadedModuleChecksums( true );
|
||||
this->report_interface = ReportInterface;
|
||||
}
|
||||
|
||||
|
@ -315,79 +314,4 @@ void usermode::Process::CheckPageProtection( MEMORY_BASIC_INFORMATION* Page )
|
|||
report.allocation_type = Page->Type;
|
||||
this->report_interface->ReportViolation( &report );
|
||||
}
|
||||
}
|
||||
|
||||
void usermode::Process::VerifyLoadedModuleChecksums(bool Init)
|
||||
{
|
||||
HANDLE process_modules_handle;
|
||||
MODULEENTRY32 module_entry;
|
||||
PVOID mapped_image;
|
||||
DWORD in_memory_header_sum;
|
||||
DWORD in_memory_check_sum;
|
||||
DWORD result;
|
||||
INT index = 0;
|
||||
std::vector<DWORD> temp;
|
||||
|
||||
process_modules_handle = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, this->process_id );
|
||||
|
||||
if ( process_modules_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
LOG_ERROR( "CreateToolHelp32Snapshot with TH32CS_SNAPMODULE failed with status 0x%x", GetLastError() );
|
||||
return;
|
||||
}
|
||||
|
||||
module_entry.dwSize = sizeof( MODULEENTRY32 );
|
||||
|
||||
if ( !Module32First( process_modules_handle, &module_entry ) )
|
||||
{
|
||||
LOG_ERROR( "Module32First failed with status 0x%x", GetLastError() );
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* compute checksum for the in memory module */
|
||||
mapped_image = CheckSumMappedFile(
|
||||
module_entry.modBaseAddr,
|
||||
module_entry.modBaseSize,
|
||||
&in_memory_header_sum,
|
||||
&in_memory_check_sum
|
||||
);
|
||||
|
||||
if ( !mapped_image )
|
||||
{
|
||||
LOG_ERROR( "CheckSumMappedFile failed with status 0x%x", GetLastError() );
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* if we are initiliasing simply fill the vector with checksums */
|
||||
if ( Init )
|
||||
{
|
||||
this->in_memory_module_checksums.push_back( in_memory_check_sum );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* compare the current checksum to the previously calculated checksum */
|
||||
if ( this->in_memory_module_checksums[ index ] != in_memory_check_sum )
|
||||
{
|
||||
global::report_structures::MODULE_VERIFICATION_CHECKSUM_FAILURE report;
|
||||
report.report_code = REPORT_CODE_MODULE_VERIFICATION;
|
||||
report.module_base_address = (UINT64)module_entry.modBaseAddr;
|
||||
report.module_size = module_entry.modBaseSize;
|
||||
std::wstring wstr( module_entry.szModule );
|
||||
report.module_name = std::string( wstr.begin(), wstr.end() );
|
||||
this->report_interface->ReportViolation( &report );
|
||||
}
|
||||
|
||||
//store the new checksums in a temp vector
|
||||
temp.push_back( in_memory_check_sum );
|
||||
index++;
|
||||
|
||||
} while ( Module32Next( process_modules_handle, &module_entry ) );
|
||||
|
||||
if (!Init )
|
||||
this->in_memory_module_checksums = temp;
|
||||
|
||||
end:
|
||||
CloseHandle( process_modules_handle );
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
#include "../client.h"
|
||||
#include "../threadpool.h"
|
||||
#include "../um/imports.h"
|
||||
#include "../km/kmanager.h"
|
||||
|
||||
#define ThreadQuerySetWin32StartAddress 9
|
||||
|
||||
|
@ -30,7 +31,6 @@ namespace usermode
|
|||
std::shared_ptr<global::Client> report_interface;
|
||||
|
||||
HANDLE GetHandleToProcessGivenName( std::string ProcessName );
|
||||
std::vector<UINT64> GetProcessThreadsStartAddresses();
|
||||
bool CheckIfAddressLiesWithinValidProcessModule( UINT64 Address, bool* Result );
|
||||
bool GetProcessBaseAddress( UINT64* Result );
|
||||
void CheckPageProtection( MEMORY_BASIC_INFORMATION* Page );
|
||||
|
@ -42,7 +42,6 @@ namespace usermode
|
|||
|
||||
void ValidateProcessThreads();
|
||||
void ScanProcessMemory();
|
||||
void VerifyLoadedModuleChecksums(bool Init);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,3 @@ void usermode::UManager::ValidateProcessMemory()
|
|||
{
|
||||
this->thread_pool->QueueJob( [ this ]() {this->process->ScanProcessMemory(); } );
|
||||
}
|
||||
|
||||
void usermode::UManager::ValidateProcessModules()
|
||||
{
|
||||
this->thread_pool->QueueJob( [ this ]() {this->process->VerifyLoadedModuleChecksums( false ); } );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue