mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
fix up pool reporting system
This commit is contained in:
parent
86316e9bbf
commit
6958b7090b
9 changed files with 69 additions and 64 deletions
|
@ -2,6 +2,15 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
/*
|
||||
* Massive WIP from which I have essentially just copied from these 2 repos:
|
||||
*
|
||||
* https://github.com/yardenshafir/MitigationFlagsCliTool
|
||||
* https://github.com/lilhoser/livedump
|
||||
*
|
||||
* just to help with leraning the windows debugger api
|
||||
*/
|
||||
|
||||
static NtSystemDebugControl g_NtSystemDebugControl = NULL;
|
||||
|
||||
BOOL
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#define OBJECT_HEADER_TYPE_INDEX_OFFSET 0x018
|
||||
|
||||
#define POOL_HEADER_BLOCK_SIZE_OFFSET 0x02
|
||||
#define POOL_HEADER_TAG_OFFSET 0x04
|
||||
|
||||
#define KPROCESS_OFFSET_FROM_POOL_HEADER_SIZE_1 0x70
|
||||
#define KPROCESS_OFFSET_FROM_POOL_HEADER_SIZE_2 0x80
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#define MOTHERBOARD_SERIAL_CODE_LENGTH 64
|
||||
#define DEVICE_DRIVE_0_SERIAL_CODE_LENGTH 64
|
||||
|
||||
#define MAX_REPORTS_PER_IRP 20
|
||||
|
||||
#define POOL_TAG_STRINGS 'strs'
|
||||
|
||||
#define IOCTL_STORAGE_QUERY_PROPERTY 0x002D1400
|
||||
|
|
|
@ -249,14 +249,6 @@ NTSTATUS MapDiskImageIntoVirtualAddressSpace(
|
|||
}
|
||||
|
||||
object_attributes.ObjectName = NULL;
|
||||
|
||||
if ( !NT_SUCCESS( status ) )
|
||||
{
|
||||
DEBUG_ERROR( "NTSetInformationProcess failed with status %x", status );
|
||||
ZwClose( file_handle );
|
||||
//TerminateProtectedProcessOnViolation();
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Its important that we set the SEC_IMAGE flag with the PAGE_READONLY
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "common.h"
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "queue.h"
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
|
@ -79,7 +80,6 @@ VOID GetPsActiveProcessHead(
|
|||
_In_ PUINT64 Address
|
||||
)
|
||||
{
|
||||
/* TODO: have a global debugger pool here since shit aint really change */
|
||||
PKDDEBUGGER_DATA64 debugger_data = GetGlobalDebuggerData();
|
||||
|
||||
*Address = *( UINT64* )( debugger_data->PsActiveProcessHead );
|
||||
|
@ -166,14 +166,6 @@ BOOLEAN ValidateIfAddressIsProcessStructure(
|
|||
}
|
||||
|
||||
/*
|
||||
* For ~90% of EPROCESS structures the header layout is as follows:
|
||||
*
|
||||
* Pool base + 0x00 = ?? (not sure what structure lies here)
|
||||
* Pool base + 0x10 = OBJECT_HEADER_QUOTA_INFO
|
||||
* Pool base + 0x30 = OBJECT_HEADER_HANDLE_INFO
|
||||
* Pool base + 0x40 = OBJECT_HEADER
|
||||
* Pool base + 0x70 = EPROCESS
|
||||
*
|
||||
* OBJECT_HEADER->InfoMask is a bit mask that tells us which optional
|
||||
* headers the object has. The bits are as follows:
|
||||
*
|
||||
|
@ -232,12 +224,19 @@ VOID ScanPageForKernelObjectAllocation(
|
|||
|
||||
if ( sig_index == POOL_TAG_LENGTH )
|
||||
{
|
||||
pool_header = ( UINT64 )PageBase + offset - 0x04;
|
||||
pool_header = ( UINT64 )PageBase + offset - POOL_HEADER_TAG_OFFSET;
|
||||
|
||||
if ( !MmIsAddressValid( ( PVOID )pool_header ) )
|
||||
break;
|
||||
|
||||
for ( ULONG header_size = 0x30; header_size < 0xb0; header_size += 0x10 )
|
||||
/*
|
||||
* Since every executive allocation is required to have an _OBJECT_HEADER, we start
|
||||
* iterating from the size of this object header, then jump up in blocks of 0x10 since
|
||||
* every object header is divisible by 0x10. We iterate up to 0xb0 which is equal to the following:
|
||||
*
|
||||
* 0xb0 = sizeof(ALL_HEADER_OBJECTS) + 0x10 where the 0x10 is 16 bytes of padding.
|
||||
*/
|
||||
for ( ULONG header_size = OBJECT_HEADER_SIZE; header_size < 0xb0; header_size += 0x10 )
|
||||
{
|
||||
test_process = ( PEPROCESS )( ( UINT64 )pool_header + sizeof( POOL_HEADER ) + header_size );
|
||||
|
||||
|
@ -309,10 +308,13 @@ VOID EnumerateKernelLargePages(
|
|||
_In_ ULONG ObjectIndex
|
||||
)
|
||||
{
|
||||
/*
|
||||
* Split the large pages up into blocks of 0x1000 and scan each block
|
||||
*/
|
||||
for ( INT page_index = 0; page_index < PageSize; page_index++ )
|
||||
{
|
||||
ScanPageForKernelObjectAllocation(
|
||||
PageBase + ( page_index * PageSize ),
|
||||
PageBase + ( page_index * PAGE_SIZE ),
|
||||
PAGE_SIZE,
|
||||
ObjectIndex,
|
||||
AddressBuffer
|
||||
|
@ -545,17 +547,6 @@ VOID CheckIfProcessAllocationIsInProcessList(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Plan:
|
||||
* 1. Find number of running procs and allocate a pool equal to size 1.5 * num_procs.
|
||||
* 2. Walk the pages tables and store all found process allocation base addresses in this pool
|
||||
* 3. Enumerate the process allocation list and make sure that each allocation is within
|
||||
* 0x50 bytes of the EPROCESS base of one of the running processes.
|
||||
* 4. If there exists a process allocation that doesn't have a matching running process,
|
||||
* make sure it hasnt been deallocated
|
||||
* 5. If it hasn't been deallocated, search for the .exe via the long string file name
|
||||
* and report. Maybe do some further analysis can figure this out once we get there.
|
||||
*/
|
||||
NTSTATUS FindUnlinkedProcesses(
|
||||
_In_ PIRP Irp
|
||||
)
|
||||
|
@ -581,8 +572,6 @@ NTSTATUS FindUnlinkedProcesses(
|
|||
|
||||
WalkKernelPageTables( process_buffer );
|
||||
|
||||
__debugbreak();
|
||||
|
||||
EnumerateProcessListWithCallbackFunction(
|
||||
CheckIfProcessAllocationIsInProcessList,
|
||||
NULL
|
||||
|
@ -595,41 +584,31 @@ NTSTATUS FindUnlinkedProcesses(
|
|||
if ( allocation_address[ i ] == NULL )
|
||||
continue;
|
||||
|
||||
/* process has been deallocated yet the pool header hasnt been updated? */
|
||||
if ( *( UINT8* )( allocation_address[ i ] + EPROCESS_PEAK_VIRTUAL_SIZE_OFFSET ) == 0x00 )
|
||||
continue;
|
||||
|
||||
/* report / do some further analysis */
|
||||
/* report / do some further analysis etc. */
|
||||
DEBUG_ERROR( "INVALID POOL proc OMGGG" );
|
||||
|
||||
report_buffer = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( INVALID_PROCESS_ALLOCATION_REPORT ), INVALID_PROCESS_REPORT_TAG );
|
||||
report_buffer = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( INVALID_PROCESS_ALLOCATION_REPORT ), REPORT_POOL_TAG );
|
||||
|
||||
if ( !report_buffer )
|
||||
goto end;
|
||||
|
||||
//report_buffer->report_code = REPORT_INVALID_PROCESS_ALLOCATION;
|
||||
report_buffer->report_code = REPORT_INVALID_PROCESS_ALLOCATION;
|
||||
|
||||
//RtlCopyMemory(
|
||||
// report_buffer->process,
|
||||
// allocation_address[ i ],
|
||||
// REPORT_INVALID_PROCESS_BUFFER_SIZE );
|
||||
RtlCopyMemory(
|
||||
report_buffer->process,
|
||||
(UINT64)allocation_address[ i ] - OBJECT_HEADER_SIZE,
|
||||
REPORT_INVALID_PROCESS_BUFFER_SIZE
|
||||
);
|
||||
|
||||
//Irp->IoStatus.Information = sizeof( INVALID_PROCESS_ALLOCATION_REPORT );
|
||||
|
||||
//RtlCopyMemory(
|
||||
// Irp->AssociatedIrp.SystemBuffer,
|
||||
// report_buffer,
|
||||
// sizeof( INVALID_PROCESS_ALLOCATION_REPORT ) );
|
||||
InsertReportToQueue( report_buffer );
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
if ( report_buffer )
|
||||
ExFreePoolWithTag( report_buffer, INVALID_PROCESS_REPORT_TAG );
|
||||
|
||||
if ( process_buffer )
|
||||
ExFreePoolWithTag( process_buffer, PROCESS_ADDRESS_LIST_TAG );
|
||||
|
||||
/* todo: make use of the new context variable in the enum proc func */
|
||||
process_count = NULL;
|
||||
process_buffer = NULL;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <ntifs.h>
|
||||
#include "common.h"
|
||||
|
||||
#define REPORT_INVALID_PROCESS_BUFFER_SIZE 4096
|
||||
#define REPORT_INVALID_PROCESS_BUFFER_SIZE 4000 // we want to make sure this allocation fits on a page
|
||||
|
||||
#define PAGE_BASE_SIZE 0x1000
|
||||
#define POOL_TAG_SIZE 0x004
|
||||
|
|
|
@ -204,6 +204,17 @@ NTSTATUS HandlePeriodicGlobalReportQueueQuery(
|
|||
|
||||
total_size += sizeof( ATTACH_PROCESS_REPORT );
|
||||
break;
|
||||
|
||||
case REPORT_INVALID_PROCESS_ALLOCATION:
|
||||
|
||||
RtlCopyMemory(
|
||||
( UINT64 )report_buffer + sizeof( GLOBAL_REPORT_QUEUE_HEADER ) + total_size,
|
||||
report,
|
||||
sizeof( INVALID_PROCESS_ALLOCATION_REPORT )
|
||||
);
|
||||
|
||||
total_size += sizeof( INVALID_PROCESS_ALLOCATION_REPORT );
|
||||
break;
|
||||
}
|
||||
|
||||
/* QueuePop frees the node, but we still need to free the returned data */
|
||||
|
|
|
@ -143,7 +143,7 @@ namespace global
|
|||
CHAR driver_name[ 128 ];
|
||||
};
|
||||
|
||||
struct OPEN_HANDLE_FAILURE_REPORT_HEADER
|
||||
struct REPORT_QUEUE_HEADER
|
||||
{
|
||||
INT count;
|
||||
};
|
||||
|
|
|
@ -174,8 +174,9 @@ VOID kernelmode::Driver::QueryReportQueue()
|
|||
SIZE_T total_size = NULL;
|
||||
global::report_structures::OPEN_HANDLE_FAILURE_REPORT* handle_report;
|
||||
global::report_structures::ATTACH_PROCESS_REPORT* attach_report;
|
||||
global::report_structures::INVALID_PROCESS_ALLOCATION_REPORT* allocation_report;
|
||||
|
||||
buffer_size = 1024 * 2;
|
||||
buffer_size = sizeof( global::report_structures::INVALID_PROCESS_ALLOCATION_REPORT ) * MAX_REPORTS_PER_IRP;
|
||||
buffer = malloc( buffer_size );
|
||||
|
||||
status = DeviceIoControl(
|
||||
|
@ -196,8 +197,8 @@ VOID kernelmode::Driver::QueryReportQueue()
|
|||
return;
|
||||
}
|
||||
|
||||
global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER* header =
|
||||
( global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER* )buffer;
|
||||
global::report_structures::REPORT_QUEUE_HEADER* header =
|
||||
( global::report_structures::REPORT_QUEUE_HEADER* )buffer;
|
||||
|
||||
if ( !header )
|
||||
goto end;
|
||||
|
@ -209,15 +210,15 @@ VOID kernelmode::Driver::QueryReportQueue()
|
|||
|
||||
for ( INT i = 0; i < header->count; i++ )
|
||||
{
|
||||
report_header = (REPORT_ID*)( ( UINT64 )buffer +
|
||||
sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER ) + total_size );
|
||||
report_header = ( REPORT_ID* )( ( UINT64 )buffer +
|
||||
sizeof( global::report_structures::REPORT_QUEUE_HEADER ) + total_size );
|
||||
|
||||
LOG_INFO( "Report id: %d", report_header->report_id );
|
||||
|
||||
if ( report_header->report_id == REPORT_ILLEGAL_ATTACH_PROCESS )
|
||||
{
|
||||
attach_report = ( global::report_structures::ATTACH_PROCESS_REPORT* )(
|
||||
( UINT64 )buffer + sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER ) + total_size );
|
||||
( UINT64 )buffer + sizeof( global::report_structures::REPORT_QUEUE_HEADER ) + total_size );
|
||||
|
||||
this->report_interface->ReportViolation( attach_report );
|
||||
|
||||
|
@ -225,16 +226,26 @@ VOID kernelmode::Driver::QueryReportQueue()
|
|||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( report_header->report_id == REPORT_ILLEGAL_HANDLE_OPERATION )
|
||||
else if ( report_header->report_id == REPORT_ILLEGAL_HANDLE_OPERATION )
|
||||
{
|
||||
handle_report = ( global::report_structures::OPEN_HANDLE_FAILURE_REPORT* )(
|
||||
( UINT64 )buffer + sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER ) + total_size );
|
||||
( UINT64 )buffer + sizeof( global::report_structures::REPORT_QUEUE_HEADER ) + total_size );
|
||||
|
||||
this->report_interface->ReportViolation( handle_report );
|
||||
|
||||
total_size += sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT );
|
||||
|
||||
continue;
|
||||
}
|
||||
else if ( report_header->report_id == REPORT_INVALID_PROCESS_ALLOCATION )
|
||||
{
|
||||
allocation_report = ( global::report_structures::INVALID_PROCESS_ALLOCATION_REPORT* )(
|
||||
( UINT64 )buffer + sizeof( global::report_structures::REPORT_QUEUE_HEADER ) + total_size );
|
||||
|
||||
this->report_interface->ReportViolation( allocation_report );
|
||||
|
||||
total_size += sizeof( global::report_structures::INVALID_PROCESS_ALLOCATION_REPORT );
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue