working on integrity checks

This commit is contained in:
lhodges1 2023-08-23 22:14:20 +10:00
parent 77525c1ccf
commit af62e47949
9 changed files with 223 additions and 58 deletions

View file

@ -3,6 +3,47 @@
#include "common.h" #include "common.h"
#include "modules.h" #include "modules.h"
/*
* note: this can be put into its own function wihtout an IRP as argument then it can be used
* in both the get driver image ioctl handler and the CopyDriverExecvutableRegions func
*/
NTSTATUS GetDriverImageSize(
_In_ PIRP Irp
)
{
NTSTATUS status;
SYSTEM_MODULES modules = { 0 };
PRTL_MODULE_EXTENDED_INFO driver_info;
status = GetSystemModuleInformation( &modules );
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "GetSystemModuleInformation failed with status %x", status );
return status;
}
driver_info = FindSystemModuleByName(
"driver.sys",
&modules
);
Irp->IoStatus.Information = sizeof( ULONG );
RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &driver_info->ImageSize, sizeof( ULONG ) );
if (modules.address )
ExFreePoolWithTag( modules.address, SYSTEM_MODULES_POOL );
return status;
}
/*
* Instead of copying pages with the EDB (execute disable bit) not set, I am simply
* copying the entire image which we can then send to the server which can then can
* analyse the executable sections from there. Until I find a better way to enumerate
* kernel memory without having to walk the pages tables to check the EDB bit this
* is how I will be doing it. c:
*/
NTSTATUS CopyDriverExecutableRegions( NTSTATUS CopyDriverExecutableRegions(
_In_ PIRP Irp _In_ PIRP Irp
) )
@ -10,10 +51,10 @@ NTSTATUS CopyDriverExecutableRegions(
NTSTATUS status; NTSTATUS status;
SYSTEM_MODULES modules = { 0 }; SYSTEM_MODULES modules = { 0 };
PRTL_MODULE_EXTENDED_INFO driver_info; PRTL_MODULE_EXTENDED_INFO driver_info;
MEMORY_BASIC_INFORMATION region_info; MM_COPY_ADDRESS address;
SIZE_T return_length; PVOID mapped_address;
PVOID current; PHYSICAL_ADDRESS physical_address;
INT count = 0; SIZE_T bytes_returned;
status = GetSystemModuleInformation( &modules ); status = GetSystemModuleInformation( &modules );
@ -28,33 +69,35 @@ NTSTATUS CopyDriverExecutableRegions(
&modules &modules
); );
current = driver_info->ImageBase;
Irp->IoStatus.Information = driver_info->ImageSize; Irp->IoStatus.Information = driver_info->ImageSize;
while (NT_SUCCESS( NtQueryVirtualMemory( /*
NtCurrentProcess(), * Map the drivers physical memory into our IO space, then copy it into
current, * our IRP buffer.
MemoryBasicInformation, */
&region_info, physical_address.QuadPart = MmGetPhysicalAddress( driver_info->ImageBase ).QuadPart;
sizeof( MEMORY_BASIC_INFORMATION ),
&return_length mapped_address = MmMapIoSpace(
))) physical_address,
driver_info->ImageSize,
MmNonCached
);
if ( !mapped_address )
{ {
if ( region_info.AllocationProtect & PAGE_EXECUTE ) DEBUG_ERROR( "Failed to MmMapIoSpace " );
{ goto end;
RtlCopyMemory(
(UINT64)Irp->AssociatedIrp.SystemBuffer + count * region_info.RegionSize,
current,
region_info.RegionSize
);
DEBUG_LOG( "Copied region at address: %p, with protect: %lx", current, region_info.AllocationProtect );
}
current = (UINT64)current + region_info.RegionSize;
} }
RtlCopyMemory(
Irp->AssociatedIrp.SystemBuffer,
mapped_address,
driver_info->ImageSize
);
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "MmCopyMemory failed with status %x", status );
end: end:
Irp->IoStatus.Status = status; Irp->IoStatus.Status = status;

View file

@ -9,4 +9,8 @@ NTSTATUS CopyDriverExecutableRegions(
_In_ PIRP Irp _In_ PIRP Irp
); );
NTSTATUS GetDriverImageSize(
_In_ PIRP Irp
);
#endif #endif

View file

@ -126,13 +126,59 @@ NTSTATUS DeviceControl(
case IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS: case IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS:
status = CopyDriverExecutableRegions( Irp ); status = PsCreateSystemThread(
&handle,
PROCESS_ALL_ACCESS,
NULL,
NULL,
NULL,
CopyDriverExecutableRegions,
Irp
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "Failed to start system thread to get executable regions" );
goto end;
}
status = ObReferenceObjectByHandle(
handle,
THREAD_ALL_ACCESS,
*PsThreadType,
KernelMode,
&thread,
NULL
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "ObReferenceObjectbyhandle failed with status %lx", status );
ZwClose( handle );
goto end;
}
PAGED_CODE();
KeWaitForSingleObject( thread, Executive, KernelMode, FALSE, NULL );;
ZwClose( handle );
ObDereferenceObject( thread );
if ( !NT_SUCCESS( status ) ) if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "Failed to retrieve executable regions" ); DEBUG_ERROR( "Failed to retrieve executable regions" );
break; break;
case IOCTL_REQUEST_TOTAL_MODULE_SIZE:
status = GetDriverImageSize( Irp );
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "Failed to retrieve driver image size" );
break;
default: default:
DEBUG_ERROR( "Invalid IOCTL passed to driver" ); DEBUG_ERROR( "Invalid IOCTL passed to driver" );
break; break;

