start doing some ept detection stuff

This commit is contained in:
lhodges1 2023-10-03 01:31:30 +11:00
parent 651b310f1c
commit f6d3966ecb
7 changed files with 195 additions and 19 deletions

View file

@ -91,7 +91,8 @@ ObPreOpCallbackRoutine(
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 );
POPEN_HANDLE_FAILURE_REPORT report =
ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( OPEN_HANDLE_FAILURE_REPORT ), REPORT_POOL_TAG );
if ( !report )
goto end;
@ -299,10 +300,10 @@ EnumHandleCallback(
DEBUG_LOG( "Stripped PROCESS_VM_WRITE" );
}
//POPEN_HANDLE_FAILURE_REPORT report = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( OPEN_HANDLE_FAILURE_REPORT ), REPORT_POOL_TAG );
POPEN_HANDLE_FAILURE_REPORT report = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( OPEN_HANDLE_FAILURE_REPORT ), REPORT_POOL_TAG );
//if ( !report )
// goto end;
if ( !report )
goto end;
/*
* Using the same report structure as the ObRegisterCallbacks report
@ -312,14 +313,14 @@ EnumHandleCallback(
* another queue specifically for open handle reports since they will be
* rare.
*/
//report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
//report->is_kernel_handle = NULL;
//report->process_id = PsGetProcessId( process );
//report->thread_id = NULL;
//report->access = handle_access_mask;
//RtlCopyMemory( &report->process_name, process_name, HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH );
report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
report->is_kernel_handle = NULL;
report->process_id = PsGetProcessId( process );
report->thread_id = NULL;
report->access = handle_access_mask;
RtlCopyMemory( &report->process_name, process_name, HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH );
//InsertReportToQueue( report );
InsertReportToQueue( report );
}
end:

View file

@ -36,6 +36,8 @@
#define MODULES_REPORT_POOL_TAG 'modu'
#define POOL_TAG_LIST_ITEM 'tsil'
#define IA32_APERF_MSR 0x000000E8
#define ERROR -1
#define STACK_FRAME_POOL_SIZE 0x200
#define NUMBER_HASH_BUCKETS 37

View file

@ -640,14 +640,14 @@ DriverUnload(
//QueryActiveApcContextsForCompletion();
/* dont unload while we have active APC operations */
while ( !FreeAllApcContextStructures() )
YieldProcessor();
//while ( !FreeAllApcContextStructures() )
// YieldProcessor();
/* This is safe to call even if the callbacks have already been disabled */
UnregisterCallbacksOnProcessTermination();
//UnregisterCallbacksOnProcessTermination();
CleanupDriverConfigOnUnload();
IoDeleteDevice( DriverObject->DeviceObject );
//CleanupDriverConfigOnUnload();
//IoDeleteDevice( DriverObject->DeviceObject );
}
VOID
@ -747,6 +747,10 @@ DriverEntry(
return STATUS_FAILED_DRIVER_ENTRY;
}
UNICODE_STRING string = RTL_CONSTANT_STRING( L"ExAllocatePoolWithTag" );
DetectEptPresenceOnFunction( &string );
DEBUG_LOG( "DonnaAC Driver Entry Complete" );
return STATUS_SUCCESS;

View file

