2023-08-20 16:12:04 +02:00
|
|
|
#include "callbacks.h"
|
|
|
|
|
|
|
|
#include "driver.h"
|
|
|
|
|
|
|
|
#include "queue.h"
|
2023-08-30 11:19:41 +02:00
|
|
|
#include "pool.h"
|
2023-09-02 10:54:04 +02:00
|
|
|
#include "thread.h"
|
2024-01-07 05:13:41 +01:00
|
|
|
#include "modules.h"
|
|
|
|
#include "imports.h"
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
/*
|
2023-12-13 05:06:27 +01:00
|
|
|
* Interlocked intrinsics are only atomic with respect to other InterlockedXxx functions,
|
|
|
|
* so all reads and writes to the THREAD_LIST->active flag must be with Interlocked instrinsics
|
|
|
|
* to ensure atomicity.
|
|
|
|
*/
|
2023-10-08 16:07:49 +02:00
|
|
|
typedef struct _THREAD_LIST
|
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
SINGLE_LIST_ENTRY start;
|
|
|
|
volatile BOOLEAN active;
|
|
|
|
KGUARDED_MUTEX lock;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
} THREAD_LIST, *PTHREAD_LIST;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
/* todo: maybe put this in the global config? hmm.. I kinda like how its encapsulated here tho hm..
|
|
|
|
*/
|
2023-10-08 16:07:49 +02:00
|
|
|
PTHREAD_LIST thread_list = NULL;
|
|
|
|
|
2023-10-10 19:49:17 +02:00
|
|
|
typedef struct _PROCESS_LIST
|
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
SINGLE_LIST_ENTRY start;
|
|
|
|
volatile BOOLEAN active;
|
|
|
|
KGUARDED_MUTEX lock;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
} PROCESS_LIST, *PPROCESS_LIST;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
|
|
|
PPROCESS_LIST process_list = NULL;
|
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
typedef struct _DRIVER_LIST
|
|
|
|
{
|
|
|
|
SINGLE_LIST_ENTRY start;
|
|
|
|
volatile ULONG count;
|
|
|
|
volatile BOOLEAN active;
|
|
|
|
KGUARDED_MUTEX lock;
|
|
|
|
|
|
|
|
} DRIVER_LIST, *PDRIVER_LIST;
|
|
|
|
|
|
|
|
PDRIVER_LIST driver_list = NULL;
|
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
STATIC
|
|
|
|
BOOLEAN
|
|
|
|
EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
|
|
|
|
_In_ PHANDLE_TABLE_ENTRY Entry,
|
|
|
|
_In_ HANDLE Handle,
|
|
|
|
_In_ PVOID Context);
|
2023-10-07 17:37:47 +02:00
|
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
2023-12-13 05:06:27 +01:00
|
|
|
# pragma alloc_text(PAGE, ObPostOpCallbackRoutine)
|
|
|
|
# pragma alloc_text(PAGE, ObPreOpCallbackRoutine)
|
|
|
|
# pragma alloc_text(PAGE, EnumHandleCallback)
|
|
|
|
# pragma alloc_text(PAGE, EnumerateProcessHandles)
|
|
|
|
# pragma alloc_text(PAGE, InitialiseThreadList)
|
|
|
|
# pragma alloc_text(PAGE, ExUnlockHandleTableEntry)
|
2023-10-07 17:37:47 +02:00
|
|
|
#endif
|
|
|
|
|
2023-10-12 13:27:40 +02:00
|
|
|
/*
|
2023-12-13 05:06:27 +01:00
|
|
|
* Its important on unload we dereference any objects to ensure the kernels reference
|
|
|
|
* count remains correct.
|
|
|
|
*/
|
2023-10-12 13:27:40 +02:00
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
CleanupProcessListFreeCallback(_In_ PPROCESS_LIST_ENTRY ProcessListEntry)
|
2023-10-12 13:27:40 +02:00
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpObDereferenceObject(ProcessListEntry->parent);
|
|
|
|
ImpObDereferenceObject(ProcessListEntry->process);
|
2023-10-12 13:27:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
CleanupThreadListFreeCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry)
|
2023-10-12 13:27:40 +02:00
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpObDereferenceObject(ThreadListEntry->thread);
|
|
|
|
ImpObDereferenceObject(ThreadListEntry->owning_process);
|
2023-10-12 13:27:40 +02:00
|
|
|
}
|
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
VOID
|
2023-10-10 19:49:17 +02:00
|
|
|
CleanupProcessListOnDriverUnload()
|
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
InterlockedExchange(&process_list->active, FALSE);
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpPsSetCreateProcessNotifyRoutine(ProcessCreateNotifyRoutine, TRUE);
|
2023-12-13 05:06:27 +01:00
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (!ListFreeFirstEntry(
|
|
|
|
&process_list->start, &process_list->lock, CleanupProcessListFreeCallback))
|
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpExFreePoolWithTag(process_list, POOL_TAG_THREAD_LIST);
|
2023-12-13 05:06:27 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-10-10 19:49:17 +02:00
|
|
|
}
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
VOID
|
|
|
|
CleanupThreadListOnDriverUnload()
|
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
InterlockedExchange(&thread_list->active, FALSE);
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpPsRemoveCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine);
|
2023-12-13 05:06:27 +01:00
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (!ListFreeFirstEntry(
|
|
|
|
&thread_list->start, &thread_list->lock, CleanupThreadListFreeCallback))
|
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpExFreePoolWithTag(thread_list, POOL_TAG_THREAD_LIST);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
CleanupDriverListOnDriverUnload()
|
|
|
|
{
|
|
|
|
InterlockedExchange(&driver_list->active, FALSE);
|
|
|
|
PsRemoveLoadImageNotifyRoutine(ImageLoadNotifyRoutineCallback);
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (!ListFreeFirstEntry(&driver_list->start, &driver_list->lock, NULL))
|
|
|
|
{
|
2024-01-07 05:42:40 +01:00
|
|
|
ImpExFreePoolWithTag(driver_list, POOL_TAG_DRIVER_LIST);
|
2023-12-13 05:06:27 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2023-10-08 16:07:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
EnumerateThreadListWithCallbackRoutine(_In_ PVOID CallbackRoutine, _In_opt_ PVOID Context)
|
2023-10-08 16:07:49 +02:00
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeAcquireGuardedMutex(&thread_list->lock);
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!CallbackRoutine)
|
|
|
|
goto unlock;
|
2023-10-09 20:19:51 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
PTHREAD_LIST_ENTRY entry = thread_list->start.Next;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
while (entry)
|
|
|
|
{
|
|
|
|
VOID (*callback_function_ptr)(PTHREAD_LIST_ENTRY, PVOID) = CallbackRoutine;
|
|
|
|
(*callback_function_ptr)(entry, Context);
|
|
|
|
entry = entry->list.Next;
|
|
|
|
}
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-10-09 20:19:51 +02:00
|
|
|
unlock:
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeReleaseGuardedMutex(&thread_list->lock);
|
2023-10-08 16:07:49 +02:00
|
|
|
}
|
|
|
|
|
2023-10-10 19:49:17 +02:00
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
EnumerateProcessListWithCallbackRoutine(_In_ PVOID CallbackRoutine, _In_opt_ PVOID Context)
|
2023-10-10 19:49:17 +02:00
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeAcquireGuardedMutex(&process_list->lock);
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!CallbackRoutine)
|
|
|
|
goto unlock;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
PPROCESS_LIST_ENTRY entry = process_list->start.Next;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
while (entry)
|
|
|
|
{
|
|
|
|
VOID (*callback_function_ptr)(PPROCESS_LIST_ENTRY, PVOID) = CallbackRoutine;
|
|
|
|
(*callback_function_ptr)(entry, Context);
|
|
|
|
entry = entry->list.Next;
|
|
|
|
}
|
2023-10-10 19:49:17 +02:00
|
|
|
|
|
|
|
unlock:
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeReleaseGuardedMutex(&process_list->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
InitialiseDriverList()
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
SYSTEM_MODULES modules = {0};
|
|
|
|
PDRIVER_LIST_ENTRY entry = NULL;
|
|
|
|
PRTL_MODULE_EXTENDED_INFO module_entry = NULL;
|
|
|
|
|
|
|
|
driver_list =
|
2024-01-07 05:42:40 +01:00
|
|
|
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(DRIVER_LIST), POOL_TAG_DRIVER_LIST);
|
2024-01-07 05:13:41 +01:00
|
|
|
|
|
|
|
if (!driver_list)
|
|
|
|
return STATUS_MEMORY_NOT_ALLOCATED;
|
|
|
|
|
|
|
|
InterlockedExchange(&driver_list->active, TRUE);
|
|
|
|
ListInit(&driver_list->start, &driver_list->lock);
|
|
|
|
|
|
|
|
status = GetSystemModuleInformation(&modules);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
DEBUG_ERROR("GetSystemModuleInformation failed with status %x", status);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2024-01-07 06:27:23 +01:00
|
|
|
/* skip hal.dll and ntoskrnl.exe */
|
2024-01-07 05:13:41 +01:00
|
|
|
for (INT index = 2; index < modules.module_count; index++)
|
|
|
|
{
|
|
|
|
entry = ImpExAllocatePool2(
|
2024-01-07 05:42:40 +01:00
|
|
|
POOL_FLAG_NON_PAGED, sizeof(DRIVER_LIST_ENTRY), POOL_TAG_DRIVER_LIST);
|
2024-01-07 05:13:41 +01:00
|
|
|
|
|
|
|
if (!entry)
|
2024-01-08 04:57:07 +01:00
|
|
|
continue;
|
2024-01-07 05:13:41 +01:00
|
|
|
|
|
|
|
module_entry = &((PRTL_MODULE_EXTENDED_INFO)modules.address)[index];
|
|
|
|
|
|
|
|
entry->hashed = TRUE;
|
|
|
|
entry->ImageBase = module_entry->ImageBase;
|
|
|
|
entry->ImageSize = module_entry->ImageSize;
|
2024-01-08 04:57:07 +01:00
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
RtlCopyMemory(
|
|
|
|
entry->path, module_entry->FullPathName, sizeof(module_entry->FullPathName));
|
|
|
|
|
|
|
|
status = HashModule(module_entry, entry->text_hash);
|
|
|
|
|
|
|
|
if (status == STATUS_INVALID_IMAGE_WIN_32)
|
|
|
|
{
|
|
|
|
DEBUG_ERROR("32 bit module not hashed, will hash later. %x", status);
|
|
|
|
entry->hashed = FALSE;
|
|
|
|
}
|
|
|
|
else if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
DEBUG_ERROR("HashModule failed with status %x", status);
|
|
|
|
entry->hashed = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListInsert(&driver_list->start, entry, &driver_list->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (modules.address)
|
|
|
|
ImpExFreePoolWithTag(modules.address, SYSTEM_MODULES_POOL);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
/*
|
|
|
|
* I actually think a spinlock here for the driver list is what we want rather then a mutex, but
|
|
|
|
* implementing a spinlock has its challenges... todo: have a think!
|
|
|
|
*/
|
2024-01-07 05:13:41 +01:00
|
|
|
VOID
|
|
|
|
FindDriverEntryByBaseAddress(_In_ PVOID ImageBase, _Out_ PDRIVER_LIST_ENTRY* Entry)
|
|
|
|
{
|
|
|
|
*Entry = NULL;
|
|
|
|
ImpKeAcquireGuardedMutex(&driver_list->lock);
|
|
|
|
|
|
|
|
PDRIVER_LIST_ENTRY entry = (PDRIVER_LIST_ENTRY)driver_list->start.Next;
|
|
|
|
|
|
|
|
while (entry)
|
|
|
|
{
|
|
|
|
if (entry->ImageBase == ImageBase)
|
|
|
|
{
|
|
|
|
*Entry = entry;
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry = entry->list.Next;
|
|
|
|
}
|
|
|
|
unlock:
|
|
|
|
ImpKeReleaseGuardedMutex(&driver_list->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName,
|
|
|
|
_In_ HANDLE ProcessId,
|
|
|
|
_In_ PIMAGE_INFO ImageInfo)
|
|
|
|
{
|
|
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
PDRIVER_LIST_ENTRY entry = NULL;
|
|
|
|
RTL_MODULE_EXTENDED_INFO module = {0};
|
|
|
|
|
|
|
|
if (InterlockedExchange(&driver_list->active, driver_list->active) == FALSE)
|
|
|
|
return;
|
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
if (ImageInfo->SystemModeImage == FALSE)
|
|
|
|
return;
|
2024-01-12 06:40:33 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
FindDriverEntryByBaseAddress(ImageInfo->ImageBase, &entry);
|
2024-01-07 05:13:41 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
if (entry)
|
|
|
|
return;
|
2024-01-07 05:13:41 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
DEBUG_VERBOSE("New system image: %wZ", FullImageName);
|
2024-01-07 05:13:41 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
entry =
|
|
|
|
ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(DRIVER_LIST_ENTRY), POOL_TAG_DRIVER_LIST);
|
2024-01-07 05:13:41 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
if (!entry)
|
|
|
|
return;
|
2024-01-07 05:13:41 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
entry->hashed = TRUE;
|
|
|
|
entry->ImageBase = ImageInfo->ImageBase;
|
|
|
|
entry->ImageSize = ImageInfo->ImageSize;
|
2024-01-07 05:13:41 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
/*todo: unicode 2 ansi string -> store in buf */
|
|
|
|
module.ImageBase = ImageInfo->ImageBase;
|
|
|
|
module.ImageSize = ImageInfo->ImageSize;
|
2024-01-07 05:13:41 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
status = HashModule(&module, &entry->text_hash);
|
2024-01-07 05:13:41 +01:00
|
|
|
|
2024-01-07 05:42:40 +01:00
|
|
|
if (status == STATUS_INVALID_IMAGE_WIN_32)
|
|
|
|
{
|
|
|
|
DEBUG_ERROR("32 bit module not hashed, will hash later. %x", status);
|
|
|
|
entry->hashed = FALSE;
|
2024-01-07 05:13:41 +01:00
|
|
|
}
|
2024-01-07 05:42:40 +01:00
|
|
|
else if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
DEBUG_ERROR("HashModule failed with status %x", status);
|
|
|
|
entry->hashed = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListInsert(&driver_list->start, entry, &driver_list->lock);
|
2023-10-10 19:49:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
InitialiseProcessList()
|
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
PAGED_CODE();
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
process_list =
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(PROCESS_LIST), POOL_TAG_THREAD_LIST);
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!process_list)
|
|
|
|
return STATUS_MEMORY_NOT_ALLOCATED;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
InterlockedExchange(&process_list->active, TRUE);
|
|
|
|
ListInit(&process_list->start, &process_list->lock);
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
return STATUS_SUCCESS;
|
2023-10-10 19:49:17 +02:00
|
|
|
}
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
NTSTATUS
|
|
|
|
InitialiseThreadList()
|
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
PAGED_CODE();
|
2023-10-09 20:19:51 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
thread_list =
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(THREAD_LIST), POOL_TAG_THREAD_LIST);
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!thread_list)
|
|
|
|
return STATUS_MEMORY_NOT_ALLOCATED;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
InterlockedExchange(&thread_list->active, TRUE);
|
|
|
|
ListInit(&thread_list->start, &thread_list->lock);
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
return STATUS_SUCCESS;
|
2023-10-08 16:07:49 +02:00
|
|
|
}
|
|
|
|
|
2023-10-10 19:49:17 +02:00
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
FindProcessListEntryByProcess(_In_ PKPROCESS Process, _Inout_ PPROCESS_LIST_ENTRY* Entry)
|
2023-10-10 19:49:17 +02:00
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
*Entry = NULL;
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeAcquireGuardedMutex(&process_list->lock);
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
PPROCESS_LIST_ENTRY entry = (PPROCESS_LIST_ENTRY)process_list->start.Next;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
while (entry)
|
|
|
|
{
|
|
|
|
if (entry->process == Process)
|
|
|
|
{
|
|
|
|
*Entry = entry;
|
|
|
|
goto unlock;
|
|
|
|
}
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
entry = entry->list.Next;
|
|
|
|
}
|
2023-10-10 19:49:17 +02:00
|
|
|
unlock:
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeReleaseGuardedMutex(&process_list->lock);
|
2023-10-10 19:49:17 +02:00
|
|
|
}
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
FindThreadListEntryByThreadAddress(_In_ PKTHREAD Thread, _Inout_ PTHREAD_LIST_ENTRY* Entry)
|
2023-10-08 16:07:49 +02:00
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
*Entry = NULL;
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeAcquireGuardedMutex(&thread_list->lock);
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
PTHREAD_LIST_ENTRY entry = (PTHREAD_LIST_ENTRY)thread_list->start.Next;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
while (entry)
|
|
|
|
{
|
|
|
|
if (entry->thread == Thread)
|
|
|
|
{
|
|
|
|
*Entry = entry;
|
|
|
|
goto unlock;
|
|
|
|
}
|
2023-10-08 16:30:05 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
entry = entry->list.Next;
|
|
|
|
}
|
2023-10-08 16:07:49 +02:00
|
|
|
unlock:
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeReleaseGuardedMutex(&thread_list->lock);
|
2023-10-08 16:07:49 +02:00
|
|
|
}
|
|
|
|
|
2023-10-10 19:49:17 +02:00
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
ProcessCreateNotifyRoutine(_In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOOLEAN Create)
|
2023-10-10 19:49:17 +02:00
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
PPROCESS_LIST_ENTRY entry = NULL;
|
|
|
|
PKPROCESS parent = NULL;
|
|
|
|
PKPROCESS process = NULL;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (InterlockedExchange(&process_list->active, process_list->active) == FALSE)
|
|
|
|
return;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpPsLookupProcessByProcessId(ParentId, &parent);
|
|
|
|
ImpPsLookupProcessByProcessId(ProcessId, &process);
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!parent || !process)
|
|
|
|
return;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (Create)
|
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
entry = ImpExAllocatePool2(
|
2023-12-13 05:06:27 +01:00
|
|
|
POOL_FLAG_NON_PAGED, sizeof(PROCESS_LIST_ENTRY), POOL_TAG_THREAD_LIST);
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!entry)
|
|
|
|
return;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpObfReferenceObject(parent);
|
|
|
|
ImpObfReferenceObject(process);
|
2023-10-12 13:27:40 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
entry->parent = parent;
|
|
|
|
entry->process = process;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
ListInsert(&process_list->start, entry, &process_list->lock);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FindProcessListEntryByProcess(process, &entry);
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!entry)
|
|
|
|
return;
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpObDereferenceObject(entry->parent);
|
|
|
|
ImpObDereferenceObject(entry->process);
|
2023-10-12 13:27:40 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
ListRemoveEntry(&process_list->start, entry, &process_list->lock);
|
|
|
|
}
|
2023-10-10 19:49:17 +02:00
|
|
|
}
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
ThreadCreateNotifyRoutine(_In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ BOOLEAN Create)
|
2023-10-08 16:07:49 +02:00
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
PTHREAD_LIST_ENTRY entry = NULL;
|
|
|
|
PKTHREAD thread = NULL;
|
|
|
|
PKPROCESS process = NULL;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
/* ensure we don't insert new entries if we are unloading */
|
|
|
|
if (InterlockedExchange(&thread_list->active, thread_list->active) == FALSE)
|
|
|
|
return;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpPsLookupThreadByThreadId(ThreadId, &thread);
|
|
|
|
ImpPsLookupProcessByProcessId(ProcessId, &process);
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!thread || !process)
|
|
|
|
return;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (Create)
|
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
entry = ImpExAllocatePool2(
|
2023-12-13 05:06:27 +01:00
|
|
|
POOL_FLAG_NON_PAGED, sizeof(THREAD_LIST_ENTRY), POOL_TAG_THREAD_LIST);
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!entry)
|
|
|
|
return;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpObfReferenceObject(thread);
|
|
|
|
ImpObfReferenceObject(process);
|
2023-10-12 13:27:40 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
entry->thread = thread;
|
|
|
|
entry->owning_process = process;
|
|
|
|
entry->apc = NULL;
|
|
|
|
entry->apc_queued = FALSE;
|
2023-10-09 09:34:30 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
ListInsert(&thread_list->start, &entry->list, &thread_list->lock);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FindThreadListEntryByThreadAddress(thread, &entry);
|
2023-10-08 16:30:05 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!entry)
|
|
|
|
return;
|
2023-10-08 16:30:05 +02:00
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpObDereferenceObject(entry->thread);
|
|
|
|
ImpObDereferenceObject(entry->owning_process);
|
2023-10-12 13:27:40 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
ListRemoveEntry(&thread_list->start, entry, &thread_list->lock);
|
|
|
|
}
|
2023-10-08 16:07:49 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
2023-12-13 05:06:27 +01:00
|
|
|
ObPostOpCallbackRoutine(_In_ PVOID RegistrationContext,
|
|
|
|
_In_ POB_POST_OPERATION_INFORMATION OperationInformation)
|
2023-08-20 16:12:04 +02:00
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
PAGED_CODE();
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
UNREFERENCED_PARAMETER(RegistrationContext);
|
|
|
|
UNREFERENCED_PARAMETER(OperationInformation);
|
2023-08-20 16:12:04 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
OB_PREOP_CALLBACK_STATUS
|
2023-12-13 05:06:27 +01:00
|
|
|
ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
|
|
|
|
_In_ POB_PRE_OPERATION_INFORMATION OperationInformation)
|
2023-08-20 16:12:04 +02:00
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNREFERENCED_PARAMETER(RegistrationContext);
|
|
|
|
|
|
|
|
/* access mask to completely strip permissions */
|
|
|
|
ACCESS_MASK deny_access = SYNCHRONIZE | PROCESS_TERMINATE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This callback routine is executed in the context of the thread that
|
|
|
|
* is requesting to open said handle
|
|
|
|
*/
|
|
|
|
PEPROCESS process_creator = PsGetCurrentProcess();
|
|
|
|
PEPROCESS protected_process = NULL;
|
|
|
|
PEPROCESS target_process = (PEPROCESS)OperationInformation->Object;
|
2024-01-07 05:13:41 +01:00
|
|
|
HANDLE process_creator_id = ImpPsGetProcessId(process_creator);
|
2023-12-13 05:06:27 +01:00
|
|
|
LONG protected_process_id = 0;
|
|
|
|
LPCSTR process_creator_name = NULL;
|
|
|
|
LPCSTR target_process_name = NULL;
|
|
|
|
LPCSTR protected_process_name = NULL;
|
|
|
|
POB_CALLBACKS_CONFIG configuration = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is to prevent the condition where the thread executing this function is scheduled
|
|
|
|
* whilst we are cleaning up the callbacks on driver unload. We must hold the driver config
|
|
|
|
* lock to ensure the pool containing the callback configuration lock is not freed
|
|
|
|
*/
|
|
|
|
GetCallbackConfigStructure(&configuration);
|
|
|
|
|
|
|
|
if (!configuration)
|
|
|
|
return OB_PREOP_SUCCESS;
|
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeAcquireGuardedMutex(&configuration->lock);
|
2023-12-13 05:06:27 +01:00
|
|
|
GetProtectedProcessId(&protected_process_id);
|
|
|
|
GetProtectedProcessEProcess(&protected_process);
|
|
|
|
|
|
|
|
if (!protected_process_id || !protected_process)
|
|
|
|
goto end;
|
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
process_creator_name = ImpPsGetProcessImageFileName(process_creator);
|
|
|
|
target_process_name = ImpPsGetProcessImageFileName(target_process);
|
|
|
|
protected_process_name = ImpPsGetProcessImageFileName(protected_process);
|
2023-12-13 05:06:27 +01:00
|
|
|
|
|
|
|
if (!protected_process_name || !target_process_name)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
if (!strcmp(protected_process_name, target_process_name))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* 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
|
2024-01-12 06:40:33 +01:00
|
|
|
*
|
|
|
|
* todo: perform stricter checks rather then the image name. perhapds check some
|
|
|
|
* certificate or something.
|
2023-12-13 05:06:27 +01:00
|
|
|
*/
|
|
|
|
if (!strcmp(process_creator_name, "lsass.exe") ||
|
|
|
|
!strcmp(process_creator_name, "csrss.exe") ||
|
|
|
|
!strcmp(process_creator_name, "WerFault.exe"))
|
|
|
|
{
|
|
|
|
/* We will downgrade these handles later */
|
|
|
|
// DEBUG_LOG("Handles created by CSRSS, LSASS and WerFault are allowed for
|
|
|
|
// now...");
|
|
|
|
}
|
|
|
|
else if (target_process == process_creator)
|
|
|
|
{
|
|
|
|
// DEBUG_LOG("handles made by NOTEPAD r okay :)");
|
|
|
|
/* handles created by the game (notepad) are okay */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess =
|
|
|
|
deny_access;
|
|
|
|
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess =
|
|
|
|
deny_access;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* These processes will constantly open handles to any open process for
|
|
|
|
* various reasons, so we will still strip them but we won't report them..
|
|
|
|
* for now atleast.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!strcmp(process_creator_name, "Discord.exe") ||
|
|
|
|
!strcmp(process_creator_name, "svchost.exe") ||
|
|
|
|
!strcmp(process_creator_name, "explorer.exe"))
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
// DEBUG_LOG("handle stripped from: %s", process_creator_name);
|
|
|
|
|
|
|
|
POPEN_HANDLE_FAILURE_REPORT report =
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
|
|
|
sizeof(OPEN_HANDLE_FAILURE_REPORT),
|
|
|
|
REPORT_POOL_TAG);
|
2023-12-13 05:06:27 +01:00
|
|
|
|
|
|
|
if (!report)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
|
|
|
|
report->is_kernel_handle = OperationInformation->KernelHandle;
|
|
|
|
report->process_id = process_creator_id;
|
2024-01-07 05:13:41 +01:00
|
|
|
report->thread_id = ImpPsGetCurrentThreadId();
|
2023-12-13 05:06:27 +01:00
|
|
|
report->access =
|
|
|
|
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
|
|
|
|
|
|
|
|
RtlCopyMemory(report->process_name,
|
|
|
|
process_creator_name,
|
|
|
|
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
|
|
|
|
|
|
|
InsertReportToQueue(report);
|
|
|
|
}
|
|
|
|
}
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-08-20 17:04:53 +02:00
|
|
|
end:
|
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpKeReleaseGuardedMutex(&configuration->lock);
|
2023-12-13 05:06:27 +01:00
|
|
|
return OB_PREOP_SUCCESS;
|
2023-08-20 16:12:04 +02:00
|
|
|
}
|
|
|
|
|
2023-08-22 10:51:52 +02:00
|
|
|
/* stolen from ReactOS xD */
|
2023-12-13 05:06:27 +01:00
|
|
|
VOID NTAPI
|
|
|
|
ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
INT64 old_value;
|
|
|
|
PAGED_CODE();
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
/* Set the lock bit and make sure it wasn't earlier */
|
|
|
|
old_value = InterlockedOr((PLONG)&HandleTableEntry->VolatileLowValue, 1);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
/* Unblock any waiters */
|
2024-01-07 05:13:41 +01:00
|
|
|
ImpExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-09-27 06:22:14 +02:00
|
|
|
STATIC
|
2023-10-05 08:27:17 +02:00
|
|
|
BOOLEAN
|
2023-12-13 05:06:27 +01:00
|
|
|
EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
|
|
|
|
_In_ PHANDLE_TABLE_ENTRY Entry,
|
|
|
|
_In_ HANDLE Handle,
|
|
|
|
_In_ PVOID Context)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
2023-12-13 05:06:27 +01:00
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
PVOID object = NULL;
|
|
|
|
PVOID object_header = NULL;
|
|
|
|
POBJECT_TYPE object_type = NULL;
|
|
|
|
PEPROCESS process = NULL;
|
|
|
|
PEPROCESS protected_process = NULL;
|
|
|
|
LPCSTR process_name = NULL;
|
|
|
|
LPCSTR protected_process_name = NULL;
|
|
|
|
ACCESS_MASK handle_access_mask = 0;
|
|
|
|
|
|
|
|
object_header = GET_OBJECT_HEADER_FROM_HANDLE(Entry->ObjectPointerBits);
|
|
|
|
|
|
|
|
/* Object header is the first 30 bytes of the object */
|
|
|
|
object = (uintptr_t)object_header + OBJECT_HEADER_SIZE;
|
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
object_type = ImpObGetObjectType(object);
|
2023-12-13 05:06:27 +01:00
|
|
|
|
|
|
|
/* TODO: check for threads aswell */
|
2024-01-07 05:13:41 +01:00
|
|
|
if (!ImpRtlCompareUnicodeString(&object_type->Name, &OBJECT_TYPE_PROCESS, TRUE))
|
2023-12-13 05:06:27 +01:00
|
|
|
{
|
|
|
|
process = (PEPROCESS)object;
|
2024-01-07 05:13:41 +01:00
|
|
|
process_name = ImpPsGetProcessImageFileName(process);
|
2023-12-13 05:06:27 +01:00
|
|
|
|
|
|
|
GetProtectedProcessEProcess(&protected_process);
|
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
protected_process_name = ImpPsGetProcessImageFileName(protected_process);
|
2023-12-13 05:06:27 +01:00
|
|
|
|
|
|
|
if (strcmp(process_name, protected_process_name))
|
|
|
|
goto end;
|
|
|
|
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Handle references our protected process with access mask: %lx",
|
2024-01-02 23:29:23 +01:00
|
|
|
(ACCESS_MASK)Entry->GrantedAccessBits);
|
2023-12-13 05:06:27 +01:00
|
|
|
|
|
|
|
handle_access_mask = (ACCESS_MASK)Entry->GrantedAccessBits;
|
|
|
|
|
|
|
|
/* These permissions can be stripped from every process including CSRSS and LSASS */
|
|
|
|
if (handle_access_mask & PROCESS_CREATE_PROCESS)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_CREATE_PROCESS;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_CREATE_PROCESS");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_CREATE_THREAD)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_CREATE_THREAD;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_CREATE_THREAD");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_DUP_HANDLE)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_DUP_HANDLE;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_DUP_HANDLE");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_QUERY_INFORMATION)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_QUERY_INFORMATION;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_QUERY_INFORMATION");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_QUERY_LIMITED_INFORMATION)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_QUERY_LIMITED_INFORMATION;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_QUERY_LIMITED_INFORMATION");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_VM_READ)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_VM_READ;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_VM_READ");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(process_name, "csrss.exe") || !strcmp(process_name, "lsass.exe"))
|
|
|
|
{
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE(
|
2023-12-13 05:06:27 +01:00
|
|
|
"Required system process allowed, only stripping some permissions");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Permissions beyond here can only be stripped from non critical processes */
|
|
|
|
if (handle_access_mask & PROCESS_SET_INFORMATION)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_SET_INFORMATION;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_SET_INFORMATION");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_SET_QUOTA)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_SET_QUOTA;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_SET_QUOTA");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_SUSPEND_RESUME)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_SUSPEND_RESUME;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_SUSPEND_RESUME ");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_TERMINATE)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_TERMINATE;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_TERMINATE");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_VM_OPERATION)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_VM_OPERATION;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_VM_OPERATION");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_access_mask & PROCESS_VM_WRITE)
|
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_VM_WRITE;
|
2023-12-23 19:52:55 +01:00
|
|
|
DEBUG_VERBOSE("Stripped PROCESS_VM_WRITE");
|
2023-12-13 05:06:27 +01:00
|
|
|
}
|
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
POPEN_HANDLE_FAILURE_REPORT report = ImpExAllocatePool2(
|
2023-12-13 05:06:27 +01:00
|
|
|
POOL_FLAG_NON_PAGED, sizeof(OPEN_HANDLE_FAILURE_REPORT), REPORT_POOL_TAG);
|
|
|
|
|
|
|
|
if (!report)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Using the same report structure as the ObRegisterCallbacks report
|
|
|
|
* since both of these reports are closely related by the fact they are
|
|
|
|
* triggered by a process either opening a handle to our protected process
|
|
|
|
* or have a valid open handle to it. I also don't think its worth creating
|
|
|
|
* another queue specifically for open handle reports since they will be
|
|
|
|
* rare.
|
|
|
|
*/
|
|
|
|
report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
|
|
|
|
report->is_kernel_handle = 0;
|
2024-01-07 05:13:41 +01:00
|
|
|
report->process_id = ImpPsGetProcessId(process);
|
2023-12-13 05:06:27 +01:00
|
|
|
report->thread_id = 0;
|
|
|
|
report->access = handle_access_mask;
|
2023-12-23 19:52:55 +01:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
RtlCopyMemory(
|
|
|
|
&report->process_name, process_name, HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
|
|
|
|
|
|
|
InsertReportToQueue(report);
|
|
|
|
}
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
end:
|
2023-12-13 05:06:27 +01:00
|
|
|
ExUnlockHandleTableEntry(HandleTable, Entry);
|
|
|
|
return FALSE;
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
NTSTATUS
|
2023-12-13 05:06:27 +01:00
|
|
|
EnumerateProcessHandles(_In_ PPROCESS_LIST_ENTRY ProcessListEntry, _In_opt_ PVOID Context)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
2024-01-07 05:13:41 +01:00
|
|
|
/* Handles are stored in pageable memory */
|
2023-12-13 05:06:27 +01:00
|
|
|
PAGED_CODE();
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
UNREFERENCED_PARAMETER(Context);
|
2023-10-10 19:49:17 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!ProcessListEntry)
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (ProcessListEntry->process == PsInitialSystemProcess)
|
|
|
|
return STATUS_SUCCESS;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
PHANDLE_TABLE handle_table =
|
|
|
|
*(PHANDLE_TABLE*)((uintptr_t)ProcessListEntry->process + EPROCESS_HANDLE_TABLE_OFFSET);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
if (!handle_table)
|
|
|
|
return STATUS_INVALID_ADDRESS;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
if (!ImpMmIsAddressValid(handle_table))
|
2023-12-13 05:06:27 +01:00
|
|
|
return STATUS_INVALID_ADDRESS;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
#pragma warning(push)
|
|
|
|
#pragma warning(suppress : 6387)
|
|
|
|
|
2024-01-07 05:13:41 +01:00
|
|
|
BOOLEAN result = ImpExEnumHandleTable(handle_table, EnumHandleCallback, NULL, NULL);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
#pragma warning(pop)
|
|
|
|
|
2023-12-13 05:06:27 +01:00
|
|
|
return STATUS_SUCCESS;
|
2024-01-12 06:40:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#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.");
|
2024-01-02 23:29:23 +01:00
|
|
|
}
|