mirror-ac/driver/integrity.c

711 lines
17 KiB
C
Raw Normal View History

2023-08-22 19:32:25 +02:00
#include "integrity.h"
#include "common.h"
2023-09-01 13:46:31 +02:00
#include "driver.h"
2023-08-22 19:32:25 +02:00
#include "modules.h"
2023-09-01 12:56:27 +02:00
#include <bcrypt.h>
typedef struct _INTEGRITY_CHECK_HEADER
{
INT executable_section_count;
LONG total_packet_size;
}INTEGRITY_CHECK_HEADER, *PINTEGRITY_CHECK_HEADER;
2023-08-23 14:14:20 +02:00
/*
* 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;
}
NTSTATUS GetModuleInformationByName(
_In_ PRTL_MODULE_EXTENDED_INFO ModuleInfo,
_In_ LPCSTR ModuleName
2023-08-22 19:32:25 +02:00
)
{
NTSTATUS status = STATUS_SUCCESS;
2023-08-22 19:32:25 +02:00
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 );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
return status;
2023-08-22 19:32:25 +02:00
}
driver_info = FindSystemModuleByName(
"driver.sys",
&modules
);
ModuleInfo->FileNameOffset = driver_info->FileNameOffset;
ModuleInfo->ImageBase = driver_info->ImageBase;
ModuleInfo->ImageSize = driver_info->ImageSize;
RtlCopyMemory(
ModuleInfo->FullPathName,
driver_info->FullPathName,
sizeof( ModuleInfo->FullPathName )
);
2023-08-22 19:32:25 +02:00
if ( modules.address )
ExFreePoolWithTag( modules.address, SYSTEM_MODULES_POOL );
return status;
2023-08-28 17:00:52 +02:00
}
2023-08-31 13:21:49 +02:00
NTSTATUS StoreModuleExecutableRegionsInBuffer(
_In_ PVOID* Buffer,
_In_ PVOID ModuleBase,
2023-08-31 18:42:38 +02:00
_In_ SIZE_T ModuleSize,
_In_ PSIZE_T BytesWritten
2023-08-31 13:21:49 +02:00
)
{
NTSTATUS status = STATUS_SUCCESS;
PIMAGE_DOS_HEADER dos_header;
PLOCAL_NT_HEADER nt_header;
PIMAGE_SECTION_HEADER section;
ULONG total_packet_size = 0;
ULONG num_sections = 0;
ULONG num_executable_sections = 0;
UINT64 buffer_base;
ULONG bytes_returned;
MM_COPY_ADDRESS address;
if ( !ModuleBase || !ModuleSize )
return STATUS_INVALID_PARAMETER;
DEBUG_LOG( "Module base: %llx, size: %llx", (UINT64)ModuleBase, ModuleSize );
2023-08-31 13:21:49 +02:00
/*
* The reason we allocate a buffer to temporarily hold the section data is that
* we don't know the total size until after we iterate over the sections meaning
* we cant set Irp->IoStatus.Information to the size of our reponse until we
* enumerate and count all executable sections for the file.
*/
2023-09-01 12:56:27 +02:00
2023-08-31 13:21:49 +02:00
*Buffer = ExAllocatePool2( POOL_FLAG_NON_PAGED, ModuleSize + sizeof( INTEGRITY_CHECK_HEADER ), POOL_TAG_INTEGRITY );
if ( !*Buffer )
return STATUS_ABANDONED;
/*
2023-09-01 12:56:27 +02:00
* Note: Verifier doesn't like it when we map the module so rather then mapping it to our address
* space we will simply use MmCopyMemory on the module to avoid upsettings verifier :)
2023-08-31 13:21:49 +02:00
*/
dos_header = ( PIMAGE_DOS_HEADER )ModuleBase;
/*
* The IMAGE_DOS_HEADER.e_lfanew stores the offset of the IMAGE_NT_HEADER from the base
* of the image.
*/
nt_header = ( struct _IMAGE_NT_HEADERS64* )( ( UINT64 )ModuleBase + dos_header->e_lfanew );
num_sections = nt_header->FileHeader.NumberOfSections;
/*
* The IMAGE_FIRST_SECTION macro takes in an IMAGE_NT_HEADER and returns the address of
* the first section of the PE file.
*/
section = IMAGE_FIRST_SECTION( nt_header );
buffer_base = ( UINT64 )*Buffer + sizeof( INTEGRITY_CHECK_HEADER );
for ( ULONG index = 0; index < num_sections; index++ )
{
DEBUG_LOG( "section name: %s, size: %lx", section->Name, section->SizeOfRawData );
2023-08-31 13:21:49 +02:00
if ( section->Characteristics & IMAGE_SCN_MEM_EXECUTE )
{
/*
* Note: MmCopyMemory will fail on discardable sections.
*/
address.VirtualAddress = section;
status = MmCopyMemory(
( UINT64 )buffer_base + total_packet_size,
address,
sizeof( IMAGE_SECTION_HEADER ),
MM_COPY_MEMORY_VIRTUAL,
&bytes_returned
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "MmCopyMemory failed with status %x", status );
ExFreePoolWithTag( *Buffer, POOL_TAG_INTEGRITY );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-08-31 13:21:49 +02:00
return status;
}
address.VirtualAddress = ( UINT64 )ModuleBase + section->PointerToRawData;
status = MmCopyMemory(
( UINT64 )buffer_base + total_packet_size + sizeof( IMAGE_SECTION_HEADER ),
address,
section->SizeOfRawData,
MM_COPY_MEMORY_VIRTUAL,
&bytes_returned
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "MmCopyMemory failed with status %x", status );
ExFreePoolWithTag( *Buffer, POOL_TAG_INTEGRITY );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-08-31 13:21:49 +02:00
return status;
}
total_packet_size += section->SizeOfRawData + sizeof( IMAGE_SECTION_HEADER );
num_executable_sections += 1;
}
section++;
}
INTEGRITY_CHECK_HEADER header = { 0 };
header.executable_section_count = num_executable_sections;
header.total_packet_size = total_packet_size + sizeof( INTEGRITY_CHECK_HEADER );
RtlCopyMemory(
*Buffer,
&header,
sizeof( INTEGRITY_CHECK_HEADER )
);
2023-08-31 18:42:38 +02:00
*BytesWritten = total_packet_size + sizeof( INTEGRITY_CHECK_HEADER );
2023-08-31 13:21:49 +02:00
2023-08-31 18:42:38 +02:00
return status;
}
2023-08-31 13:21:49 +02:00
NTSTATUS MapDiskImageIntoVirtualAddressSpace(
_In_ PHANDLE SectionHandle,
_In_ PVOID* Section,
_In_ PUNICODE_STRING Path,
_In_ PSIZE_T Size
)
2023-08-28 17:00:52 +02:00
{
NTSTATUS status;
HANDLE file_handle;
2023-08-31 12:33:26 +02:00
OBJECT_ATTRIBUTES object_attributes;
PIO_STATUS_BLOCK pio_block;
UNICODE_STRING path;
RtlInitUnicodeString( &path, L"\\SystemRoot\\System32\\Drivers\\driver.sys" );
2023-08-31 12:33:26 +02:00
InitializeObjectAttributes(
&object_attributes,
&path,
2023-08-31 12:33:26 +02:00
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = ZwOpenFile(
&file_handle,
2023-09-01 12:56:27 +02:00
FILE_GENERIC_READ | SYNCHRONIZE,
2023-08-31 12:33:26 +02:00
&object_attributes,
&pio_block,
2023-09-01 12:56:27 +02:00
FILE_GENERIC_READ,
NULL
2023-08-31 12:33:26 +02:00
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "ZwOpenFile failed with statsu %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-08-31 12:33:26 +02:00
return status;
}
object_attributes.ObjectName = NULL;
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "NTSetInformationProcess failed with status %x", status );
ZwClose( file_handle );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
return status;
}
2023-08-31 12:33:26 +02:00
/*
2023-08-31 13:21:49 +02:00
* Its important that we set the SEC_IMAGE flag with the PAGE_READONLY
2023-08-31 12:33:26 +02:00
* flag as we are mapping an executable image.
*/
status = ZwCreateSection(
2023-08-31 13:21:49 +02:00
SectionHandle,
2023-08-31 12:33:26 +02:00
SECTION_ALL_ACCESS,
&object_attributes,
NULL,
2023-09-01 12:56:27 +02:00
PAGE_READONLY,
2023-08-31 12:33:26 +02:00
SEC_IMAGE,
file_handle
2023-08-31 12:33:26 +02:00
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "ZwCreateSection failed with status %x", status );
ZwClose( file_handle );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-08-31 12:33:26 +02:00
return status;
}
2023-09-01 12:56:27 +02:00
/*
* Mapping a section with the flag SEC_IMAGE (see function above) tells the os we
* are mapping an executable image. This then allows the OS to take care of parsing
* the PE header and dealing with all relocations for us, meaning the mapped image
* will be identical to the in memory image.
*/
2023-08-31 12:33:26 +02:00
status = ZwMapViewOfSection(
2023-08-31 13:21:49 +02:00
*SectionHandle,
ZwCurrentProcess(),
2023-08-31 13:21:49 +02:00
Section,
2023-08-31 12:33:26 +02:00
NULL,
NULL,
NULL,
2023-08-31 13:21:49 +02:00
Size,
2023-08-31 12:33:26 +02:00
ViewUnmap,
MEM_TOP_DOWN,
2023-09-01 12:56:27 +02:00
PAGE_READONLY
2023-08-31 12:33:26 +02:00
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "ZwMapViewOfSection failed with status %x", status );
ZwClose( file_handle );
2023-08-31 13:21:49 +02:00
ZwClose( *SectionHandle );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-08-31 12:33:26 +02:00
return status;
}
ZwClose( file_handle );
2023-09-01 12:56:27 +02:00
return status;
}
NTSTATUS ComputeHashOfBuffer(
_In_ PVOID Buffer,
_In_ ULONG BufferSize,
_In_ PVOID* HashResult,
_In_ PULONG HashResultSize
)
{
/*
* Since the windows documentation for the BCrypt functions contain the worst variable naming scheme
* in existence, I will try to explain what they do. (for my sake and any readers who also aren't smart
* enough to understand their otherworldy naming convention)
*
* algo_handle: handle to our BCrypt algorithm
* hash_handle: handle to our BCrypt hash
* bytes_copied: number of bytes that were copied to the output buffer when using BCryptGetProperty
* resulting_hash_size: this is the size of the final buffer hash, it should be equal to 32 (sizeof SHA256 hash)
* hash_object_size: the size of the buffer that will temporarily store our hash object
* hash_object: pointer to the buffer storing our hash object which is used to hash our buffer
* resulting_hash: pointer to the buffer that stores the resulting hash of our buffer, this is what we care about
*/
NTSTATUS status;
BCRYPT_ALG_HANDLE algo_handle = NULL;
BCRYPT_HASH_HANDLE hash_handle = NULL;
ULONG bytes_copied = 0;
ULONG resulting_hash_size = 0;
ULONG hash_object_size = 0;
PCHAR hash_object = NULL;
PCHAR resulting_hash = NULL;
status = BCryptOpenAlgorithmProvider(
&algo_handle,
BCRYPT_SHA256_ALGORITHM,
NULL,
NULL
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "BCryptOpenAlogrithmProvider failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
/*
* Request the size of the hash object buffer, this is different then the buffer that
* will store the resulting hash, instead this will be used to store the hash object
* used to create the hash.
*/
status = BCryptGetProperty(
algo_handle,
BCRYPT_OBJECT_LENGTH,
( PCHAR )&hash_object_size,
sizeof( ULONG ),
&bytes_copied,
NULL
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "BCryptGetProperty failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
hash_object = ExAllocatePool2( POOL_FLAG_NON_PAGED, hash_object_size, POOL_TAG_INTEGRITY );
/*
* This call gets the size of the resulting hash, which we will use to allocate the
* resulting hash buffer.
*/
status = BCryptGetProperty(
algo_handle,
BCRYPT_HASH_LENGTH,
( PCHAR )&resulting_hash_size,
sizeof( ULONG ),
&bytes_copied,
NULL
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "BCryptGetProperty failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
resulting_hash = ExAllocatePool2( POOL_FLAG_NON_PAGED, resulting_hash_size, POOL_TAG_INTEGRITY );
if ( !resulting_hash )
goto end;
2023-09-01 13:46:31 +02:00
/*
* Here we create our hash object and store it in the hash_object buffer.
*/
2023-09-01 12:56:27 +02:00
status = BCryptCreateHash(
algo_handle,
&hash_handle,
hash_object,
hash_object_size,
NULL,
NULL,
NULL
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "BCryptCreateHash failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
/*
* This function hashes the buffer, but does NOT store it in our resulting buffer yet,
* we need to call BCryptFinishHash to retrieve the final hash.
*/
status = BCryptHashData(
hash_handle,
Buffer,
BufferSize,
NULL
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "BCryptHashData failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
/*
* As said in the previous comment, this is where we retrieve the final hash and store
* it in our output buffer.
*/
status = BCryptFinishHash(
hash_handle,
resulting_hash,
resulting_hash_size,
NULL
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "BCryptFinishHash failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
return status;
}
*HashResult = resulting_hash;
*HashResultSize = resulting_hash_size;
end:
if ( algo_handle )
BCryptCloseAlgorithmProvider( algo_handle, 0 );
if ( hash_handle )
BCryptDestroyHash( hash_handle );
if ( hash_object )
ExFreePoolWithTag( hash_object, POOL_TAG_INTEGRITY );
return status;
2023-08-31 13:21:49 +02:00
}
/*
* 1. map driver to memory
* 2. store executable sections in buffer
* 3. do the same with the in-memory module
2023-09-01 12:56:27 +02:00
* 4. hash both buffers
2023-08-31 13:21:49 +02:00
* 5. compare
*/
NTSTATUS VerifyInMemoryImageVsDiskImage(
//_In_ PIRP Irp
)
{
NTSTATUS status;
UNICODE_STRING path;
HANDLE section_handle = NULL;
PVOID section = NULL;
SIZE_T section_size = NULL;
2023-08-31 18:42:38 +02:00
SIZE_T bytes_written = NULL;
2023-08-31 13:21:49 +02:00
PVOID disk_buffer = NULL;
PVOID in_memory_buffer = NULL;
RTL_MODULE_EXTENDED_INFO module_info = { 0 };
2023-09-01 12:56:27 +02:00
UINT64 disk_base = NULL;
UINT64 memory_base = NULL;
PIMAGE_SECTION_HEADER disk_text_header = NULL;
PIMAGE_SECTION_HEADER memory_text_header = NULL;
PVOID disk_text_hash = NULL;
PVOID memory_text_hash = NULL;
ULONG disk_text_hash_size = NULL;
ULONG memory_text_hash_size = NULL;
SIZE_T result = NULL;
/* TODO: ad this into global config */
2023-08-31 13:21:49 +02:00
RtlInitUnicodeString( &path, L"\\SystemRoot\\System32\\Drivers\\driver.sys" );
status = MapDiskImageIntoVirtualAddressSpace(
&section_handle,
&section,
&path,
&section_size
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "MapDiskImageIntoVirtualAddressSpace failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-08-31 13:21:49 +02:00
return status;
}
2023-08-31 12:33:26 +02:00
2023-08-31 13:21:49 +02:00
status = StoreModuleExecutableRegionsInBuffer(
&disk_buffer,
section,
2023-08-31 18:42:38 +02:00
section_size,
&bytes_written
2023-08-31 13:21:49 +02:00
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "StoreModuleExecutableRegionsInBuffer failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-08-31 13:21:49 +02:00
goto end;
}
2023-08-28 17:00:52 +02:00
2023-08-31 13:21:49 +02:00
/*
* Parse the in-memory module
*/
status = GetModuleInformationByName(
&module_info,
"driver.sys"
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "GetModuleInformationByName failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
goto end;
}
status = StoreModuleExecutableRegionsInBuffer(
&in_memory_buffer,
module_info.ImageBase,
2023-08-31 18:42:38 +02:00
module_info.ImageSize,
&bytes_written
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "StoreModuleExecutableRegionsInBuffe failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
goto end;
}
2023-09-01 12:56:27 +02:00
disk_base = ( UINT64 )( ( UINT64 )disk_buffer + sizeof( INTEGRITY_CHECK_HEADER ) + sizeof( IMAGE_SECTION_HEADER ) );
memory_base = ( UINT64 )( ( UINT64 )in_memory_buffer + sizeof( INTEGRITY_CHECK_HEADER ) + sizeof( IMAGE_SECTION_HEADER ) );
2023-09-01 12:56:27 +02:00
disk_text_header = ( PIMAGE_SECTION_HEADER )( ( UINT64 )disk_buffer + sizeof( INTEGRITY_CHECK_HEADER ) );
memory_text_header = ( PIMAGE_SECTION_HEADER )( ( UINT64 )in_memory_buffer + sizeof( INTEGRITY_CHECK_HEADER ) );
2023-08-31 13:21:49 +02:00
if ( !disk_base || !memory_base || !disk_buffer || !in_memory_buffer )
{
DEBUG_ERROR( "buffers are null lmao" );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
goto end;
}
2023-09-01 12:56:27 +02:00
if ( disk_text_header->SizeOfRawData != memory_text_header->SizeOfRawData )
{
/* report or bug check etc. */
DEBUG_LOG( "Executable section size differs, LOL" );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
2023-09-01 12:56:27 +02:00
status = ComputeHashOfBuffer(
disk_base,
disk_text_header->SizeOfRawData,
&disk_text_hash,
&disk_text_hash_size
);
2023-09-01 12:56:27 +02:00
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "ComputeHashOfBuffer failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
2023-09-01 12:56:27 +02:00
status = ComputeHashOfBuffer(
memory_base,
memory_text_header->SizeOfRawData,
&memory_text_hash,
&memory_text_hash_size
);
2023-09-01 12:56:27 +02:00
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "ComputeHashOfBuffer failed with status %x", status );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
2023-08-31 13:21:49 +02:00
2023-09-01 12:56:27 +02:00
if ( memory_text_hash_size != disk_text_hash_size )
{
DEBUG_ERROR( "Error with the hash algorithm, hash sizes are different." );
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
2023-09-01 13:46:31 +02:00
result = RtlCompareMemory(
memory_text_hash,
disk_text_hash,
memory_text_hash_size
);
2023-09-01 12:56:27 +02:00
if (result != memory_text_hash_size)
{
/* report etc. bug check etc. */
DEBUG_ERROR( "Text sections are different from each other!!");
2023-09-01 13:46:31 +02:00
TerminateProtectedProcessOnViolation();
2023-09-01 12:56:27 +02:00
goto end;
}
2023-08-28 17:00:52 +02:00
2023-09-01 12:56:27 +02:00
DEBUG_LOG( "Text sections are fine, integrity check complete." );
end:
2023-08-31 13:21:49 +02:00
if ( section_handle != NULL )
2023-08-31 13:21:49 +02:00
ZwClose( section_handle );
2023-09-01 12:56:27 +02:00
ZwUnmapViewOfSection( ZwCurrentProcess(), section );
if ( disk_buffer )
2023-08-31 13:21:49 +02:00
ExFreePoolWithTag( disk_buffer, POOL_TAG_INTEGRITY );
if ( in_memory_buffer )
ExFreePoolWithTag( in_memory_buffer, POOL_TAG_INTEGRITY );
2023-09-01 12:56:27 +02:00
if ( memory_text_hash )
ExFreePoolWithTag( memory_text_hash, POOL_TAG_INTEGRITY );
if ( disk_text_hash )
ExFreePoolWithTag( disk_text_hash, POOL_TAG_INTEGRITY );
return status;
2023-08-31 18:42:38 +02:00
}
NTSTATUS RetrieveInMemoryModuleExecutableSections(
_In_ PIRP Irp
)
{
NTSTATUS status;
SIZE_T bytes_written = NULL;
PVOID buffer = NULL;
RTL_MODULE_EXTENDED_INFO module_info = { 0 };
status = GetModuleInformationByName(
&module_info,
"driver.sys"
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "GetModuleInformationByName failed with status %x", status );
return status;
}
status = StoreModuleExecutableRegionsInBuffer(
&buffer,
module_info.ImageBase,
module_info.ImageSize,
&bytes_written
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "StoreModuleExecutableRegionsInBuffe failed with status %x", status );
return status;
}
Irp->IoStatus.Information = bytes_written;
RtlCopyMemory(
Irp->AssociatedIrp.SystemBuffer,
buffer,
bytes_written
);
if ( buffer )
ExFreePoolWithTag( buffer, POOL_TAG_INTEGRITY );
return status;
2023-08-22 19:32:25 +02:00
}