mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
integrity check ALMOST there fucking stoopid pe bullshit
This commit is contained in:
parent
ee4046d99d
commit
12de715264
5 changed files with 160 additions and 178 deletions
|
@ -171,7 +171,7 @@ NTSTATUS DriverEntry(
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
MapDiskImageIntoVirtualAddressSpace,
|
||||
VerifyInMemoryImageVsDiskImage,
|
||||
NULL
|
||||
);
|
||||
|
||||
|
|
|
@ -44,33 +44,21 @@ NTSTATUS GetDriverImageSize(
|
|||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS CopyDriverExecutableRegions(
|
||||
_In_ PIRP Irp
|
||||
NTSTATUS GetModuleInformationByName(
|
||||
_In_ PRTL_MODULE_EXTENDED_INFO ModuleInfo,
|
||||
_In_ LPCSTR ModuleName
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
SYSTEM_MODULES modules = { 0 };
|
||||
PRTL_MODULE_EXTENDED_INFO driver_info;
|
||||
PVOID mapped_address;
|
||||
PHYSICAL_ADDRESS physical_address;
|
||||
PIMAGE_DOS_HEADER dos_header;
|
||||
PLOCAL_NT_HEADER nt_header;
|
||||
PIMAGE_SECTION_HEADER section;
|
||||
ULONG total_packet_size = 0;
|
||||
ULONG previous_section_size = 0;
|
||||
PVOID buffer = NULL;
|
||||
ULONG num_sections = 0;
|
||||
ULONG num_executable_sections = 0;
|
||||
UINT64 buffer_base;
|
||||
ULONG bytes_returned;
|
||||
MM_COPY_ADDRESS address;
|
||||
|
||||
status = GetSystemModuleInformation( &modules );
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "GetSystemModuleInformation failed with status %x", status );
|
||||
goto end;
|
||||
return status;
|
||||
}
|
||||
|
||||
driver_info = FindSystemModuleByName(
|
||||
|
@ -78,116 +66,19 @@ NTSTATUS CopyDriverExecutableRegions(
|
|||
&modules
|
||||
);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
buffer = ExAllocatePool2( POOL_FLAG_NON_PAGED, driver_info->ImageSize + sizeof( INTEGRITY_CHECK_HEADER ), POOL_TAG_INTEGRITY);
|
||||
ModuleInfo->FileNameOffset = driver_info->FileNameOffset;
|
||||
ModuleInfo->ImageBase = driver_info->ImageBase;
|
||||
ModuleInfo->ImageSize = driver_info->ImageSize;
|
||||
|
||||
if ( !buffer )
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Note: Verifier doesn't like it when we map the module :c
|
||||
*/
|
||||
|
||||
dos_header = ( PIMAGE_DOS_HEADER )driver_info->ImageBase;
|
||||
|
||||
/*
|
||||
* 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 )driver_info->ImageBase + 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++ )
|
||||
{
|
||||
if ( section->Characteristics & IMAGE_SCN_MEM_EXECUTE )
|
||||
{
|
||||
DEBUG_LOG( "Found executable section with name: %s", section->Name );
|
||||
|
||||
/*
|
||||
* 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 );
|
||||
goto end;
|
||||
}
|
||||
|
||||
address.VirtualAddress = ( UINT64 )driver_info->ImageBase + 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 );
|
||||
goto end;
|
||||
}
|
||||
|
||||
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 )
|
||||
RtlCopyMemory(
|
||||
ModuleInfo->FullPathName,
|
||||
driver_info->FullPathName,
|
||||
sizeof( ModuleInfo->FullPathName )
|
||||
);
|
||||
|
||||
//Irp->IoStatus.Information = total_packet_size;
|
||||
|
||||
//RtlCopyMemory(
|
||||
// Irp->AssociatedIrp.SystemBuffer,
|
||||
// buffer,
|
||||
// total_packet_size
|
||||
//);
|
||||
|
||||
end:
|
||||
|
||||
//Irp->IoStatus.Status = status;
|
||||
|
||||
if ( modules.address )
|
||||
ExFreePoolWithTag( modules.address, SYSTEM_MODULES_POOL );
|
||||
|
||||
if ( buffer )
|
||||
ExFreePoolWithTag( buffer, POOL_TAG_INTEGRITY );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -208,6 +99,11 @@ NTSTATUS StoreModuleExecutableRegionsInBuffer(
|
|||
ULONG bytes_returned;
|
||||
MM_COPY_ADDRESS address;
|
||||
|
||||
if ( !ModuleBase || !ModuleSize )
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
DEBUG_LOG( "Module base: %llx, size: %llx", (UINT64)ModuleBase, ModuleSize );
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -243,10 +139,10 @@ 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 )
|
||||
{
|
||||
DEBUG_LOG( "Found executable section with name: %s", section->Name );
|
||||
|
||||
/*
|
||||
* Note: MmCopyMemory will fail on discardable sections.
|
||||
*/
|
||||
|
@ -305,33 +201,48 @@ NTSTATUS StoreModuleExecutableRegionsInBuffer(
|
|||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to perform the relocations using the base address of the in memory
|
||||
* module to ensure all offsets are equal across both images.
|
||||
*/
|
||||
NTSTATUS PerformPeHeaderRelocations(
|
||||
_In_ PVOID ImageBase,
|
||||
_In_ PVOID RelocationBase
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
}
|
||||
|
||||
NTSTATUS MapDiskImageIntoVirtualAddressSpace(
|
||||
_In_ PHANDLE SectionHandle,
|
||||
_In_ PHANDLE FileHandle,
|
||||
_In_ PVOID* Section,
|
||||
_In_ PUNICODE_STRING Path,
|
||||
_In_ PSIZE_T Size
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE file_handle;
|
||||
OBJECT_ATTRIBUTES object_attributes;
|
||||
PIO_STATUS_BLOCK pio_block;
|
||||
UNICODE_STRING path;
|
||||
|
||||
RtlInitUnicodeString( &path, L"\\SystemRoot\\System32\\Drivers\\driver.sys" );
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&object_attributes,
|
||||
Path,
|
||||
&path,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
status = ZwOpenFile(
|
||||
FileHandle,
|
||||
FILE_GENERIC_READ | SYNCHRONIZE,
|
||||
&file_handle,
|
||||
FILE_GENERIC_EXECUTE | SYNCHRONIZE,
|
||||
&object_attributes,
|
||||
&pio_block,
|
||||
FILE_SHARE_READ,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT
|
||||
FILE_GENERIC_EXECUTE,
|
||||
NULL
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
|
@ -341,6 +252,13 @@ NTSTATUS MapDiskImageIntoVirtualAddressSpace(
|
|||
}
|
||||
|
||||
object_attributes.ObjectName = NULL;
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "NTSetInformationProcess failed with status %x", status );
|
||||
ZwClose( file_handle );
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Its important that we set the SEC_IMAGE flag with the PAGE_READONLY
|
||||
|
@ -351,21 +269,21 @@ NTSTATUS MapDiskImageIntoVirtualAddressSpace(
|
|||
SECTION_ALL_ACCESS,
|
||||
&object_attributes,
|
||||
NULL,
|
||||
PAGE_READONLY,
|
||||
PAGE_EXECUTE_READWRITE,
|
||||
SEC_IMAGE,
|
||||
*FileHandle
|
||||
file_handle
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "ZwCreateSection failed with status %x", status );
|
||||
ZwClose( FileHandle );
|
||||
ZwClose( file_handle );
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ZwMapViewOfSection(
|
||||
*SectionHandle,
|
||||
NtCurrentProcess(),
|
||||
ZwCurrentProcess(),
|
||||
Section,
|
||||
NULL,
|
||||
NULL,
|
||||
|
@ -373,18 +291,21 @@ NTSTATUS MapDiskImageIntoVirtualAddressSpace(
|
|||
Size,
|
||||
ViewUnmap,
|
||||
MEM_TOP_DOWN,
|
||||
PAGE_READONLY
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "ZwMapViewOfSection failed with status %x", status );
|
||||
ZwClose( *FileHandle );
|
||||
ZwClose( file_handle );
|
||||
ZwClose( *SectionHandle );
|
||||
return status;
|
||||
}
|
||||
|
||||
DEBUG_LOG( "mapped LOL!" );
|
||||
ZwClose( file_handle );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -401,21 +322,23 @@ NTSTATUS VerifyInMemoryImageVsDiskImage(
|
|||
NTSTATUS status;
|
||||
UNICODE_STRING path;
|
||||
HANDLE section_handle = NULL;
|
||||
HANDLE file_handle = NULL;
|
||||
PVOID section = NULL;
|
||||
SIZE_T section_size = NULL;
|
||||
PVOID disk_buffer = NULL;
|
||||
PVOID in_memory_buffer = NULL;
|
||||
RTL_MODULE_EXTENDED_INFO module_info = { 0 };
|
||||
|
||||
|
||||
/*
|
||||
* Map the disk image into memory and parse it.
|
||||
* Map the disk image into memory and parse it. Note that we still need to parse the PE
|
||||
* file since the on-disk version is different to the in memory module before we
|
||||
* compare the executable sections.
|
||||
*/
|
||||
|
||||
RtlInitUnicodeString( &path, L"\\SystemRoot\\System32\\Drivers\\driver.sys" );
|
||||
|
||||
status = MapDiskImageIntoVirtualAddressSpace(
|
||||
§ion_handle,
|
||||
&file_handle,
|
||||
§ion,
|
||||
&path,
|
||||
§ion_size
|
||||
|
@ -443,18 +366,63 @@ NTSTATUS VerifyInMemoryImageVsDiskImage(
|
|||
* Parse the in-memory module
|
||||
*/
|
||||
|
||||
status = GetModuleInformationByName(
|
||||
&module_info,
|
||||
"driver.sys"
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "GetModuleInformationByName failed with status %x", status );
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = StoreModuleExecutableRegionsInBuffer(
|
||||
&in_memory_buffer,
|
||||
module_info.ImageBase,
|
||||
module_info.ImageSize
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "StoreModuleExecutableRegionsInBuffe failed with status %x", status );
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* The in memory text section seems to be around 1k bytes larger then on disk section
|
||||
*/
|
||||
UINT64 disk_base = ( UINT64 )( ( UINT64 )disk_buffer + sizeof( INTEGRITY_CHECK_HEADER ) + sizeof( IMAGE_SECTION_HEADER ) );
|
||||
UINT64 memory_base = ( UINT64 )( ( UINT64 )in_memory_buffer + sizeof( INTEGRITY_CHECK_HEADER ) + sizeof( IMAGE_SECTION_HEADER ) );
|
||||
|
||||
PIMAGE_SECTION_HEADER disk_text_header = ( PIMAGE_SECTION_HEADER )( ( UINT64 )disk_buffer + sizeof( INTEGRITY_CHECK_HEADER ) );
|
||||
|
||||
if ( !disk_base || !memory_base || !disk_buffer || !in_memory_buffer )
|
||||
{
|
||||
DEBUG_ERROR( "buffers are null lmao" );
|
||||
goto end;
|
||||
}
|
||||
|
||||
DEBUG_LOG( "Disk base: %llx, memory base: %llx, disk_text header: %llx", disk_base, memory_base, ( UINT64 )disk_text_header );
|
||||
|
||||
DEBUG_LOG( "Disk text header size of data: %lx", disk_text_header->SizeOfRawData );
|
||||
|
||||
int result = RtlCompareMemory( (PVOID)disk_base, (PVOID)memory_base, disk_text_header->SizeOfRawData - 8000 );
|
||||
|
||||
DEBUG_LOG( "Result: %lx", result );
|
||||
|
||||
__debugbreak();
|
||||
|
||||
end:
|
||||
|
||||
ZwUnmapViewOfSection( NtCurrentProcess(), section );
|
||||
|
||||
if (file_handle != NULL )
|
||||
ZwClose( file_handle );
|
||||
|
||||
if (section_handle != NULL )
|
||||
if ( section_handle != NULL )
|
||||
ZwClose( section_handle );
|
||||
|
||||
if (disk_buffer )
|
||||
if ( disk_buffer )
|
||||
ExFreePoolWithTag( disk_buffer, POOL_TAG_INTEGRITY );
|
||||
|
||||
if ( in_memory_buffer )
|
||||
ExFreePoolWithTag( in_memory_buffer, POOL_TAG_INTEGRITY );
|
||||
}
|
|
@ -13,6 +13,17 @@ NTSTATUS GetDriverImageSize(
|
|||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS VerifyInMemoryImageVsDiskImage();
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtSetInformationProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ PROCESSINFOCLASS ProcessInformationClass,
|
||||
_In_ PVOID ProcessInformation,
|
||||
_In_ ULONG ProcessInformationLength
|
||||
);
|
||||
|
||||
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
|
||||
|
||||
#define IMAGE_SIZEOF_SHORT_NAME 8
|
||||
|
|
|
@ -150,47 +150,47 @@ NTSTATUS DeviceControl(
|
|||
|
||||
case IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS:
|
||||
|
||||
status = PsCreateSystemThread(
|
||||
&handle,
|
||||
PROCESS_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
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;
|
||||
}
|
||||
//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
|
||||
);
|
||||
//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;
|
||||
}
|
||||
//if ( !NT_SUCCESS( status ) )
|
||||
//{
|
||||
// DEBUG_ERROR( "ObReferenceObjectbyhandle failed with status %lx", status );
|
||||
// ZwClose( handle );
|
||||
// goto end;
|
||||
//}
|
||||
|
||||
PAGED_CODE();
|
||||
//PAGED_CODE();
|
||||
|
||||
KeWaitForSingleObject( thread, Executive, KernelMode, FALSE, NULL );;
|
||||
//KeWaitForSingleObject( thread, Executive, KernelMode, FALSE, NULL );;
|
||||
|
||||
ZwClose( handle );
|
||||
ObDereferenceObject( thread );
|
||||
//ZwClose( handle );
|
||||
//ObDereferenceObject( thread );
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
DEBUG_ERROR( "Failed to retrieve executable regions" );
|
||||
//if ( !NT_SUCCESS( status ) )
|
||||
// DEBUG_ERROR( "Failed to retrieve executable regions" );
|
||||
|
||||
break;
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@ CHAR WHITELISTED_MODULES[ WHITELISTED_MODULE_COUNT ][ MODULE_MAX_STRING_SIZE ] =
|
|||
"Wdf01000.sys",
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: this needs to be refactored to just return the entry not the whole fukin thing
|
||||
*/
|
||||
PRTL_MODULE_EXTENDED_INFO FindSystemModuleByName(
|
||||
_In_ LPCSTR ModuleName,
|
||||
_In_ PSYSTEM_MODULES SystemModules
|
||||
|
|
Loading…
Reference in a new issue