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 "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(
_In_ PIRP Irp
)
@ -10,10 +51,10 @@ NTSTATUS CopyDriverExecutableRegions(
NTSTATUS status;
SYSTEM_MODULES modules = { 0 };
PRTL_MODULE_EXTENDED_INFO driver_info;
MEMORY_BASIC_INFORMATION region_info;
SIZE_T return_length;
PVOID current;
INT count = 0;
MM_COPY_ADDRESS address;
PVOID mapped_address;
PHYSICAL_ADDRESS physical_address;
SIZE_T bytes_returned;
status = GetSystemModuleInformation( &modules );
@ -28,33 +69,35 @@ NTSTATUS CopyDriverExecutableRegions(
&modules
);
current = driver_info->ImageBase;
Irp->IoStatus.Information = driver_info->ImageSize;
while (NT_SUCCESS( NtQueryVirtualMemory(
NtCurrentProcess(),
current,
MemoryBasicInformation,
&region_info,
sizeof( MEMORY_BASIC_INFORMATION ),
&return_length
)))
/*
* Map the drivers physical memory into our IO space, then copy it into
* our IRP buffer.
*/
physical_address.QuadPart = MmGetPhysicalAddress( driver_info->ImageBase ).QuadPart;
mapped_address = MmMapIoSpace(
physical_address,
driver_info->ImageSize,
MmNonCached
);
if ( !mapped_address )
{
if ( region_info.AllocationProtect & PAGE_EXECUTE )
{
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;
DEBUG_ERROR( "Failed to MmMapIoSpace " );
goto end;
}
RtlCopyMemory(
Irp->AssociatedIrp.SystemBuffer,
mapped_address,
driver_info->ImageSize
);
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "MmCopyMemory failed with status %x", status );
end:
Irp->IoStatus.Status = status;

View file

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

View file

@ -126,13 +126,59 @@ NTSTATUS DeviceControl(
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 ) )
DEBUG_ERROR( "Failed to retrieve executable regions" );
break;
case IOCTL_REQUEST_TOTAL_MODULE_SIZE:
status = GetDriverImageSize( Irp );
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "Failed to retrieve driver image size" );
break;
default:
DEBUG_ERROR( "Invalid IOCTL passed to driver" );
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.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 ) ),
&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() );
}
void kernelmode::Driver::RunNmiCallbacks()
VOID kernelmode::Driver::RunNmiCallbacks()
{
BOOLEAN status;
DWORD bytes_returned;
@ -60,7 +60,7 @@ void kernelmode::Driver::RunNmiCallbacks()
* 2. Checks the IOCTL dispatch routines to ensure they lie within the module
*/
void kernelmode::Driver::VerifySystemModules()
VOID kernelmode::Driver::VerifySystemModules()
{
BOOLEAN status;
DWORD bytes_returned;
@ -145,7 +145,7 @@ void kernelmode::Driver::VerifySystemModules()
* modules.
*/
void kernelmode::Driver::QueryReportQueue()
VOID kernelmode::Driver::QueryReportQueue()
{
BOOLEAN status;
DWORD bytes_returned;
@ -199,7 +199,7 @@ end:
free( buffer );
}
void kernelmode::Driver::RunCallbackReportQueue()
VOID kernelmode::Driver::RunCallbackReportQueue()
{
/*TODO have some volatile flag instead */
while ( true )
@ -209,7 +209,7 @@ void kernelmode::Driver::RunCallbackReportQueue()
}
}
void kernelmode::Driver::NotifyDriverOnProcessLaunch()
VOID kernelmode::Driver::NotifyDriverOnProcessLaunch()
{
BOOLEAN status;
kernelmode::DRIVER_INITIATION_INFORMATION information;
@ -230,7 +230,7 @@ void kernelmode::Driver::NotifyDriverOnProcessLaunch()
LOG_ERROR( "DeviceIoControl failed with status code 0x%x", GetLastError() );
}
void kernelmode::Driver::DetectSystemVirtualization()
VOID kernelmode::Driver::DetectSystemVirtualization()
{
BOOLEAN status;
HYPERVISOR_DETECTION_REPORT report;
@ -259,7 +259,7 @@ void kernelmode::Driver::DetectSystemVirtualization()
/* shutdown the application or smth lmao */
}
void kernelmode::Driver::CheckHandleTableEntries()
VOID kernelmode::Driver::CheckHandleTableEntries()
{
BOOLEAN status;
DWORD bytes_returned;
@ -284,22 +284,80 @@ void kernelmode::Driver::CheckHandleTableEntries()
LOG_ERROR( "CheckHandleTableEntries failed with status %x", status );
}
void kernelmode::Driver::RequestModuleExecutableRegions()
VOID kernelmode::Driver::RequestModuleExecutableRegions()
{
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;
std::shared_ptr<global::Client> report_interface;
void QueryReportQueue();
void RequestTotalModuleSize();
VOID QueryReportQueue();
ULONG RequestTotalModuleSize();
public:
Driver(LPCWSTR DriverName, std::shared_ptr<global::Client> ReportInterface );
void RunNmiCallbacks();
void VerifySystemModules();
void RunCallbackReportQueue();
void NotifyDriverOnProcessLaunch();
void DetectSystemVirtualization();
void ValidateKPRCBThreads();
void CheckDriverHeartbeat();
void CheckHandleTableEntries();
void RequestModuleExecutableRegions();
VOID RunNmiCallbacks();
VOID VerifySystemModules();
VOID RunCallbackReportQueue();
VOID NotifyDriverOnProcessLaunch();
VOID DetectSystemVirtualization();
VOID ValidateKPRCBThreads();
VOID CheckDriverHeartbeat();
VOID CheckHandleTableEntries();
VOID RequestModuleExecutableRegions();
/* todo: driver integrity check */
};

View file

@ -25,3 +25,13 @@ void kernelmode::KManager::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:
KManager( LPCWSTR DriverName, std::shared_ptr<global::ThreadPool> ThreadPool, std::shared_ptr<global::Client> ReportInterface);
void RunNmiCallbacks();
void VerifySystemModules();
void MonitorCallbackReports();
void DetectSystemVirtualization();
VOID RunNmiCallbacks();
VOID VerifySystemModules();
VOID MonitorCallbackReports();
VOID DetectSystemVirtualization();
VOID EnumerateHandleTables();
VOID RequestModuleExecutableRegionsForIntegrityCheck();
};
}

View file

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