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 "common.h"
|
||||||
#include "modules.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
|
* 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
|
* in both the get driver image ioctl handler and the CopyDriverExecvutableRegions func
|
||||||
|
@ -37,26 +44,24 @@ NTSTATUS GetDriverImageSize(
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
NTSTATUS New_CopyDriverExecutableRegions(
|
||||||
* 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(
|
|
||||||
_In_ PIRP Irp
|
_In_ PIRP Irp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
SYSTEM_MODULES modules = { 0 };
|
SYSTEM_MODULES modules = { 0 };
|
||||||
PRTL_MODULE_EXTENDED_INFO driver_info;
|
PRTL_MODULE_EXTENDED_INFO driver_info;
|
||||||
MM_COPY_ADDRESS address;
|
|
||||||
PVOID mapped_address;
|
PVOID mapped_address;
|
||||||
PHYSICAL_ADDRESS physical_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 );
|
status = GetSystemModuleInformation( &modules );
|
||||||
|
|
||||||
|
@ -71,7 +76,16 @@ NTSTATUS CopyDriverExecutableRegions(
|
||||||
&modules
|
&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
|
* 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;
|
physical_address.QuadPart = MmGetPhysicalAddress( driver_info->ImageBase ).QuadPart;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verifier doesn't like it when we map system pages xD (sometimes ?)
|
||||||
|
*/
|
||||||
mapped_address = MmMapIoSpace(
|
mapped_address = MmMapIoSpace(
|
||||||
physical_address,
|
physical_address,
|
||||||
driver_info->ImageSize,
|
driver_info->ImageSize,
|
||||||
|
@ -91,14 +108,67 @@ NTSTATUS CopyDriverExecutableRegions(
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlCopyMemory(
|
dos_header = ( PIMAGE_DOS_HEADER )driver_info->ImageBase;
|
||||||
Irp->AssociatedIrp.SystemBuffer,
|
|
||||||
mapped_address,
|
/*
|
||||||
driver_info->ImageSize
|
* 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 ) )
|
Irp->IoStatus.Information = total_packet_size;
|
||||||
DEBUG_ERROR( "MmCopyMemory failed with status %x", status );
|
|
||||||
|
RtlCopyMemory(
|
||||||
|
Irp->AssociatedIrp.SystemBuffer,
|
||||||
|
buffer,
|
||||||
|
total_packet_size
|
||||||
|
);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
|
||||||
|
@ -107,5 +177,8 @@ end:
|
||||||
if ( modules.address )
|
if ( modules.address )
|
||||||
ExFreePoolWithTag( modules.address, SYSTEM_MODULES_POOL );
|
ExFreePoolWithTag( modules.address, SYSTEM_MODULES_POOL );
|
||||||
|
|
||||||
|
if ( buffer )
|
||||||
|
ExFreePoolWithTag( buffer, POOL_TAG_INTEGRITY );
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
|
@ -13,4 +13,113 @@ NTSTATUS GetDriverImageSize(
|
||||||
_In_ PIRP Irp
|
_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 );
|
ReadInitialisedConfigFlag( &security_flag );
|
||||||
|
|
||||||
if ( security_flag == FALSE )
|
if ( security_flag == FALSE &&
|
||||||
|
stack_location->Parameters.DeviceIoControl.IoControlCode != IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH )
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
switch ( stack_location->Parameters.DeviceIoControl.IoControlCode )
|
switch ( stack_location->Parameters.DeviceIoControl.IoControlCode )
|
||||||
|
@ -154,7 +155,7 @@ NTSTATUS DeviceControl(
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
CopyDriverExecutableRegions,
|
New_CopyDriverExecutableRegions,
|
||||||
Irp
|
Irp
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -308,6 +308,11 @@ VOID kernelmode::Driver::RequestModuleExecutableRegions()
|
||||||
|
|
||||||
LOG_INFO( "module size: %lx", module_size );
|
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 );
|
buffer = malloc( module_size );
|
||||||
|
|
||||||
if ( !buffer )
|
if ( !buffer )
|
||||||
|
@ -332,7 +337,7 @@ VOID kernelmode::Driver::RequestModuleExecutableRegions()
|
||||||
|
|
||||||
LOG_INFO( "bytes returned: %lx", bytes_returned );
|
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:
|
end:
|
||||||
free( buffer );
|
free( buffer );
|
||||||
|
|
|
@ -44,7 +44,6 @@ namespace kernelmode
|
||||||
VOID ValidateKPRCBThreads();
|
VOID ValidateKPRCBThreads();
|
||||||
VOID CheckHandleTableEntries();
|
VOID CheckHandleTableEntries();
|
||||||
VOID RequestModuleExecutableRegions();
|
VOID RequestModuleExecutableRegions();
|
||||||
/* todo: driver integrity check */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DRIVER_INITIATION_INFORMATION
|
struct DRIVER_INITIATION_INFORMATION
|
||||||
|
|
|
@ -31,7 +31,7 @@ DWORD WINAPI Init(HINSTANCE hinstDLL)
|
||||||
//kmanager.MonitorCallbackReports();
|
//kmanager.MonitorCallbackReports();
|
||||||
//kmanager.RunNmiCallbacks();
|
//kmanager.RunNmiCallbacks();
|
||||||
//kmanager.VerifySystemModules();
|
//kmanager.VerifySystemModules();
|
||||||
//kmanager.RequestModuleExecutableRegionsForIntegrityCheck();
|
kmanager.RequestModuleExecutableRegionsForIntegrityCheck();
|
||||||
//kmanager.MonitorCallbackReports();
|
//kmanager.MonitorCallbackReports();
|
||||||
|
|
||||||
//umanager.ValidateProcessModules();
|
//umanager.ValidateProcessModules();
|
||||||
|
|
Loading…
Reference in a new issue