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"
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
/*
|
|
|
|
* Interlocked intrinsics are only atomic with respect to other InterlockedXxx functions,
|
2023-10-09 09:34:30 +02:00
|
|
|
* 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
|
|
|
|
{
|
|
|
|
SINGLE_LIST_ENTRY start;
|
|
|
|
volatile BOOLEAN active;
|
|
|
|
KSPIN_LOCK lock;
|
|
|
|
|
|
|
|
}THREAD_LIST, * PTHREAD_LIST;
|
|
|
|
|
|
|
|
/* todo: maybe put this in the global config? hmm.. I kinda like how its encapsulated here tho hm.. */
|
|
|
|
PTHREAD_LIST thread_list = NULL;
|
|
|
|
|
2023-10-08 06:24:54 +02: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
|
|
|
|
#pragma alloc_text(PAGE, ObPostOpCallbackRoutine)
|
|
|
|
#pragma alloc_text(PAGE, ObPreOpCallbackRoutine)
|
|
|
|
#pragma alloc_text(PAGE, EnumHandleCallback)
|
|
|
|
#pragma alloc_text(PAGE, EnumerateProcessHandles)
|
|
|
|
#pragma alloc_text(PAGE, EnumerateProcessListWithCallbackFunction)
|
2023-10-08 16:07:49 +02:00
|
|
|
#pragma alloc_text(PAGE, InitialiseThreadList)
|
2023-10-07 17:37:47 +02:00
|
|
|
#endif
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
VOID
|
|
|
|
CleanupThreadListOnDriverUnload()
|
|
|
|
{
|
|
|
|
InterlockedExchange(&thread_list->active, FALSE);
|
|
|
|
PsRemoveCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine);
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (!ListFreeFirstEntry(&thread_list->start, &thread_list->lock))
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(thread_list, POOL_TAG_THREAD_LIST);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2023-10-09 09:34:30 +02:00
|
|
|
* Important to remember the callback function will run at irql = DISPATCH_LEVEL since
|
|
|
|
* we hold the spinlock during enumeration.
|
2023-10-08 16:07:49 +02:00
|
|
|
*/
|
|
|
|
VOID
|
|
|
|
EnumerateThreadListWithCallbackRoutine(
|
|
|
|
_In_ PVOID CallbackRoutine,
|
|
|
|
_In_opt_ PVOID Context
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (!CallbackRoutine)
|
|
|
|
return;
|
|
|
|
|
|
|
|
KIRQL irql = KeGetCurrentIrql();
|
|
|
|
KeAcquireSpinLock(&thread_list->lock, &irql);
|
|
|
|
|
|
|
|
PTHREAD_LIST_ENTRY entry = thread_list->start.Next;
|
|
|
|
|
|
|
|
while (entry)
|
|
|
|
{
|
2023-10-09 09:34:30 +02:00
|
|
|
VOID(*callback_function_ptr)(PTHREAD_LIST_ENTRY, PVOID) = CallbackRoutine;
|
|
|
|
(*callback_function_ptr)(entry, Context);
|
2023-10-08 16:07:49 +02:00
|
|
|
entry = entry->list.Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
KeReleaseSpinLock(&thread_list->lock, irql);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
InitialiseThreadList()
|
|
|
|
{
|
|
|
|
thread_list =
|
|
|
|
ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(THREAD_LIST), POOL_TAG_THREAD_LIST);
|
|
|
|
|
|
|
|
if (!thread_list)
|
|
|
|
return STATUS_MEMORY_NOT_ALLOCATED;
|
|
|
|
|
|
|
|
thread_list->active = TRUE;
|
|
|
|
ListInit(&thread_list->start, &thread_list->lock);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FindThreadListEntryByThreadAddress(
|
|
|
|
_In_ PKTHREAD Thread,
|
|
|
|
_Inout_ PTHREAD_LIST_ENTRY* Entry
|
|
|
|
)
|
|
|
|
{
|
|
|
|
KIRQL irql = KeGetCurrentIrql();
|
|
|
|
*Entry = NULL;
|
|
|
|
KeAcquireSpinLock(&thread_list->lock, &irql);
|
|
|
|
|
|
|
|
PTHREAD_LIST_ENTRY entry = (PTHREAD_LIST_ENTRY)thread_list->start.Next;
|
|
|
|
|
|
|
|
while (entry)
|
|
|
|
{
|
|
|
|
if (entry->thread == Thread)
|
|
|
|
{
|
|
|
|
*Entry = entry;
|
|
|
|
goto unlock;
|
|
|
|
}
|
2023-10-08 16:30:05 +02:00
|
|
|
|
|
|
|
entry = entry->list.Next;
|
2023-10-08 16:07:49 +02:00
|
|
|
}
|
|
|
|
unlock:
|
|
|
|
KeReleaseSpinLock(&thread_list->lock, irql);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
ThreadCreateNotifyRoutine(
|
|
|
|
_In_ HANDLE ProcessId,
|
|
|
|
_In_ HANDLE ThreadId,
|
|
|
|
_In_ BOOLEAN Create
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PTHREAD_LIST_ENTRY entry = NULL;
|
|
|
|
PKTHREAD thread = NULL;
|
2023-10-09 09:34:30 +02:00
|
|
|
PKPROCESS process = NULL;
|
2023-10-08 16:07:49 +02:00
|
|
|
|
|
|
|
/* ensure we don't insert new entries if we are unloading */
|
|
|
|
if (InterlockedExchange(&thread_list->active, thread_list->active) == FALSE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
PsLookupThreadByThreadId(ThreadId, &thread);
|
2023-10-09 09:34:30 +02:00
|
|
|
PsLookupProcessByProcessId(ProcessId, &process);
|
2023-10-08 16:07:49 +02:00
|
|
|
|
2023-10-09 09:34:30 +02:00
|
|
|
if (!thread || !process)
|
2023-10-08 16:07:49 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (Create)
|
|
|
|
{
|
|
|
|
entry = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(THREAD_LIST_ENTRY), POOL_TAG_THREAD_LIST);
|
|
|
|
|
|
|
|
if (!entry)
|
|
|
|
return;
|
|
|
|
|
2023-10-08 16:30:05 +02:00
|
|
|
entry->thread = thread;
|
2023-10-09 09:34:30 +02:00
|
|
|
entry->owning_process = process;
|
|
|
|
entry->apc = NULL;
|
|
|
|
entry->apc_queued = FALSE;
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
ListInsert(&thread_list->start, &entry->list, &thread_list->lock);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FindThreadListEntryByThreadAddress(thread, &entry);
|
2023-10-08 16:30:05 +02:00
|
|
|
|
|
|
|
if (!entry)
|
|
|
|
return;
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
ListRemoveEntry(&thread_list->start, entry, &thread_list->lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
2023-09-27 06:22:14 +02:00
|
|
|
ObPostOpCallbackRoutine(
|
2023-08-20 16:12:04 +02:00
|
|
|
_In_ PVOID RegistrationContext,
|
|
|
|
_In_ POB_POST_OPERATION_INFORMATION OperationInformation
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
OB_PREOP_CALLBACK_STATUS
|
2023-09-27 06:22:14 +02:00
|
|
|
ObPreOpCallbackRoutine(
|
2023-08-20 16:12:04 +02:00
|
|
|
_In_ PVOID RegistrationContext,
|
|
|
|
_In_ POB_PRE_OPERATION_INFORMATION OperationInformation
|
|
|
|
)
|
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
UNREFERENCED_PARAMETER(RegistrationContext);
|
2023-08-20 16:12:04 +02:00
|
|
|
|
|
|
|
/* access mask to completely strip permissions */
|
|
|
|
ACCESS_MASK deny_access = SYNCHRONIZE | PROCESS_TERMINATE;
|
|
|
|
|
|
|
|
/* Access mask to be used for crss / lsass */
|
|
|
|
ACCESS_MASK downgrade_access = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This callback routine is executed in the context of the thread that
|
|
|
|
* is requesting to open said handle
|
|
|
|
*/
|
|
|
|
PEPROCESS process_creator = PsGetCurrentProcess();
|
2023-08-30 18:29:44 +02:00
|
|
|
PEPROCESS protected_process;
|
2023-10-05 08:27:17 +02:00
|
|
|
PEPROCESS target_process = (PEPROCESS)OperationInformation->Object;
|
|
|
|
LONG target_process_id = PsGetProcessId(target_process);
|
|
|
|
LONG process_creator_id = PsGetProcessId(process_creator);
|
2023-08-24 15:12:49 +02:00
|
|
|
LONG protected_process_id = NULL;
|
2023-08-22 10:51:52 +02:00
|
|
|
LPCSTR process_creator_name;
|
|
|
|
LPCSTR target_process_name;
|
2023-08-30 18:29:44 +02:00
|
|
|
LPCSTR protected_process_name;
|
2023-10-09 18:27:04 +02:00
|
|
|
POB_CALLBACKS_CONFIG configuration = NULL;
|
2023-10-06 10:30:14 +02:00
|
|
|
|
2023-10-07 07:27:22 +02:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
2023-10-06 10:30:14 +02:00
|
|
|
GetCallbackConfigStructure(&configuration);
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-10-06 10:30:14 +02:00
|
|
|
if (!configuration)
|
|
|
|
return OB_PREOP_SUCCESS;
|
2023-08-29 19:36:58 +02:00
|
|
|
|
2023-10-07 07:27:22 +02:00
|
|
|
KeAcquireGuardedMutex(&configuration->lock);
|
2023-10-05 08:27:17 +02:00
|
|
|
GetProtectedProcessId(&protected_process_id);
|
|
|
|
GetProtectedProcessEProcess(&protected_process);
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!protected_process_id || !protected_process)
|
2023-09-26 12:00:45 +02:00
|
|
|
goto end;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
process_creator_name = PsGetProcessImageFileName(process_creator);
|
|
|
|
target_process_name = PsGetProcessImageFileName(target_process);
|
|
|
|
protected_process_name = PsGetProcessImageFileName(protected_process);
|
2023-08-20 18:39:39 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!protected_process_name || !target_process_name)
|
2023-09-26 12:00:45 +02:00
|
|
|
goto end;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!strcmp(protected_process_name, target_process_name))
|
2023-08-20 16:12:04 +02:00
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!strcmp(process_creator_name, "lsass.exe") || !strcmp(process_creator_name, "csrss.exe"))
|
2023-08-20 16:12:04 +02:00
|
|
|
{
|
|
|
|
/* We will downgrade these handles later */
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Handles created by CSRSS and LSASS are allowed for now...");
|
2023-08-20 16:12:04 +02:00
|
|
|
}
|
2023-10-05 08:27:17 +02:00
|
|
|
else if (target_process == process_creator)
|
2023-08-20 18:06:21 +02:00
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("handles made by NOTEPAD r okay :)");
|
2023-08-20 18:06:21 +02:00
|
|
|
/* handles created by the game (notepad) are okay */
|
|
|
|
}
|
2023-08-20 16:12:04 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = deny_access;
|
|
|
|
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = deny_access;
|
2023-08-20 17:04:53 +02:00
|
|
|
|
2023-09-10 19:32:12 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2023-09-10 19:42:46 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!strcmp(process_creator_name, "Discord.exe") ||
|
|
|
|
!strcmp(process_creator_name, "svchost.exe") ||
|
|
|
|
!strcmp(process_creator_name, "explorer.exe"))
|
2023-09-10 19:32:12 +02:00
|
|
|
goto end;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("handle stripped from: %s", process_creator_name);
|
2023-09-10 19:38:36 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
POPEN_HANDLE_FAILURE_REPORT report =
|
|
|
|
ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(OPEN_HANDLE_FAILURE_REPORT), REPORT_POOL_TAG);
|
2023-08-20 17:04:53 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!report)
|
2023-08-20 17:04:53 +02:00
|
|
|
goto end;
|
|
|
|
|
|
|
|
report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
|
2023-08-22 10:51:52 +02:00
|
|
|
report->access = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
|
2023-08-20 17:04:53 +02:00
|
|
|
report->is_kernel_handle = OperationInformation->KernelHandle;
|
|
|
|
report->process_id = process_creator_id;
|
|
|
|
report->thread_id = PsGetCurrentThreadId();
|
2023-10-05 08:27:17 +02:00
|
|
|
RtlCopyMemory(report->process_name, process_creator_name, HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
2023-08-20 17:04:53 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
InsertReportToQueue(report);
|
2023-08-20 16:12:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-20 17:04:53 +02:00
|
|
|
end:
|
|
|
|
|
2023-10-07 07:27:22 +02:00
|
|
|
KeReleaseGuardedMutex(&configuration->lock);
|
2023-08-20 16:12:04 +02:00
|
|
|
return OB_PREOP_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2023-08-24 15:12:49 +02:00
|
|
|
//VOID ProcessCreateNotifyRoutine(
|
|
|
|
// _In_ HANDLE ParentId,
|
|
|
|
// _In_ HANDLE ProcessId,
|
|
|
|
// _In_ BOOLEAN Create
|
|
|
|
//)
|
|
|
|
//{
|
|
|
|
// NTSTATUS status;
|
|
|
|
// PEPROCESS parent_process;
|
|
|
|
// PEPROCESS target_process;
|
|
|
|
// LONG parent_process_id;
|
|
|
|
// LONG target_process_id;
|
|
|
|
// LPCSTR target_process_name = NULL;
|
|
|
|
// LPCSTR parent_process_name = NULL;
|
|
|
|
//
|
|
|
|
// status = PsLookupProcessByProcessId( ParentId, &parent_process );
|
|
|
|
//
|
|
|
|
// if ( !NT_SUCCESS( status ) )
|
|
|
|
// return;
|
|
|
|
//
|
|
|
|
// status = PsLookupProcessByProcessId( ProcessId, &target_process );
|
|
|
|
//
|
|
|
|
// if ( !NT_SUCCESS( status ) )
|
|
|
|
// return;
|
|
|
|
//
|
|
|
|
// parent_process_name = PsGetProcessImageFileName( parent_process );
|
|
|
|
//
|
|
|
|
// if ( !parent_process_name )
|
|
|
|
// return;
|
|
|
|
//
|
|
|
|
// target_process_name = PsGetProcessImageFileName( target_process );
|
|
|
|
//
|
|
|
|
// if ( !target_process_name )
|
|
|
|
// return;
|
|
|
|
//
|
|
|
|
// if ( !strcmp( target_process_name, "notepad.exe") )
|
|
|
|
// {
|
|
|
|
// parent_process_id = PsGetProcessId( parent_process );
|
|
|
|
// UpdateProtectedProcessParentId( parent_process_id );
|
|
|
|
//
|
|
|
|
// target_process_id = PsGetProcessId( target_process );
|
|
|
|
// UpdateProtectedProcessId( target_process_id );
|
|
|
|
//
|
|
|
|
// DEBUG_LOG( "Protected process parent proc id: %lx", parent_process_id );
|
|
|
|
// }
|
|
|
|
//}
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
/* stolen from ReactOS xD */
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2023-09-27 06:22:14 +02:00
|
|
|
ExUnlockHandleTableEntry(
|
2023-08-22 10:51:52 +02:00
|
|
|
IN PHANDLE_TABLE HandleTable,
|
|
|
|
IN PHANDLE_TABLE_ENTRY HandleTableEntry
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LONG_PTR old_value;
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Set the lock bit and make sure it wasn't earlier */
|
2023-10-05 08:27:17 +02:00
|
|
|
old_value = InterlockedOr((PLONG)&HandleTableEntry->VolatileLowValue, 1);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
/* Unblock any waiters */
|
2023-10-05 08:27:17 +02:00
|
|
|
ExfUnblockPushLock(&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-09-27 06:22:14 +02:00
|
|
|
EnumHandleCallback(
|
2023-08-22 10:51:52 +02:00
|
|
|
_In_ PHANDLE_TABLE HandleTable,
|
|
|
|
_In_ PHANDLE_TABLE_ENTRY Entry,
|
|
|
|
_In_ HANDLE Handle,
|
|
|
|
_In_ PVOID Context
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PVOID object;
|
|
|
|
PVOID object_header;
|
|
|
|
POBJECT_TYPE object_type;
|
|
|
|
PEPROCESS process;
|
2023-08-24 15:12:49 +02:00
|
|
|
PEPROCESS protected_process = NULL;
|
2023-08-22 10:51:52 +02:00
|
|
|
LPCSTR process_name;
|
|
|
|
LPCSTR protected_process_name;
|
|
|
|
ACCESS_MASK handle_access_mask;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
object_header = GET_OBJECT_HEADER_FROM_HANDLE(Entry->ObjectPointerBits);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
/* Object header is the first 30 bytes of the object */
|
2023-10-05 08:27:17 +02:00
|
|
|
object = (uintptr_t)object_header + OBJECT_HEADER_SIZE;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
object_type = ObGetObjectType(object);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
/* TODO: check for threads aswell */
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!RtlCompareUnicodeString(&object_type->Name, &OBJECT_TYPE_PROCESS, TRUE))
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
process = (PEPROCESS)object;
|
|
|
|
process_name = PsGetProcessImageFileName(process);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
GetProtectedProcessEProcess(&protected_process);
|
2023-08-22 19:32:25 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
protected_process_name = PsGetProcessImageFileName(protected_process);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (strcmp(process_name, protected_process_name))
|
2023-08-22 10:51:52 +02:00
|
|
|
goto end;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Handle references our protected process with access mask: %lx", (ACCESS_MASK)Entry->GrantedAccessBits);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
handle_access_mask = (ACCESS_MASK)Entry->GrantedAccessBits;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
/* These permissions can be stripped from every process including CSRSS and LSASS */
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_CREATE_PROCESS)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_CREATE_PROCESS;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_CREATE_PROCESS");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_CREATE_THREAD)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_CREATE_THREAD;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_CREATE_THREAD");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_DUP_HANDLE)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_DUP_HANDLE;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_DUP_HANDLE");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_QUERY_INFORMATION)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_QUERY_INFORMATION;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_QUERY_INFORMATION");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_QUERY_LIMITED_INFORMATION)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_QUERY_LIMITED_INFORMATION;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_QUERY_LIMITED_INFORMATION");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_VM_READ)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_VM_READ;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_VM_READ");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!strcmp(process_name, "csrss.exe") || !strcmp(process_name, "lsass.exe"))
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Required system process allowed, only stripping some permissions");
|
2023-08-22 10:51:52 +02:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Permissions beyond here can only be stripped from non critical processes */
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_SET_INFORMATION)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_SET_INFORMATION;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_SET_INFORMATION");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_SET_QUOTA)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_SET_QUOTA;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_SET_QUOTA");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_SUSPEND_RESUME)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_SUSPEND_RESUME;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_SUSPEND_RESUME ");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_TERMINATE)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_TERMINATE;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_TERMINATE");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_VM_OPERATION)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_VM_OPERATION;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_VM_OPERATION");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (handle_access_mask & PROCESS_VM_WRITE)
|
2023-08-22 10:51:52 +02:00
|
|
|
{
|
|
|
|
Entry->GrantedAccessBits &= ~PROCESS_VM_WRITE;
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Stripped PROCESS_VM_WRITE");
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
POPEN_HANDLE_FAILURE_REPORT report = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(OPEN_HANDLE_FAILURE_REPORT), REPORT_POOL_TAG);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!report)
|
2023-10-02 16:31:30 +02:00
|
|
|
goto end;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
2023-09-11 13:11:04 +02:00
|
|
|
* another queue specifically for open handle reports since they will be
|
2023-08-22 10:51:52 +02:00
|
|
|
* rare.
|
|
|
|
*/
|
2023-10-02 16:31:30 +02:00
|
|
|
report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
|
|
|
|
report->is_kernel_handle = NULL;
|
2023-10-05 08:27:17 +02:00
|
|
|
report->process_id = PsGetProcessId(process);
|
2023-10-02 16:31:30 +02:00
|
|
|
report->thread_id = NULL;
|
|
|
|
report->access = handle_access_mask;
|
2023-10-05 08:27:17 +02:00
|
|
|
RtlCopyMemory(&report->process_name, process_name, HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
2023-10-02 16:31:30 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
InsertReportToQueue(report);
|
2023-08-22 10:51:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
2023-10-05 08:27:17 +02:00
|
|
|
ExUnlockHandleTableEntry(HandleTable, Entry);
|
2023-08-22 10:51:52 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
NTSTATUS
|
2023-09-27 06:22:14 +02:00
|
|
|
EnumerateProcessHandles(
|
2023-08-22 10:51:52 +02:00
|
|
|
_In_ PEPROCESS Process
|
|
|
|
)
|
|
|
|
{
|
|
|
|
/* Handles are paged out so we need to be at an IRQL that allows paging */
|
|
|
|
PAGED_CODE();
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!Process)
|
2023-08-22 10:51:52 +02:00
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (Process == PsInitialSystemProcess)
|
2023-09-11 13:11:04 +02:00
|
|
|
return STATUS_SUCCESS;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
PHANDLE_TABLE handle_table = *(PHANDLE_TABLE*)((uintptr_t)Process + EPROCESS_HANDLE_TABLE_OFFSET);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!handle_table)
|
2023-09-11 13:11:04 +02:00
|
|
|
return STATUS_INVALID_ADDRESS;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!MmIsAddressValid(handle_table))
|
2023-09-11 13:11:04 +02:00
|
|
|
return STATUS_INVALID_ADDRESS;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
#pragma warning(push)
|
|
|
|
#pragma warning(suppress : 6387)
|
|
|
|
|
|
|
|
BOOLEAN result = ExEnumHandleTable(
|
|
|
|
handle_table,
|
|
|
|
EnumHandleCallback,
|
|
|
|
NULL,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
#pragma warning(pop)
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* I dont think this way of enumerating processes is valid for something like an anti
|
|
|
|
* cheat which is mass deployed and needs to ensure that it won't crash the system.
|
|
|
|
* Since we have no access to the process structure locks it is definitely not
|
|
|
|
* mass deployment safe lol.
|
2023-10-05 08:27:17 +02:00
|
|
|
*
|
2023-09-13 12:06:25 +02:00
|
|
|
* The Context argument is simply a pointer to a user designed context structure
|
|
|
|
* which is passed to the callback function.
|
2023-08-22 10:51:52 +02:00
|
|
|
*/
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
2023-09-27 06:22:14 +02:00
|
|
|
EnumerateProcessListWithCallbackFunction(
|
2023-09-13 12:06:25 +02:00
|
|
|
_In_ PVOID Function,
|
2023-09-13 12:25:32 +02:00
|
|
|
_In_opt_ PVOID Context
|
2023-08-22 10:51:52 +02:00
|
|
|
)
|
|
|
|
{
|
2023-08-30 11:19:41 +02:00
|
|
|
UINT64 current_process;
|
|
|
|
PLIST_ENTRY process_list_head = NULL;
|
|
|
|
PLIST_ENTRY process_list_entry = NULL;
|
2023-09-11 13:11:04 +02:00
|
|
|
PEPROCESS base_process = PsInitialSystemProcess;
|
2023-08-30 11:19:41 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!base_process)
|
2023-08-22 10:51:52 +02:00
|
|
|
return;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
process_list_head = (UINT64)((UINT64)base_process + EPROCESS_PLIST_ENTRY_OFFSET);
|
2023-08-30 11:19:41 +02:00
|
|
|
process_list_entry = process_list_head;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
current_process = (PEPROCESS)((UINT64)process_list_entry - EPROCESS_PLIST_ENTRY_OFFSET);
|
2023-08-30 11:19:41 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!current_process)
|
2023-09-11 13:11:04 +02:00
|
|
|
return;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID(*callback_function_ptr)(PEPROCESS, PVOID) = Function;
|
|
|
|
(*callback_function_ptr)(current_process, Context);
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-08-30 11:19:41 +02:00
|
|
|
process_list_entry = process_list_entry->Flink;
|
2023-08-22 10:51:52 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
} while (process_list_entry != process_list_head->Blink);
|
2023-08-20 16:12:04 +02:00
|
|
|
}
|