mirror-ac/driver/callbacks.c

773 lines
19 KiB
C
Raw Normal View History

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;
2023-10-11 08:35:20 +02:00
KGUARDED_MUTEX lock;
2023-10-08 16:07:49 +02:00
}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-10 19:49:17 +02:00
typedef struct _PROCESS_LIST
{
SINGLE_LIST_ENTRY start;
volatile BOOLEAN active;
2023-10-11 08:35:20 +02:00
KGUARDED_MUTEX lock;
2023-10-10 19:49:17 +02:00
}PROCESS_LIST, *PPROCESS_LIST;
PPROCESS_LIST process_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)
2023-10-08 16:07:49 +02:00
#pragma alloc_text(PAGE, InitialiseThreadList)
2023-10-09 20:19:51 +02:00
#pragma alloc_text(PAGE, ExUnlockHandleTableEntry)
2023-10-07 17:37:47 +02:00
#endif
2023-10-12 13:27:40 +02:00
/*
* Its important on unload we dereference any objects to ensure the kernels reference
* count remains correct.
*/
VOID
CleanupProcessListFreeCallback(
_In_ PPROCESS_LIST_ENTRY ProcessListEntry
)
{
ObDereferenceObject(ProcessListEntry->parent);
ObDereferenceObject(ProcessListEntry->process);
}
VOID
CleanupThreadListFreeCallback(
_In_ PTHREAD_LIST_ENTRY ThreadListEntry
)
{
ObDereferenceObject(ThreadListEntry->thread);
ObDereferenceObject(ThreadListEntry->owning_process);
}
2023-10-10 19:49:17 +02:00
VOID
CleanupProcessListOnDriverUnload()
{
InterlockedExchange(&process_list->active, FALSE);
PsSetCreateProcessNotifyRoutine(ProcessCreateNotifyRoutine, TRUE);
for (;;)
{
2023-10-12 13:27:40 +02:00
if (!ListFreeFirstEntry(&process_list->start, &process_list->lock, CleanupProcessListFreeCallback))
2023-10-10 19:49:17 +02:00
{
ExFreePoolWithTag(process_list, POOL_TAG_THREAD_LIST);
return;
}
}
}
2023-10-08 16:07:49 +02:00
VOID
CleanupThreadListOnDriverUnload()
{
InterlockedExchange(&thread_list->active, FALSE);
PsRemoveCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine);
for (;;)
{
2023-10-12 13:27:40 +02:00
if (!ListFreeFirstEntry(&thread_list->start, &thread_list->lock, CleanupThreadListFreeCallback))
2023-10-08 16:07:49 +02:00
{
ExFreePoolWithTag(thread_list, POOL_TAG_THREAD_LIST);
return;
}
}
}
2023-10-11 08:35:20 +02:00
_IRQL_requires_max_(APC_LEVEL)
_Acquires_lock_(_Lock_kind_mutex_)
_Releases_lock_(_Lock_kind_mutex_)
2023-10-08 16:07:49 +02:00
VOID
EnumerateThreadListWithCallbackRoutine(
_In_ PVOID CallbackRoutine,
_In_opt_ PVOID Context
)
{
2023-10-11 08:35:20 +02:00
KeAcquireGuardedMutex(&thread_list->lock);
2023-10-08 16:07:49 +02:00
2023-10-09 20:19:51 +02:00
if (!CallbackRoutine)
goto unlock;
2023-10-08 16:07:49 +02:00
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;
}
2023-10-09 20:19:51 +02:00
unlock:
2023-10-11 08:35:20 +02:00
KeReleaseGuardedMutex(&thread_list->lock);
2023-10-08 16:07:49 +02:00
}
2023-10-11 08:35:20 +02:00
_IRQL_requires_max_(APC_LEVEL)
_Acquires_lock_(_Lock_kind_mutex_)
_Releases_lock_(_Lock_kind_mutex_)
2023-10-10 19:49:17 +02:00
VOID
EnumerateProcessListWithCallbackRoutine(
_In_ PVOID CallbackRoutine,
_In_opt_ PVOID Context
)
{
2023-10-11 08:35:20 +02:00
KeAcquireGuardedMutex(&process_list->lock);
2023-10-10 19:49:17 +02:00
if (!CallbackRoutine)
goto unlock;
PPROCESS_LIST_ENTRY entry = process_list->start.Next;
while (entry)
{
VOID(*callback_function_ptr)(PPROCESS_LIST_ENTRY, PVOID) = CallbackRoutine;
(*callback_function_ptr)(entry, Context);
entry = entry->list.Next;
}
unlock:
2023-10-11 08:35:20 +02:00
KeReleaseGuardedMutex(&process_list->lock);
2023-10-10 19:49:17 +02:00
}
NTSTATUS
InitialiseProcessList()
{
PAGED_CODE();
process_list =
ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(PROCESS_LIST), POOL_TAG_THREAD_LIST);
if (!process_list)
return STATUS_MEMORY_NOT_ALLOCATED;
InterlockedExchange(&process_list->active, TRUE);
ListInit(&process_list->start, &process_list->lock);
return STATUS_SUCCESS;
}
2023-10-08 16:07:49 +02:00
NTSTATUS
InitialiseThreadList()
{
2023-10-09 20:19:51 +02:00
PAGED_CODE();
2023-10-08 16:07:49 +02:00
thread_list =
ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(THREAD_LIST), POOL_TAG_THREAD_LIST);
if (!thread_list)
return STATUS_MEMORY_NOT_ALLOCATED;
2023-10-09 20:19:51 +02:00
InterlockedExchange(&thread_list->active, TRUE);
2023-10-08 16:07:49 +02:00
ListInit(&thread_list->start, &thread_list->lock);
return STATUS_SUCCESS;
}
2023-10-11 08:35:20 +02:00
_IRQL_requires_max_(APC_LEVEL)
_Acquires_lock_(_Lock_kind_mutex_)
_Releases_lock_(_Lock_kind_mutex_)
2023-10-10 19:49:17 +02:00
VOID
FindProcessListEntryByProcess(
_In_ PKPROCESS Process,
_Inout_ PPROCESS_LIST_ENTRY* Entry
)
{
*Entry = NULL;
2023-10-11 08:35:20 +02:00
KeAcquireGuardedMutex(&process_list->lock);
2023-10-10 19:49:17 +02:00
PPROCESS_LIST_ENTRY entry = (PPROCESS_LIST_ENTRY)process_list->start.Next;
while (entry)
{
if (entry->process == Process)
{
*Entry = entry;
goto unlock;
}
entry = entry->list.Next;
}
unlock:
2023-10-11 08:35:20 +02:00
KeReleaseGuardedMutex(&process_list->lock);
2023-10-10 19:49:17 +02:00
}
2023-10-11 08:35:20 +02:00
_IRQL_requires_max_(APC_LEVEL)
_Acquires_lock_(_Lock_kind_mutex_)
_Releases_lock_(_Lock_kind_mutex_)
2023-10-08 16:07:49 +02:00
VOID
FindThreadListEntryByThreadAddress(
_In_ PKTHREAD Thread,
_Inout_ PTHREAD_LIST_ENTRY* Entry
)
{
*Entry = NULL;
2023-10-11 08:35:20 +02:00
KeAcquireGuardedMutex(&thread_list->lock);
2023-10-08 16:07:49 +02:00
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:
2023-10-11 08:35:20 +02:00
KeReleaseGuardedMutex(&thread_list->lock);
2023-10-08 16:07:49 +02:00
}
2023-10-10 19:49:17 +02:00
VOID
ProcessCreateNotifyRoutine(
_In_ HANDLE ParentId,
2023-10-11 08:35:20 +02:00
_In_ HANDLE ProcessId,
2023-10-10 19:49:17 +02:00
_In_ BOOLEAN Create
)
{
PPROCESS_LIST_ENTRY entry = NULL;
PKPROCESS parent = NULL;
PKPROCESS process = NULL;
if (InterlockedExchange(&process_list->active, process_list->active) == FALSE)
return;
PsLookupProcessByProcessId(ParentId, &parent);
2023-10-11 08:35:20 +02:00
PsLookupProcessByProcessId(ProcessId, &process);
2023-10-10 19:49:17 +02:00
if (!parent || !process)
return;
if (Create)
{
entry = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(PROCESS_LIST_ENTRY), POOL_TAG_THREAD_LIST);
if (!entry)
return;
2023-10-12 13:27:40 +02:00
ObReferenceObject(parent);
ObReferenceObject(process);
2023-10-10 19:49:17 +02:00
entry->parent = parent;
entry->process = process;
2023-10-11 08:35:20 +02:00
ListInsert(&process_list->start, entry, &process_list->lock);
2023-10-10 19:49:17 +02:00
}
else
{
FindProcessListEntryByProcess(process, &entry);
if (!entry)
return;
2023-10-12 13:27:40 +02:00
ObDereferenceObject(entry->parent);
ObDereferenceObject(entry->process);
2023-10-10 19:49:17 +02:00
ListRemoveEntry(&process_list->start, entry, &process_list->lock);
}
}
2023-10-08 16:07:49 +02:00
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-12 13:27:40 +02:00
ObReferenceObject(thread);
ObReferenceObject(process);
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-12 13:27:40 +02:00
ObDereferenceObject(entry->thread);
ObDereferenceObject(entry->owning_process);
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-09 20:19:51 +02:00
PAGED_CODE();
2023-10-10 19:49:17 +02:00
UNREFERENCED_PARAMETER(RegistrationContext);
UNREFERENCED_PARAMETER(OperationInformation);
2023-08-20 16:12:04 +02:00
}
2023-10-10 15:52:42 +02:00
_IRQL_requires_max_(APC_LEVEL)
_Acquires_lock_(_Lock_kind_mutex_)
_Releases_lock_(_Lock_kind_mutex_)
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-09 20:19:51 +02:00
PAGED_CODE();
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;
/*
* 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;
2023-10-10 19:49:17 +02:00
HANDLE process_creator_id = PsGetProcessId(process_creator);
LONG protected_process_id = 0;
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-31 15:17:40 +01:00
/*
* 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
*/
if (!strcmp(process_creator_name, "lsass.exe") ||
!strcmp(process_creator_name, "csrss.exe") ||
!strcmp(process_creator_name, "WerFault.exe"))
2023-08-20 16:12:04 +02:00
{
/* We will downgrade these handles later */
2023-11-01 17:38:37 +01:00
//DEBUG_LOG("Handles created by CSRSS, LSASS and WerFault 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-11-01 17:38:37 +01: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-11-01 17:38:37 +01: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
)
{
2023-10-09 20:19:51 +02:00
PAGED_CODE();
2023-08-22 10:51:52 +02:00
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;
2023-10-10 19:49:17 +02:00
report->is_kernel_handle = 0;
2023-10-05 08:27:17 +02:00
report->process_id = PsGetProcessId(process);
2023-10-10 19:49:17 +02:00
report->thread_id = 0;
2023-10-02 16:31:30 +02:00
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-10-10 19:49:17 +02:00
_In_ PPROCESS_LIST_ENTRY ProcessListEntry,
_In_opt_ PVOID Context
2023-08-22 10:51:52 +02:00
)
{
2023-10-12 13:27:40 +02:00
/* Handles are stored in paged memory */
2023-08-22 10:51:52 +02:00
PAGED_CODE();
2023-10-10 19:49:17 +02:00
UNREFERENCED_PARAMETER(Context);
if (!ProcessListEntry)
2023-08-22 10:51:52 +02:00
return STATUS_INVALID_PARAMETER;
2023-10-10 19:49:17 +02:00
if (ProcessListEntry->process == PsInitialSystemProcess)
2023-09-11 13:11:04 +02:00
return STATUS_SUCCESS;
2023-08-22 10:51:52 +02:00
2023-10-10 19:49:17 +02:00
PHANDLE_TABLE handle_table =
*(PHANDLE_TABLE*)((uintptr_t)ProcessListEntry->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-10 19:49:17 +02:00
//VOID
//EnumerateProcessListWithCallbackFunction(
// _In_ PVOID Function,
// _In_opt_ PVOID Context
//)
//{
// PAGED_CODE();
//
// UINT64 current_process = 0;
// PLIST_ENTRY process_list_head = NULL;
// PLIST_ENTRY process_list_entry = NULL;
// PEPROCESS base_process = PsInitialSystemProcess;
//
// if (!base_process)
// return;
//
// process_list_head = (UINT64)((UINT64)base_process + EPROCESS_PLIST_ENTRY_OFFSET);
// process_list_entry = process_list_head;
//
// do
// {
// current_process = (PEPROCESS)((UINT64)process_list_entry - EPROCESS_PLIST_ENTRY_OFFSET);
//
// if (!current_process)
// return;
//
// VOID(*callback_function_ptr)(PEPROCESS, PVOID) = Function;
// (*callback_function_ptr)(current_process, Context);
//
// process_list_entry = process_list_entry->Flink;
//
// } while (process_list_entry != process_list_head->Blink);
//}