View file

@ -44,6 +44,8 @@ void global::Client::ServerSend(PVOID Buffer, SIZE_T Size, INT RequestId)
header_extension.current_packet_number = count; header_extension.current_packet_number = count;
header_extension.packet_size = ( count + 1 ) == total_packets ? remaining_bytes : SEND_BUFFER_SIZE; header_extension.packet_size = ( count + 1 ) == total_packets ? remaining_bytes : SEND_BUFFER_SIZE;
LOG_INFO( "current packet number: %lx, packet size: %lx", header_extension.current_packet_number, header_extension.packet_size );
memcpy( PVOID( ( UINT64 )this->send_buffer + sizeof( global::headers::PIPE_PACKET_HEADER ) ), memcpy( PVOID( ( UINT64 )this->send_buffer + sizeof( global::headers::PIPE_PACKET_HEADER ) ),
&header_extension, sizeof(global::headers::PIPE_PACKET_SEND_EXTENSION_HEADER)); &header_extension, sizeof(global::headers::PIPE_PACKET_SEND_EXTENSION_HEADER));

View file

@ -22,7 +22,7 @@ kernelmode::Driver::Driver( LPCWSTR DriverName, std::shared_ptr<global::Client>
LOG_ERROR( "Failed to open handle to driver with status 0x%x", GetLastError() ); LOG_ERROR( "Failed to open handle to driver with status 0x%x", GetLastError() );
} }
void kernelmode::Driver::RunNmiCallbacks() VOID kernelmode::Driver::RunNmiCallbacks()
{ {
BOOLEAN status; BOOLEAN status;
DWORD bytes_returned; DWORD bytes_returned;
@ -60,7 +60,7 @@ void kernelmode::Driver::RunNmiCallbacks()
* 2. Checks the IOCTL dispatch routines to ensure they lie within the module * 2. Checks the IOCTL dispatch routines to ensure they lie within the module
*/ */
void kernelmode::Driver::VerifySystemModules() VOID kernelmode::Driver::VerifySystemModules()
{ {
BOOLEAN status; BOOLEAN status;
DWORD bytes_returned; DWORD bytes_returned;
@ -145,7 +145,7 @@ void kernelmode::Driver::VerifySystemModules()
* modules. * modules.
*/ */
void kernelmode::Driver::QueryReportQueue() VOID kernelmode::Driver::QueryReportQueue()
{ {
BOOLEAN status; BOOLEAN status;
DWORD bytes_returned; DWORD bytes_returned;
@ -199,7 +199,7 @@ end:
free( buffer ); free( buffer );
} }
void kernelmode::Driver::RunCallbackReportQueue() VOID kernelmode::Driver::RunCallbackReportQueue()
{ {
/*TODO have some volatile flag instead */ /*TODO have some volatile flag instead */
while ( true ) while ( true )
@ -209,7 +209,7 @@ void kernelmode::Driver::RunCallbackReportQueue()
} }
} }
void kernelmode::Driver::NotifyDriverOnProcessLaunch() VOID kernelmode::Driver::NotifyDriverOnProcessLaunch()
{ {
BOOLEAN status; BOOLEAN status;
kernelmode::DRIVER_INITIATION_INFORMATION information; kernelmode::DRIVER_INITIATION_INFORMATION information;
@ -230,7 +230,7 @@ void kernelmode::Driver::NotifyDriverOnProcessLaunch()
LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() ); LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() );
} }
void kernelmode::Driver::DetectSystemVirtualization() VOID kernelmode::Driver::DetectSystemVirtualization()
{ {
BOOLEAN status; BOOLEAN status;
HYPERVISOR_DETECTION_REPORT report; HYPERVISOR_DETECTION_REPORT report;
@ -259,7 +259,7 @@ void kernelmode::Driver::DetectSystemVirtualization()
/* shutdown the application or smth lmao */ /* shutdown the application or smth lmao */
} }
void kernelmode::Driver::CheckHandleTableEntries() VOID kernelmode::Driver::CheckHandleTableEntries()
{ {
BOOLEAN status; BOOLEAN status;
DWORD bytes_returned; DWORD bytes_returned;
@ -284,22 +284,80 @@ void kernelmode::Driver::CheckHandleTableEntries()
LOG_ERROR( "CheckHandleTableEntries failed with status %x", status ); LOG_ERROR( "CheckHandleTableEntries failed with status %x", status );
} }
void kernelmode::Driver::RequestModuleExecutableRegions() VOID kernelmode::Driver::RequestModuleExecutableRegions()
{ {
BOOLEAN status; BOOLEAN status;
DWORD bytes_returned;
ULONG module_size;
PVOID buffer;
module_size = this->RequestTotalModuleSize();
if ( module_size == NULL )
{
LOG_ERROR( "RequestTotalModuleSize failed lolz" );
return;
}
LOG_INFO( "module size: %lx", module_size );
buffer = malloc( module_size );
if ( !buffer )
return;
status = DeviceIoControl(
this->driver_handle,
IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS,
NULL,
NULL,
buffer,
module_size,
&bytes_returned,
NULL
);
if ( status == NULL )
{
LOG_ERROR( "failed to retrieve module executable regions lozl %x", GetLastError() );
goto end;
}
LOG_INFO( "bytes returned: %lx", bytes_returned );
end:
free( buffer );
} }
void kernelmode::Driver::RequestTotalModuleSize() ULONG kernelmode::Driver::RequestTotalModuleSize()
{
BOOLEAN status;
DWORD bytes_returned;
ULONG module_size;
status = DeviceIoControl(
this->driver_handle,
IOCTL_REQUEST_TOTAL_MODULE_SIZE,
NULL,
NULL,
&module_size,
sizeof(ULONG),
&bytes_returned,
NULL
);
if ( status == NULL )
LOG_ERROR( "CheckHandleTableEntries failed with status %x", status );
return module_size;
}
VOID kernelmode::Driver::ValidateKPRCBThreads()
{ {
} }
void kernelmode::Driver::ValidateKPRCBThreads() VOID kernelmode::Driver::CheckDriverHeartbeat()
{
}
void kernelmode::Driver::CheckDriverHeartbeat()
{ {
} }