@ -6,8 +6,6 @@
#define TOTAL_ITERATION_COUNT 20
#define IA32_APERF_MSR 0x000000E8
/*
* TODO: Perform the test in a loop and average the delta out, then compare it
* to an instruction such as FYL2XP1 (source: secret.club) which has an average

View file

@ -1266,4 +1266,170 @@ EnumeratePciDevices()
}
ExFreePoolWithTag( device_interfaces, NULL );
}
STATIC
PVOID
ScanForSignature(
_In_ PVOID BaseAddress,
_In_ SIZE_T MaxLength,
_In_ LPCSTR Signature,
_In_ SIZE_T SignatureLength
)
{
CHAR current_char = 0;
CHAR current_sig_char = 0;
for ( INT index = 0; index < MaxLength; index++ )
{
for ( INT sig_index = 0; sig_index < SignatureLength + 1; sig_index++ )
{
current_char = *( PCHAR )( ( UINT64 )BaseAddress + index + sig_index );
current_sig_char = Signature[ sig_index ];
if ( sig_index == SignatureLength )
return ( UINT64 )BaseAddress + index;
if ( current_char != current_sig_char )
break;
}
}
}
#pragma optimize("", off)
STATIC
UINT64
MeasureInstructionRead(
_In_ PVOID InstructionAddress
)
{
UINT64 start = __readmsr( IA32_APERF_MSR ) << 32;
CHAR character = *(PCHAR)InstructionAddress;
return ( __readmsr( IA32_APERF_MSR ) << 32 ) - start;
}
STATIC
UINT64
MeasureInstructionExecute(
_In_ PVOID InstructionAddress
)
{
UINT64 start = __readmsr( IA32_APERF_MSR ) << 32;
( ( VOID( * )( ) )InstructionAddress )( );
return ( __readmsr( IA32_APERF_MSR ) << 32 ) - start;
}
#pragma optimize("", on)
UINT64 MeasureReads(
_In_ PVOID Address,
_In_ ULONG Count
)
{
UINT64 read_average = 0;
KIRQL old_irql;
MeasureInstructionRead( Address );
old_irql = __readcr8();
__writecr8( HIGH_LEVEL );
_disable();
for ( INT iteration = 0; iteration < Count; iteration++ )
{
read_average += MeasureInstructionRead( Address );
}
_enable();
__writecr8( old_irql );
return read_average / Count;
}
UINT64 MeasureExecutionWithAlternatingReads(
_In_ PVOID Address,
_In_ ULONG Count
)
{
UINT64 read_average = 0;
UINT64 execute_average = 0;
KIRQL old_irql;
MeasureInstructionRead( Address );
MeasureInstructionExecute( Address );
old_irql = __readcr8();
__writecr8( HIGH_LEVEL );
_disable();
for ( INT iteration = 0; iteration < Count; iteration++ )
{
read_average += MeasureInstructionRead( Address );
execute_average += MeasureInstructionExecute( Address );
}
_enable();
__writecr8( old_irql );
return execute_average / Count;
}
/*
* Even though we test for the presence of a hypervisor, we should still test for the presence
* of EPT hooks on key functions.
*
* Credits to momo5502 for the idea: https://momo5502.com/blog/?p=255
*/
NTSTATUS
DetectEptPresenceOnFunction(
_In_ PUNICODE_STRING RoutineName
)
{
PVOID function_address = NULL;
PVOID ret_instruction_address = NULL;
UINT64 page_base = NULL;
LPCSTR ret_instruction = "\xC3";
ULONG num_iterations = 200;
UINT64 read_average = 0;
UINT64 read_exec_average = 0;
DEBUG_LOG( "Sizxe of ret instruction: %llx", strlen( ret_instruction ) );
if ( !RoutineName )
return STATUS_INVALID_PARAMETER;
/* some hard coded stuff for ExAllocatePoolWithTag for now */
function_address = ( UINT64 )MmGetSystemRoutineAddress( RoutineName );
if ( !function_address )
return STATUS_INVALID_PARAMETER;
DEBUG_LOG( "NtCreateFile Virtual Address: %llx", ( UINT64 )function_address );
page_base = ( UINT64 )function_address & 0xfffffffffffff000;
DEBUG_LOG( "Page base: %llx", page_base );
ret_instruction_address = ScanForSignature(
page_base,
PAGE_SIZE,
ret_instruction,
strlen( ret_instruction )
);
if ( !ret_instruction_address )
return STATUS_NOT_FOUND;
DEBUG_LOG( "Ret instruction: %llx", ( UINT64 )ret_instruction_address );
for ( int i = 0; i < 50; i++ )
{
read_average = MeasureReads( ret_instruction_address, num_iterations );
read_exec_average = MeasureInstructionRead( ret_instruction_address, num_iterations );
DEBUG_LOG( "Read average: %llx, read exec average: %llx", read_average, read_exec_average );
}
}

View file

@ -39,4 +39,9 @@ ParseSMBIOSTable(
VOID
EnumeratePciDevices();
NTSTATUS
DetectEptPresenceOnFunction(
_In_ PUNICODE_STRING RoutineName
);
#endif

View file

@ -47,7 +47,7 @@ namespace kernelmode
//VOID GetKernelStructureOffsets();
template <typename T>
VOID ReportTypeFromReportQueue( CONST PVOID Buffer, PSIZE_T Offset, CONST PVOID Report )
VOID ReportTypeFromReportQueue( CONST PVOID Buffer, PSIZE_T Offset, PVOID Report )
{
Report = ( T* )(
( UINT64 )Buffer + sizeof( global::report_structures::REPORT_QUEUE_HEADER ) + *Offset );