mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
make the integrity checks actually GOOD lolz
This commit is contained in:
parent
ab451e0eee
commit
dd38277278
6 changed files with 212 additions and 25 deletions
|
@ -3,6 +3,13 @@
|
|||
#include "common.h"
|
||||
#include "modules.h"
|
||||
|
||||
typedef struct _INTEGRITY_CHECK_HEADER
|
||||
{
|
||||
INT executable_section_count;
|
||||
LONG total_packet_size;
|
||||
|
||||
}INTEGRITY_CHECK_HEADER, *PINTEGRITY_CHECK_HEADER;
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -37,26 +44,24 @@ NTSTATUS GetDriverImageSize(
|
|||
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:
|
||||
*
|
||||
* TODO: We will hash this based on timestamp sent from the server.
|
||||
*/
|
||||
NTSTATUS CopyDriverExecutableRegions(
|
||||
NTSTATUS New_CopyDriverExecutableRegions(
|
||||
_In_ PIRP Irp
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
SYSTEM_MODULES modules = { 0 };
|
||||
PRTL_MODULE_EXTENDED_INFO driver_info;
|
||||
MM_COPY_ADDRESS address;
|
||||
PVOID mapped_address;
|
||||
PHYSICAL_ADDRESS physical_address;
|
||||
SIZE_T bytes_returned;
|
||||
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;
|
||||
|
||||
status = GetSystemModuleInformation( &modules );
|
||||
|
||||
|
@ -71,7 +76,16 @@ NTSTATUS CopyDriverExecutableRegions(
|
|||
&modules
|
||||
);
|
||||
|
||||
Irp->IoStatus.Information = driver_info->ImageSize;
|
||||
/*
|
||||
* 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);
|
||||
|
||||
if ( !buffer )
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Map the drivers physical memory into our IO space, then copy it into
|
||||
|
@ -79,6 +93,9 @@ NTSTATUS CopyDriverExecutableRegions(
|
|||
*/
|
||||
physical_address.QuadPart = MmGetPhysicalAddress( driver_info->ImageBase ).QuadPart;
|
||||
|
||||
/*
|
||||
* Verifier doesn't like it when we map system pages xD (sometimes ?)
|
||||
*/
|
||||
mapped_address = MmMapIoSpace(
|
||||
physical_address,
|
||||
driver_info->ImageSize,
|
||||
|
@ -91,14 +108,67 @@ NTSTATUS CopyDriverExecutableRegions(
|
|||
goto end;
|
||||
}
|
||||
|
||||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
mapped_address,
|
||||
driver_info->ImageSize
|
||||
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 );
|
||||
|
||||
RtlCopyMemory(
|
||||
( UINT64 )buffer_base + previous_section_size,
|
||||
section,
|
||||
sizeof( IMAGE_SECTION_HEADER )
|
||||
);
|
||||
|
||||
RtlCopyMemory(
|
||||
( UINT64 )buffer_base + sizeof( IMAGE_SECTION_HEADER ),
|
||||
( UINT64 )mapped_address + section->PointerToRawData,
|
||||
section->SizeOfRawData
|
||||
);
|
||||
|
||||
total_packet_size += section->SizeOfRawData + sizeof( IMAGE_SECTION_HEADER );
|
||||
num_executable_sections += 1;
|
||||
previous_section_size = sizeof( IMAGE_SECTION_HEADER ) + section->SizeOfRawData;
|
||||
}
|
||||
|
||||
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 )
|
||||
);
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
DEBUG_ERROR( "MmCopyMemory failed with status %x", status );
|
||||
Irp->IoStatus.Information = total_packet_size;
|
||||
|
||||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer,
|
||||
buffer,
|
||||
total_packet_size
|
||||
);
|
||||
|
||||
end:
|
||||
|
||||
|
@ -107,5 +177,8 @@ end:
|
|||
if ( modules.address )
|
||||
ExFreePoolWithTag( modules.address, SYSTEM_MODULES_POOL );
|
||||
|
||||
if ( buffer )
|
||||
ExFreePoolWithTag( buffer, POOL_TAG_INTEGRITY );
|
||||
|
||||
return status;
|
||||
}
|
|
@ -13,4 +13,113 @@ NTSTATUS GetDriverImageSize(
|
|||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
#endif
|
||||
NTSTATUS New_CopyDriverExecutableRegions(
|
||||
_In_ PIRP Irp
|
||||
);
|
||||
|
||||
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
|
||||
|
||||
#define IMAGE_SIZEOF_SHORT_NAME 8
|
||||
|
||||
typedef struct _IMAGE_SECTION_HEADER {
|
||||
unsigned char Name[ IMAGE_SIZEOF_SHORT_NAME ];
|
||||
union {
|
||||
unsigned long PhysicalAddress;
|
||||
unsigned long VirtualSize;
|
||||
} Misc;
|
||||
unsigned long VirtualAddress;
|
||||
unsigned long SizeOfRawData;
|
||||
unsigned long PointerToRawData;
|
||||
unsigned long PointerToRelocations;
|
||||
unsigned long PointerToLinenumbers;
|
||||
unsigned short NumberOfRelocations;
|
||||
unsigned short NumberOfLinenumbers;
|
||||
unsigned long Characteristics;
|
||||
} IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER;
|
||||
|
||||
typedef struct _IMAGE_FILE_HEADER {
|
||||
unsigned short Machine;
|
||||
unsigned short NumberOfSections;
|
||||
unsigned long TimeDateStamp;
|
||||
unsigned long PointerToSymbolTable;
|
||||
unsigned long NumberOfSymbols;
|
||||
unsigned short SizeOfOptionalHeader;
|
||||
unsigned short Characteristics;
|
||||
} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER;
|
||||
|
||||
typedef struct _IMAGE_DATA_DIRECTORY {
|
||||
unsigned long VirtualAddress;
|
||||
unsigned long Size;
|
||||
} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;
|
||||
|
||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER64 {
|
||||
unsigned short Magic;
|
||||
unsigned char MajorLinkerVersion;
|
||||
unsigned char MinorLinkerVersion;
|
||||
unsigned long SizeOfCode;
|
||||
unsigned long SizeOfInitializedData;
|
||||
unsigned long SizeOfUninitializedData;
|
||||
unsigned long AddressOfEntryPoint;
|
||||
unsigned long BaseOfCode;
|
||||
ULONGLONG ImageBase;
|
||||
unsigned long SectionAlignment;
|
||||
unsigned long FileAlignment;
|
||||
unsigned short MajorOperatingSystemVersion;
|
||||
unsigned short MinorOperatingSystemVersion;
|
||||
unsigned short MajorImageVersion;
|
||||
unsigned short MinorImageVersion;
|
||||
unsigned short MajorSubsystemVersion;
|
||||
unsigned short MinorSubsystemVersion;
|
||||
unsigned long Win32VersionValue;
|
||||
unsigned long SizeOfImage;
|
||||
unsigned long SizeOfHeaders;
|
||||
unsigned long CheckSum;
|
||||
unsigned short Subsystem;
|
||||
unsigned short DllCharacteristics;
|
||||
ULONGLONG SizeOfStackReserve;
|
||||
ULONGLONG SizeOfStackCommit;
|
||||
ULONGLONG SizeOfHeapReserve;
|
||||
ULONGLONG SizeOfHeapCommit;
|
||||
unsigned long LoaderFlags;
|
||||
unsigned long NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[ IMAGE_NUMBEROF_DIRECTORY_ENTRIES ];
|
||||
} IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64;
|
||||
|
||||
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
|
||||
unsigned short e_magic; // Magic number
|
||||
unsigned short e_cblp; // Bytes on last page of file
|
||||
unsigned short e_cp; // Pages in file
|
||||
unsigned short e_crlc; // Relocations
|
||||
unsigned short e_cparhdr; // Size of header in paragraphs
|
||||
unsigned short e_minalloc; // Minimum extra paragraphs needed
|
||||
unsigned short e_maxalloc; // Maximum extra paragraphs needed
|
||||
unsigned short e_ss; // Initial (relative) SS value
|
||||
unsigned short e_sp; // Initial SP value
|
||||
unsigned short e_csum; // Checksum
|
||||
unsigned short e_ip; // Initial IP value
|
||||
unsigned short e_cs; // Initial (relative) CS value
|
||||
unsigned short e_lfarlc; // File address of relocation table
|
||||
unsigned short e_ovno; // Overlay number
|
||||
unsigned short e_res[ 4 ]; // Reserved words
|
||||
unsigned short e_oemid; // OEM identifier (for e_oeminfo)
|
||||
unsigned short e_oeminfo; // OEM information; e_oemid specific
|
||||
unsigned short e_res2[ 10 ]; // Reserved words
|
||||
LONG e_lfanew; // File address of new exe header
|
||||
} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER;
|
||||
|
||||
typedef struct _LOCAL_NT_HEADER {
|
||||
unsigned long Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
} LOCAL_NT_HEADER, * PLOCAL_NT_HEADER;
|
||||
|
||||
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \
|
||||
((ULONG_PTR)(ntheader) + \
|
||||
FIELD_OFFSET( LOCAL_NT_HEADER, OptionalHeader ) + \
|
||||
((ntheader))->FileHeader.SizeOfOptionalHeader \
|
||||
))
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ NTSTATUS DeviceControl(
|
|||
*/
|
||||
ReadInitialisedConfigFlag( &security_flag );
|
||||
|
||||
if ( security_flag == FALSE )
|
||||
if ( security_flag == FALSE &&
|
||||
stack_location->Parameters.DeviceIoControl.IoControlCode != IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH )
|
||||
goto end;
|
||||
|
||||
switch ( stack_location->Parameters.DeviceIoControl.IoControlCode )
|
||||
|
@ -154,7 +155,7 @@ NTSTATUS DeviceControl(
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
CopyDriverExecutableRegions,
|
||||
New_CopyDriverExecutableRegions,
|
||||
Irp
|
||||
);
|
||||
|
||||
|
|
|
@ -308,6 +308,11 @@ VOID kernelmode::Driver::RequestModuleExecutableRegions()
|
|||
|
||||
LOG_INFO( "module size: %lx", module_size );
|
||||
|
||||
/*
|
||||
* allocate a buffer big enough for the entire module not including section headers or
|
||||
* packet headers, however it should be big enough since executable sections do not
|
||||
* make up 100% of the image size. Bit hacky but it works.
|
||||
*/
|
||||
buffer = malloc( module_size );
|
||||
|
||||
if ( !buffer )
|
||||
|
@ -332,7 +337,7 @@ VOID kernelmode::Driver::RequestModuleExecutableRegions()
|
|||
|
||||
LOG_INFO( "bytes returned: %lx", bytes_returned );
|
||||
|
||||
this->report_interface->ServerSend( buffer, module_size, SERVER_SEND_MODULE_INTEGRITY_CHECK );
|
||||
this->report_interface->ServerSend( buffer, bytes_returned, SERVER_SEND_MODULE_INTEGRITY_CHECK );
|
||||
|
||||
end:
|
||||
free( buffer );
|
||||
|
|
|
@ -44,7 +44,6 @@ namespace kernelmode
|
|||
VOID ValidateKPRCBThreads();
|
||||
VOID CheckHandleTableEntries();
|
||||
VOID RequestModuleExecutableRegions();
|
||||
/* todo: driver integrity check */
|
||||
};
|
||||
|
||||
struct DRIVER_INITIATION_INFORMATION
|
||||
|
|
|
@ -31,7 +31,7 @@ DWORD WINAPI Init(HINSTANCE hinstDLL)
|
|||
//kmanager.MonitorCallbackReports();
|
||||
//kmanager.RunNmiCallbacks();
|
||||
//kmanager.VerifySystemModules();
|
||||
//kmanager.RequestModuleExecutableRegionsForIntegrityCheck();
|
||||
kmanager.RequestModuleExecutableRegionsForIntegrityCheck();
|
||||
//kmanager.MonitorCallbackReports();
|
||||
|
||||
//umanager.ValidateProcessModules();
|
||||
|
|
Loading…
Reference in a new issue