View file

@ -27,22 +27,22 @@ namespace kernelmode
LPCWSTR driver_name; LPCWSTR driver_name;
std::shared_ptr<global::Client> report_interface; std::shared_ptr<global::Client> report_interface;
void QueryReportQueue(); VOID QueryReportQueue();
void RequestTotalModuleSize(); ULONG RequestTotalModuleSize();
public: public:
Driver(LPCWSTR DriverName, std::shared_ptr<global::Client> ReportInterface ); Driver(LPCWSTR DriverName, std::shared_ptr<global::Client> ReportInterface );
void RunNmiCallbacks(); VOID RunNmiCallbacks();
void VerifySystemModules(); VOID VerifySystemModules();
void RunCallbackReportQueue(); VOID RunCallbackReportQueue();
void NotifyDriverOnProcessLaunch(); VOID NotifyDriverOnProcessLaunch();
void DetectSystemVirtualization(); VOID DetectSystemVirtualization();
void ValidateKPRCBThreads(); VOID ValidateKPRCBThreads();
void CheckDriverHeartbeat(); VOID CheckDriverHeartbeat();
void CheckHandleTableEntries(); VOID CheckHandleTableEntries();
void RequestModuleExecutableRegions(); VOID RequestModuleExecutableRegions();
/* todo: driver integrity check */ /* todo: driver integrity check */
}; };

View file

@ -25,3 +25,13 @@ void kernelmode::KManager::DetectSystemVirtualization()
{ {
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->DetectSystemVirtualization(); } ); this->thread_pool->QueueJob( [ this ]() { this->driver_interface->DetectSystemVirtualization(); } );
} }
void kernelmode::KManager::EnumerateHandleTables()
{
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->CheckHandleTableEntries(); } );
}
void kernelmode::KManager::RequestModuleExecutableRegionsForIntegrityCheck()
{
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->RequestModuleExecutableRegions(); } );
}

View file

@ -17,10 +17,12 @@ namespace kernelmode
public: public:
KManager( LPCWSTR DriverName, std::shared_ptr<global::ThreadPool> ThreadPool, std::shared_ptr<global::Client> ReportInterface); KManager( LPCWSTR DriverName, std::shared_ptr<global::ThreadPool> ThreadPool, std::shared_ptr<global::Client> ReportInterface);
void RunNmiCallbacks(); VOID RunNmiCallbacks();
void VerifySystemModules(); VOID VerifySystemModules();
void MonitorCallbackReports(); VOID MonitorCallbackReports();
void DetectSystemVirtualization(); VOID DetectSystemVirtualization();
VOID EnumerateHandleTables();
VOID RequestModuleExecutableRegionsForIntegrityCheck();
}; };
} }

View file

@ -31,7 +31,7 @@ DWORD WINAPI Init(HINSTANCE hinstDLL)
//kmanager.MonitorCallbackReports(); //kmanager.MonitorCallbackReports();
//kmanager.RunNmiCallbacks(); //kmanager.RunNmiCallbacks();
//kmanager.VerifySystemModules(); //kmanager.VerifySystemModules();
kmanager.DetectSystemVirtualization(); kmanager.RequestModuleExecutableRegionsForIntegrityCheck();
//umanager.ValidateProcessModules(); //umanager.ValidateProcessModules();
//umanager.ValidateProcessMemory(); //umanager.ValidateProcessMemory();