mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
implement timer objects + some stuf
This commit is contained in:
parent
2a4a5e344d
commit
19619119df
8 changed files with 228 additions and 93 deletions
|
@ -280,7 +280,7 @@ ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName,
|
|||
|
||||
if (ImageInfo->SystemModeImage == FALSE)
|
||||
return;
|
||||
|
||||
|
||||
FindDriverEntryByBaseAddress(ImageInfo->ImageBase, &entry);
|
||||
|
||||
if (entry)
|
||||
|
@ -555,6 +555,9 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
|
|||
/*
|
||||
* WerFault is some windows 11 application that cries when it cant get a handle,
|
||||
* so well allow it for now... todo; learn more about it
|
||||
*
|
||||
* todo: perform stricter checks rather then the image name. perhapds check some
|
||||
* certificate or something.
|
||||
*/
|
||||
if (!strcmp(process_creator_name, "lsass.exe") ||
|
||||
!strcmp(process_creator_name, "csrss.exe") ||
|
||||
|
@ -818,4 +821,105 @@ EnumerateProcessHandles(_In_ PPROCESS_LIST_ENTRY ProcessListEntry, _In_opt_ PVOI
|
|||
#pragma warning(pop)
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define REPEAT_TIME_10_SEC 10000
|
||||
|
||||
VOID
|
||||
TimerObjectWorkItemRoutine(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PTIMER_OBJECT timer = (PTIMER_OBJECT)Context;
|
||||
|
||||
DEBUG_VERBOSE("Integrity check timer callback invoked.");
|
||||
|
||||
if (!ValidateOurDriversDispatchRoutines())
|
||||
{
|
||||
DEBUG_VERBOSE("l");
|
||||
}
|
||||
|
||||
status = ValidateOurDriverImage();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("ValidateOurDriverImage failed with status %x", status);
|
||||
|
||||
InterlockedDecrement(&timer->state);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is executed every x seconds, and is run at IRQL = DISPATCH_LEVEL
|
||||
*/
|
||||
VOID
|
||||
TimerObjectCallbackRoutine(_In_ PKDPC Dpc,
|
||||
_In_opt_ PVOID DeferredContext,
|
||||
_In_opt_ PVOID SystemArgument1,
|
||||
_In_opt_ PVOID SystemArgument2)
|
||||
{
|
||||
PTIMER_OBJECT timer = (PTIMER_OBJECT)DeferredContext;
|
||||
|
||||
/* we dont want to queue our work item if it hasnt executed */
|
||||
if (timer->state)
|
||||
return;
|
||||
|
||||
/* we queue a work item because DPCs run at IRQL = DISPATCH_LEVEL and we need certain
|
||||
* routines which cannot be run at an IRQL this high.*/
|
||||
InterlockedIncrement(&timer->state);
|
||||
IoQueueWorkItem(timer->work_item, TimerObjectWorkItemRoutine, BackgroundWorkQueue, timer);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
InitialiseTimerObject(_Out_ PTIMER_OBJECT Timer)
|
||||
{
|
||||
LARGE_INTEGER due_time = {0};
|
||||
LONG period = 0;
|
||||
|
||||
due_time.QuadPart = ABSOLUTE(SECONDS(5));
|
||||
|
||||
Timer->timer = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KTIMER), POOL_TAG_TIMER);
|
||||
|
||||
if (!Timer->timer)
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
|
||||
Timer->dpc = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KDPC), POOL_TAG_DPC);
|
||||
|
||||
if (!Timer->dpc)
|
||||
{
|
||||
ExFreePoolWithTag(Timer->timer, POOL_TAG_TIMER);
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
|
||||
Timer->work_item = IoAllocateWorkItem(GetDriverDeviceObject());
|
||||
|
||||
if (!Timer->work_item)
|
||||
{
|
||||
ExFreePoolWithTag(Timer->dpc, POOL_TAG_DPC);
|
||||
ExFreePoolWithTag(Timer->timer, POOL_TAG_TIMER);
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
|
||||
KeInitializeDpc(Timer->dpc, TimerObjectCallbackRoutine, Timer);
|
||||
KeInitializeTimer(Timer->timer);
|
||||
KeSetTimerEx(Timer->timer, due_time, REPEAT_TIME_10_SEC, Timer->dpc);
|
||||
|
||||
DEBUG_VERBOSE("Successfully initialised global timer callback.");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
CleanupDriverTimerObjects(_Out_ PTIMER_OBJECT Timer)
|
||||
{
|
||||
/* this routine blocks until all queued DPCs on all processors have executed. */
|
||||
KeFlushQueuedDpcs();
|
||||
|
||||
/* wait for our work item to complete */
|
||||
while (Timer->state)
|
||||
YieldProcessor();
|
||||
|
||||
/* now its safe to free and cancel our timers, pools etc. */
|
||||
KeCancelTimer(Timer->timer);
|
||||
IoFreeWorkItem(Timer->work_item);
|
||||
ExFreePoolWithTag(Timer->timer, POOL_TAG_TIMER);
|
||||
ExFreePoolWithTag(Timer->dpc, POOL_TAG_DPC);
|
||||
|
||||
DEBUG_VERBOSE("Freed timer objects.");
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
#include <wdftypes.h>
|
||||
#include <wdf.h>
|
||||
#include "common.h"
|
||||
#include "driver.h"
|
||||
|
||||
#define HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH 64
|
||||
|
||||
|
@ -134,4 +135,10 @@ ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName,
|
|||
_In_ HANDLE ProcessId,
|
||||
_In_ PIMAGE_INFO ImageInfo);
|
||||
|
||||
NTSTATUS
|
||||
InitialiseTimerObject(_Out_ PTIMER_OBJECT Timer);
|
||||
|
||||
VOID
|
||||
CleanupDriverTimerObjects(_Out_ PTIMER_OBJECT Timer);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#define POOL_TAG_THREAD_LIST 'list'
|
||||
#define POOL_TAG_DRIVER_LIST 'drvl'
|
||||
#define POOL_TAG_IRP_QUEUE 'irpp'
|
||||
#define POOL_TAG_TIMER 'time'
|
||||
|
||||
#define IA32_APERF_MSR 0x000000E8
|
||||
|
||||
|
@ -1492,4 +1493,16 @@ PETHREAD
|
|||
NTAPI
|
||||
PsGetNextProcessThread(IN PEPROCESS Process, IN PETHREAD Thread OPTIONAL);
|
||||
|
||||
#define ABSOLUTE(wait) (wait)
|
||||
|
||||
#define RELATIVE(wait) (-(wait))
|
||||
|
||||
#define NANOSECONDS(nanos) (((signed __int64)(nanos)) / 100L)
|
||||
|
||||
#define MICROSECONDS(micros) (((signed __int64)(micros)) * NANOSECONDS(1000L))
|
||||
|
||||
#define MILLISECONDS(milli) (((signed __int64)(milli)) * MICROSECONDS(1000L))
|
||||
|
||||
#define SECONDS(seconds) (((signed __int64)(seconds)) * MILLISECONDS(1000L))
|
||||
|
||||
#endif
|
||||
|
|
|
@ -120,6 +120,7 @@ typedef struct _DRIVER_CONFIG
|
|||
KGUARDED_MUTEX lock;
|
||||
SYS_MODULE_VAL_CONTEXT sys_val_context;
|
||||
IRP_QUEUE_HEAD irp_queue;
|
||||
TIMER_OBJECT timer;
|
||||
|
||||
} DRIVER_CONFIG, *PDRIVER_CONFIG;
|
||||
|
||||
|
@ -774,6 +775,14 @@ DrvUnloadFreeDriverList()
|
|||
CleanupDriverListOnDriverUnload();
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
DrvUnloadFreeTimerObject()
|
||||
{
|
||||
PAGED_CODE();
|
||||
CleanupDriverTimerObjects(&driver_config.timer);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
DrvUnloadFreeProcessList()
|
||||
|
@ -814,6 +823,7 @@ DriverUnload(_In_ PDRIVER_OBJECT DriverObject)
|
|||
while (DrvUnloadFreeAllApcContextStructures() == FALSE)
|
||||
YieldProcessor();
|
||||
|
||||
DrvUnloadFreeTimerObject();
|
||||
DrvUnloadFreeModuleValidationContext();
|
||||
DrvUnloadUnregisterObCallbacks();
|
||||
DrvUnloadFreeThreadList();
|
||||
|
@ -1197,6 +1207,15 @@ DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_ST
|
|||
return status;
|
||||
}
|
||||
|
||||
status = InitialiseTimerObject(&driver_config.timer);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("InitialiseTimerObject failed with status %x", status);
|
||||
DrvUnloadFreeConfigStrings();
|
||||
return status;
|
||||
}
|
||||
|
||||
DEBUG_VERBOSE("driver name: %s", driver_config.ansi_driver_name.Buffer);
|
||||
|
||||
return status;
|
||||
|
@ -1208,6 +1227,11 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
|||
BOOLEAN flag = FALSE;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreate;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
|
||||
/* store the driver object here as we need to access it in ResolveNtImports */
|
||||
driver_config.driver_object = DriverObject;
|
||||
|
||||
|
@ -1218,16 +1242,6 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
|||
|
||||
DEBUG_VERBOSE("Beginning driver entry routine...");
|
||||
|
||||
status = DrvLoadInitialiseDriverConfig(DriverObject, RegistryPath);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("InitialiseDriverConfigOnDriverEntry failed with status %x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
DrvLoadInitialiseProcessConfig();
|
||||
|
||||
status = ImpIoCreateDevice(DriverObject,
|
||||
NULL,
|
||||
&driver_config.device_name,
|
||||
|
@ -1239,13 +1253,23 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
|||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("IoCreateDevice failed with status %x", status);
|
||||
DrvUnloadFreeConfigStrings();
|
||||
return STATUS_FAILED_DRIVER_ENTRY;
|
||||
return status;
|
||||
}
|
||||
|
||||
driver_config.driver_object = DriverObject;
|
||||
driver_config.device_object = DriverObject->DeviceObject;
|
||||
|
||||
status = DrvLoadInitialiseDriverConfig(DriverObject, RegistryPath);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("InitialiseDriverConfigOnDriverEntry failed with status %x", status);
|
||||
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
||||
return status;
|
||||
}
|
||||
|
||||
DrvLoadInitialiseProcessConfig();
|
||||
|
||||
status = ImpIoCreateSymbolicLink(&driver_config.device_symbolic_link,
|
||||
&driver_config.device_name);
|
||||
|
||||
|
@ -1257,11 +1281,6 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
|||
return STATUS_FAILED_DRIVER_ENTRY;
|
||||
}
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreate;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
|
||||
DrvLoadInitialiseReportQueue(&flag);
|
||||
|
||||
if (!flag)
|
||||
|
|
|
@ -22,6 +22,20 @@
|
|||
|
||||
#define MAXIMUM_APC_CONTEXTS 10
|
||||
|
||||
typedef struct _TIMER_OBJECT
|
||||
{
|
||||
/*
|
||||
* state = 1: callback in progress
|
||||
* state = 0: no callback in progress (i.e safe to free and unregister)
|
||||
*/
|
||||
volatile LONG state;
|
||||
|
||||
PKTIMER timer;
|
||||
PKDPC dpc;
|
||||
PIO_WORKITEM work_item;
|
||||
|
||||
} TIMER_OBJECT, *PTIMER_OBJECT;
|
||||
|
||||
typedef enum _ENVIRONMENT_TYPE
|
||||
{
|
||||
NativeWindows = 0,
|
||||
|
|
|
@ -398,15 +398,15 @@ MapDiskImageIntoVirtualAddressSpace(_Inout_ PHANDLE Sec
|
|||
* will be identical to the in memory image.
|
||||
*/
|
||||
status = ImpZwMapViewOfSection(*SectionHandle,
|
||||
ZwCurrentProcess(),
|
||||
Section,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
Size,
|
||||
ViewUnmap,
|
||||
MEM_TOP_DOWN,
|
||||
PAGE_READONLY);
|
||||
ZwCurrentProcess(),
|
||||
Section,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
Size,
|
||||
ViewUnmap,
|
||||
MEM_TOP_DOWN,
|
||||
PAGE_READONLY);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
|
@ -1558,7 +1558,8 @@ ValidateSystemModule(_In_ PRTL_MODULE_EXTENDED_INFO Module)
|
|||
if (CompareHashes(hash, entry->text_hash, SHA_256_HASH_LENGTH))
|
||||
DEBUG_VERBOSE("Module: %s text regions are valid.", Module->FullPathName);
|
||||
else
|
||||
DEBUG_WARNING("**!!** Module: %s text regions are NOT valid **!!**", Module->FullPathName);
|
||||
DEBUG_WARNING("**!!** Module: %s text regions are NOT valid **!!**",
|
||||
Module->FullPathName);
|
||||
|
||||
end:
|
||||
if (hash)
|
||||
|
@ -1568,23 +1569,14 @@ end:
|
|||
NTSTATUS
|
||||
ValidateOurDriverImage()
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
LPCSTR driver_name = NULL;
|
||||
UNICODE_STRING path = {0};
|
||||
SYSTEM_MODULES modules = {0};
|
||||
PRTL_MODULE_EXTENDED_INFO module_info = NULL;
|
||||
PVOID section = NULL;
|
||||
HANDLE section_handle = NULL;
|
||||
ULONG section_size = 0;
|
||||
PVAL_INTEGRITY_HEADER disk_buffer = NULL;
|
||||
ULONG disk_buffer_size = 0;
|
||||
PVOID disk_hash = NULL;
|
||||
ULONG disk_hash_size = 0;
|
||||
ULONG memory_text_size = 0;
|
||||
PVOID memory_hash = NULL;
|
||||
ULONG memory_hash_size = 0;
|
||||
PVAL_INTEGRITY_HEADER memory_buffer = NULL;
|
||||
ULONG memory_buffer_size = 0;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
LPCSTR driver_name = NULL;
|
||||
UNICODE_STRING path = {0};
|
||||
SYSTEM_MODULES modules = {0};
|
||||
PRTL_MODULE_EXTENDED_INFO module_info = NULL;
|
||||
PVOID memory_hash = NULL;
|
||||
ULONG memory_hash_size = 0;
|
||||
PDRIVER_LIST_ENTRY entry = NULL;
|
||||
|
||||
GetDriverPath(&path);
|
||||
GetDriverName(&driver_name);
|
||||
|
@ -1611,46 +1603,24 @@ ValidateOurDriverImage()
|
|||
goto end;
|
||||
}
|
||||
|
||||
/* here we need to map our disk image, like the previous integ checks */
|
||||
status =
|
||||
MapDiskImageIntoVirtualAddressSpace(§ion_handle, §ion, &path, §ion_size);
|
||||
memory_hash = ExAllocatePool2(POOL_FLAG_NON_PAGED, SHA_256_HASH_LENGTH, POOL_TAG_INTEGRITY);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
if (!memory_hash)
|
||||
goto end;
|
||||
|
||||
FindDriverEntryByBaseAddress(module_info->ImageBase, &entry);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
DEBUG_ERROR("MapDiskImageIntoVirtualAddressSpace failed with status %x", status);
|
||||
DEBUG_ERROR("FindDriverEntryByBaseAddress failed with no status.");
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = StoreModuleExecutableRegionsInBuffer(
|
||||
(PVOID)&disk_buffer, section, section_size, &disk_buffer_size);
|
||||
status = HashModule(module_info, memory_hash);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("StoreModuleExecutableRegionsInBuffer failed with status %x", status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = StoreModuleExecutableRegionsInBuffer((PVOID)&memory_buffer,
|
||||
module_info->ImageBase,
|
||||
module_info->ImageSize,
|
||||
&memory_buffer_size);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("StoreModuleExecutableRegionsInBuffer 2 failed with status %x", status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = ComputeHashOfSections(&memory_buffer->section_header,
|
||||
&disk_buffer->section_header,
|
||||
&disk_hash,
|
||||
&disk_hash_size,
|
||||
&memory_hash,
|
||||
&memory_hash_size);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_VERBOSE("ComputeHashOfSections failed with status %x", status);
|
||||
DEBUG_ERROR("HashModule failed with status %x", status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -1658,30 +1628,16 @@ ValidateOurDriverImage()
|
|||
* Since we don't pass a return value, I think we would raise an invalid module error and
|
||||
* stop the users game session ? since module .text section error would be a large red flag
|
||||
*/
|
||||
if (CompareHashes(disk_hash, memory_hash, SHA_256_HASH_LENGTH))
|
||||
if (CompareHashes(memory_hash, entry->text_hash, SHA_256_HASH_LENGTH))
|
||||
DEBUG_VERBOSE("Driver image is valid. Integrity check complete");
|
||||
else
|
||||
DEBUG_WARNING("Drive image is NOT valid. !!!");
|
||||
DEBUG_WARNING("**!!** Driver image is NOT valid. **!!**");
|
||||
|
||||
end:
|
||||
if (memory_buffer)
|
||||
ExFreePoolWithTag(memory_buffer, POOL_TAG_INTEGRITY);
|
||||
|
||||
if (disk_buffer)
|
||||
ExFreePoolWithTag(disk_buffer, POOL_TAG_INTEGRITY);
|
||||
|
||||
if (memory_hash)
|
||||
ExFreePoolWithTag(memory_hash, POOL_TAG_INTEGRITY);
|
||||
|
||||
if (disk_hash)
|
||||
ExFreePoolWithTag(disk_hash, POOL_TAG_INTEGRITY);
|
||||
|
||||
if (section_handle)
|
||||
ZwClose(section_handle);
|
||||
|
||||
if (section)
|
||||
ZwUnmapViewOfSection(ZwCurrentProcess(), section);
|
||||
|
||||
if (modules.address)
|
||||
ExFreePoolWithTag(modules.address, SYSTEM_MODULES_POOL);
|
||||
|
||||
|
@ -1929,3 +1885,18 @@ CalculateCpuCoreUsage(_In_ UINT32 Core)
|
|||
return (100 - (UINT32)(UInt32x32To64(idle_time, 100) / (UINT64)(kernel_time + user_time)));
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ValidateOurDriversDispatchRoutines()
|
||||
{
|
||||
PDRIVER_OBJECT driver = GetDriverObject();
|
||||
|
||||
if (driver->MajorFunction[IRP_MJ_CREATE] != DeviceCreate ||
|
||||
driver->MajorFunction[IRP_MJ_CLOSE] != DeviceClose ||
|
||||
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] != DeviceControl)
|
||||
{
|
||||
DEBUG_WARNING("**!!** Drivers dispatch routine has been tampered with. **!!**");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -130,4 +130,7 @@ HashModule(_In_ PRTL_MODULE_EXTENDED_INFO Module, _Out_ PVOID Hash);
|
|||
VOID
|
||||
ValidateSystemModule(_In_ PRTL_MODULE_EXTENDED_INFO Module);
|
||||
|
||||
BOOLEAN
|
||||
ValidateOurDriversDispatchRoutines();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -647,6 +647,10 @@ CheckIfProcessAllocationIsInProcessList(_In_ PPROCESS_LIST_ENTRY ProcessListEntr
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is actually broken right now since changing to use our process list, will need to fix at
|
||||
* somepoint.
|
||||
*/
|
||||
NTSTATUS
|
||||
FindUnlinkedProcesses()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue