mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
implement thread list
This commit is contained in:
parent
7dab235001
commit
f8b04d8b5e
8 changed files with 325 additions and 80 deletions
|
@ -6,6 +6,29 @@
|
|||
#include "pool.h"
|
||||
#include "thread.h"
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
typedef struct _THREAD_LIST
|
||||
{
|
||||
SINGLE_LIST_ENTRY start;
|
||||
volatile BOOLEAN active;
|
||||
KSPIN_LOCK lock;
|
||||
|
||||
}THREAD_LIST, * PTHREAD_LIST;
|
||||
|
||||
typedef struct _THREAD_LIST_ENTRY
|
||||
{
|
||||
SINGLE_LIST_ENTRY list;
|
||||
PKTHREAD thread;
|
||||
|
||||
}THREAD_LIST_ENTRY, *PTHREAD_LIST_ENTRY;
|
||||
|
||||
/* todo: maybe put this in the global config? hmm.. I kinda like how its encapsulated here tho hm.. */
|
||||
PTHREAD_LIST thread_list = NULL;
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
EnumHandleCallback(
|
||||
|
@ -20,8 +43,129 @@ EnumHandleCallback(
|
|||
#pragma alloc_text(PAGE, EnumHandleCallback)
|
||||
#pragma alloc_text(PAGE, EnumerateProcessHandles)
|
||||
#pragma alloc_text(PAGE, EnumerateProcessListWithCallbackFunction)
|
||||
#pragma alloc_text(PAGE, InitialiseThreadList)
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Safely enumerate the threads list.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
VOID(*callback_function_ptr)(PKTHREAD, PVOID) = CallbackRoutine;
|
||||
(*callback_function_ptr)(entry->thread, Context);
|
||||
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;
|
||||
}
|
||||
|
||||
STATIC
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
/* ensure we don't insert new entries if we are unloading */
|
||||
if (InterlockedExchange(&thread_list->active, thread_list->active) == FALSE)
|
||||
return;
|
||||
|
||||
PsLookupThreadByThreadId(ThreadId, &thread);
|
||||
|
||||
if (!thread)
|
||||
return;
|
||||
|
||||
if (Create)
|
||||
{
|
||||
entry = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(THREAD_LIST_ENTRY), POOL_TAG_THREAD_LIST);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
ListInsert(&thread_list->start, &entry->list, &thread_list->lock);
|
||||
DEBUG_LOG("Thread inserted: %llx", (UINT64)thread);
|
||||
}
|
||||
else
|
||||
{
|
||||
FindThreadListEntryByThreadAddress(thread, &entry);
|
||||
ListRemoveEntry(&thread_list->start, entry, &thread_list->lock);
|
||||
DEBUG_LOG("Thread removed: %llx", (UINT64)thread);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
ObPostOpCallbackRoutine(
|
||||
_In_ PVOID RegistrationContext,
|
||||
|
|
|
@ -80,4 +80,17 @@ EnumerateProcessHandles(
|
|||
_In_ PEPROCESS Process
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
InitialiseThreadList();
|
||||
|
||||
VOID
|
||||
ThreadCreateNotifyRoutine(
|
||||
_In_ HANDLE ProcessId,
|
||||
_In_ HANDLE ThreadId,
|
||||
_In_ BOOLEAN Create
|
||||
);
|
||||
|
||||
VOID
|
||||
CleanupThreadListOnDriverUnload();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#define REPORT_POOL_TAG 'repo'
|
||||
#define MODULES_REPORT_POOL_TAG 'modu'
|
||||
#define POOL_TAG_LIST_ITEM 'tsil'
|
||||
#define POOL_TAG_THREAD_LIST 'list'
|
||||
|
||||
#define IA32_APERF_MSR 0x000000E8
|
||||
|
||||
|
@ -49,8 +50,11 @@
|
|||
#define KTHREAD_START_ADDRESS_OFFSET 0x450
|
||||
#define KTHREAD_MISC_FLAGS_OFFSET 0x074
|
||||
#define KTHREAD_WAIT_IRQL_OFFSET 0x186
|
||||
#define KTHREAD_PREVIOUS_MODE_OFFSET 0x232
|
||||
#define KTHREAD_STATE_OFFSET 0x184
|
||||
|
||||
#define KTHREAD_MISC_FLAGS_APC_QUEUEABLE 14
|
||||
#define KTHREAD_MISC_FLAGS_ALERTABLE 4
|
||||
|
||||
#define EPROCESS_PEAK_VIRTUAL_SIZE_OFFSET 0x490
|
||||
#define EPROCESS_VAD_ROOT_OFFSET 0x7d8
|
||||
|
|
|
@ -141,6 +141,7 @@ EnableCallbackRoutinesOnProcessRun()
|
|||
|
||||
OB_CALLBACK_REGISTRATION callback_registration = { 0 };
|
||||
OB_OPERATION_REGISTRATION operation_registration = { 0 };
|
||||
PCREATE_PROCESS_NOTIFY_ROUTINE_EX notify_routine = { 0 };
|
||||
|
||||
operation_registration.ObjectType = PsProcessType;
|
||||
operation_registration.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
|
||||
|
@ -176,6 +177,28 @@ end:
|
|||
return status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
EnableCallbackRoutinesOnDriverEntry()
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = InitialiseThreadList();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("InitialiseThreadList failed with status %x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = PsSetCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("PsSetCreateProcessNotifyRoutine failed with status %x", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
AllocateCallbackStructure()
|
||||
|
@ -843,6 +866,7 @@ DriverUnload(
|
|||
|
||||
/* This is safe to call even if the callbacks have already been disabled */
|
||||
CleanupDriverCallbacksOnDriverUnload();
|
||||
CleanupThreadListOnDriverUnload();
|
||||
|
||||
CleanupDriverConfigOnUnload();
|
||||
IoDeleteDevice(DriverObject->DeviceObject);
|
||||
|
@ -947,6 +971,18 @@ DriverEntry(
|
|||
return STATUS_FAILED_DRIVER_ENTRY;
|
||||
}
|
||||
|
||||
status = EnableCallbackRoutinesOnDriverEntry();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("failed to init callback routines on driver entry");
|
||||
FreeGlobalReportQueueObjects();
|
||||
FreeDriverConfigurationStringBuffers();
|
||||
IoDeleteSymbolicLink(&driver_config.device_symbolic_link);
|
||||
IoDeleteDevice(DriverObject->DeviceObject);
|
||||
return STATUS_FAILED_DRIVER_ENTRY;
|
||||
}
|
||||
|
||||
DEBUG_LOG("DonnaAC Driver Entry Complete");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#define NMI_DELAY 200 * 10000
|
||||
|
||||
#define WHITELISTED_MODULE_COUNT 7
|
||||
#define WHITELISTED_MODULE_COUNT 11
|
||||
#define MODULE_MAX_STRING_SIZE 256
|
||||
|
||||
#define NTOSKRNL 0
|
||||
|
@ -26,10 +26,14 @@ CHAR WHITELISTED_MODULES[WHITELISTED_MODULE_COUNT][MODULE_MAX_STRING_SIZE] =
|
|||
"ntoskrnl.exe",
|
||||
"CLASSPNP.SYS",
|
||||
"Wdf01000.sys",
|
||||
"HIDCLASS.sys",
|
||||
"HIDCLASS.SYS",
|
||||
"storport.sys",
|
||||
"dxgkrnl.sys",
|
||||
"ndis.sys"
|
||||
"ndis.sys",
|
||||
"ks.sys",
|
||||
"portcls.sys",
|
||||
"rdbss.sys",
|
||||
"LXCORE.SYS"
|
||||
};
|
||||
|
||||
#define MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE 128
|
||||
|
@ -1124,7 +1128,7 @@ ApcKernelRoutine(
|
|||
|
||||
context = (PAPC_STACKWALK_CONTEXT)Apc->NormalContext;
|
||||
|
||||
buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, 0x200, POOL_TAG_APC);
|
||||
buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, STACK_FRAME_POOL_SIZE, POOL_TAG_APC);
|
||||
|
||||
if (!buffer)
|
||||
goto free;
|
||||
|
@ -1161,7 +1165,8 @@ ApcKernelRoutine(
|
|||
|
||||
if (flag == FALSE)
|
||||
{
|
||||
PAPC_STACKWALK_REPORT report = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(APC_STACKWALK_REPORT), POOL_TAG_APC);
|
||||
PAPC_STACKWALK_REPORT report =
|
||||
ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(APC_STACKWALK_REPORT), POOL_TAG_APC);
|
||||
|
||||
if (!report)
|
||||
goto free;
|
||||
|
@ -1202,7 +1207,7 @@ ApcNormalRoutine(
|
|||
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
VOID
|
||||
FlipKThreadMiscFlagsFlag(
|
||||
_In_ PKTHREAD Thread,
|
||||
_In_ LONG FlagIndex,
|
||||
|
@ -1212,17 +1217,16 @@ FlipKThreadMiscFlagsFlag(
|
|||
PLONG misc_flags = (PLONG)((UINT64)Thread + KTHREAD_MISC_FLAGS_OFFSET);
|
||||
LONG mask = 1U << FlagIndex;
|
||||
|
||||
if (!MmIsAddressValid(misc_flags))
|
||||
return FALSE;
|
||||
|
||||
if (NewValue)
|
||||
*misc_flags |= mask;
|
||||
else
|
||||
*misc_flags &= ~mask;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define THREAD_STATE_TERMINATED 4
|
||||
#define THREAD_STATE_WAIT 5
|
||||
#define THREAD_STATE_INIT 0
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ValidateThreadViaKernelApcCallback(
|
||||
|
@ -1237,21 +1241,29 @@ ValidateThreadViaKernelApcCallback(
|
|||
PKAPC apc = NULL;
|
||||
BOOLEAN apc_status;
|
||||
PLONG misc_flags = NULL;
|
||||
PCHAR previous_mode = NULL;
|
||||
PUCHAR state = NULL;
|
||||
BOOLEAN apc_queueable = FALSE;
|
||||
PAPC_STACKWALK_CONTEXT context = (PAPC_STACKWALK_CONTEXT)Context;
|
||||
LPCSTR process_name = PsGetProcessImageFileName(Process);
|
||||
|
||||
/* we dont want to schedule an apc to threads owned by the kernel */
|
||||
if (Process == PsInitialSystemProcess)
|
||||
if (Process == PsInitialSystemProcess || !Context)
|
||||
return;
|
||||
|
||||
/* We are not interested in these processess.. for now lol */
|
||||
if (!strcmp(process_name, "svchost.exe") ||
|
||||
!strcmp(process_name, "Registry") ||
|
||||
!strcmp(process_name, "smss.exe") ||
|
||||
!strcmp(process_name, "csrss.exe"))
|
||||
!strcmp(process_name, "csrss.exe") ||
|
||||
!strcmp(process_name, "explorer.exe") ||
|
||||
!strcmp(process_name, "svchost.exe") ||
|
||||
!strcmp(process_name, "lsass.exe") ||
|
||||
!strcmp(process_name, "MemCompression"))
|
||||
return;
|
||||
|
||||
DEBUG_LOG("Process: %s", process_name);
|
||||
|
||||
thread_list_head = (PLIST_ENTRY)((UINT64)Process + KPROCESS_THREADLIST_OFFSET);
|
||||
thread_list_entry = thread_list_head->Flink;
|
||||
|
||||
|
@ -1263,7 +1275,6 @@ ValidateThreadViaKernelApcCallback(
|
|||
|
||||
if (current_thread == KeGetCurrentThread() || !current_thread)
|
||||
goto increment;
|
||||
|
||||
/*
|
||||
* Its possible to set the KThread->ApcQueueable flag to false ensuring that no APCs can be
|
||||
* queued to the thread, as KeInsertQueueApc will check this flag before queueing an APC so
|
||||
|
@ -1271,23 +1282,55 @@ ValidateThreadViaKernelApcCallback(
|
|||
* threads this should be fine... c:
|
||||
*/
|
||||
misc_flags = (PLONG)((UINT64)current_thread + KTHREAD_MISC_FLAGS_OFFSET);
|
||||
previous_mode = (PCHAR)((UINT64)current_thread + KTHREAD_PREVIOUS_MODE_OFFSET);
|
||||
state = (PUCHAR)((UINT64)current_thread + KTHREAD_STATE_OFFSET);
|
||||
|
||||
/* sanity check */
|
||||
if (!MmIsAddressValid(misc_flags))
|
||||
if (!MmIsAddressValid(current_thread))
|
||||
goto increment;
|
||||
|
||||
/* we dont care about user mode threads */
|
||||
//if (*previous_mode == UserMode)
|
||||
// goto increment;
|
||||
|
||||
/* todo: We should also flag all threads that have the flag set to false */
|
||||
if (*misc_flags >> KTHREAD_MISC_FLAGS_APC_QUEUEABLE == FALSE)
|
||||
{
|
||||
if (!FlipKThreadMiscFlagsFlag(current_thread, KTHREAD_MISC_FLAGS_APC_QUEUEABLE, TRUE))
|
||||
goto increment;
|
||||
}
|
||||
FlipKThreadMiscFlagsFlag(current_thread, KTHREAD_MISC_FLAGS_APC_QUEUEABLE, TRUE);
|
||||
|
||||
/* force thread into an alertable state */
|
||||
if (*misc_flags >> KTHREAD_MISC_FLAGS_ALERTABLE == FALSE)
|
||||
FlipKThreadMiscFlagsFlag(current_thread, KTHREAD_MISC_FLAGS_ALERTABLE, TRUE);
|
||||
|
||||
apc = (PKAPC)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KAPC), POOL_TAG_APC);
|
||||
|
||||
if (!apc)
|
||||
goto increment;
|
||||
|
||||
/*
|
||||
* KTHREAD->State values:
|
||||
*
|
||||
* 0 is INITIALIZED;
|
||||
* 1 is READY;
|
||||
* 2 is RUNNING;
|
||||
* 3 is STANDBY;
|
||||
* 4 is TERMINATED;
|
||||
* 5 is WAIT;
|
||||
* 6 is TRANSITION.
|
||||
*
|
||||
* Since we are unsafely enumerating the threads linked list, it's best just
|
||||
* to make sure we don't queue an APC to a terminated thread. We also check after
|
||||
* we've allocated memory for the apc to ensure the window between queuing our APC
|
||||
* and checking the thread state is as small as possible.
|
||||
*/
|
||||
|
||||
if (*state == THREAD_STATE_TERMINATED || THREAD_STATE_INIT)
|
||||
{
|
||||
ExFreePoolWithTag(apc, POOL_TAG_APC);
|
||||
apc = NULL;
|
||||
goto increment;
|
||||
}
|
||||
|
||||
DEBUG_LOG("Apc: %llx", (UINT64)apc);
|
||||
|
||||
KeInitializeApc(
|
||||
apc,
|
||||
current_thread,
|
||||
|
|
|
@ -285,81 +285,88 @@ end:
|
|||
|
||||
VOID
|
||||
ListInit(
|
||||
_Inout_ PLIST_HEAD ListHead
|
||||
_Inout_ PSINGLE_LIST_ENTRY Head,
|
||||
_Inout_ PKSPIN_LOCK Lock
|
||||
)
|
||||
{
|
||||
KeInitializeSpinLock(&ListHead->lock);
|
||||
ListHead->start = NULL;
|
||||
KeInitializeSpinLock(Lock);
|
||||
Head->Next = NULL;
|
||||
}
|
||||
|
||||
PLIST_ITEM
|
||||
VOID
|
||||
ListInsert(
|
||||
_Inout_ PLIST_HEAD ListHead,
|
||||
_Inout_ PLIST_ITEM NewEntry
|
||||
_Inout_ PSINGLE_LIST_ENTRY Head,
|
||||
_Inout_ PSINGLE_LIST_ENTRY NewEntry,
|
||||
_In_ PKSPIN_LOCK Lock
|
||||
)
|
||||
{
|
||||
KIRQL irql = KeGetCurrentIrql();
|
||||
KeAcquireSpinLock(&ListHead->lock, &irql);
|
||||
KeAcquireSpinLock(Lock, &irql);
|
||||
|
||||
PLIST_ITEM old_entry = ListHead->start;
|
||||
PSINGLE_LIST_ENTRY old_entry = Head->Next;
|
||||
|
||||
ListHead->start = NewEntry;
|
||||
NewEntry->next = old_entry;
|
||||
Head->Next = NewEntry;
|
||||
NewEntry->Next = old_entry;
|
||||
|
||||
KeReleaseSpinLock(&ListHead->lock, irql);
|
||||
KeReleaseSpinLock(Lock, irql);
|
||||
}
|
||||
|
||||
PVOID
|
||||
ListRemoveFirst(
|
||||
_Inout_ PLIST_HEAD ListHead
|
||||
BOOLEAN
|
||||
ListFreeFirstEntry(
|
||||
_Inout_ PSINGLE_LIST_ENTRY Head,
|
||||
_In_ PKSPIN_LOCK Lock
|
||||
)
|
||||
{
|
||||
BOOLEAN result = FALSE;
|
||||
KIRQL irql = KeGetCurrentIrql();
|
||||
KeAcquireSpinLock(&ListHead->lock, &irql);
|
||||
KeAcquireSpinLock(Lock, &irql);
|
||||
|
||||
if (ListHead->start)
|
||||
if (Head->Next)
|
||||
{
|
||||
PLIST_ITEM entry = ListHead->start;
|
||||
ListHead->start = ListHead->start->next;
|
||||
ExFreePoolWithTag(entry, POOL_TAG_APC);
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
Head->Next = Head->Next->Next;
|
||||
ExFreePoolWithTag(entry, POOL_TAG_THREAD_LIST);
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&ListHead->lock, irql);
|
||||
KeReleaseSpinLock(Lock, irql);
|
||||
return result;
|
||||
}
|
||||
|
||||
PVOID
|
||||
ListRemoveItem(
|
||||
_Inout_ PLIST_HEAD ListHead,
|
||||
_Inout_ PLIST_ITEM ListItem
|
||||
VOID
|
||||
ListRemoveEntry(
|
||||
_Inout_ PSINGLE_LIST_ENTRY Head,
|
||||
_Inout_ PSINGLE_LIST_ENTRY Entry,
|
||||
_In_ PKSPIN_LOCK Lock
|
||||
)
|
||||
{
|
||||
KIRQL irql = KeGetCurrentIrql();
|
||||
KeAcquireSpinLock(&ListHead->lock, &irql);
|
||||
KeAcquireSpinLock(Lock, &irql);
|
||||
|
||||
PLIST_ITEM entry = ListHead->start;
|
||||
PSINGLE_LIST_ENTRY entry = Head->Next;
|
||||
|
||||
if (!entry)
|
||||
goto unlock;
|
||||
|
||||
if (entry == ListItem)
|
||||
if (entry == Entry)
|
||||
{
|
||||
ListHead->start = entry->next;
|
||||
ExFreePoolWithTag(ListItem, POOL_TAG_APC);
|
||||
Head->Next = entry->Next;
|
||||
ExFreePoolWithTag(Entry, POOL_TAG_THREAD_LIST);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
while (entry->next)
|
||||
while (entry->Next)
|
||||
{
|
||||
if (entry->next == ListItem)
|
||||
if (entry->Next == Entry)
|
||||
{
|
||||
entry->next = ListItem->next;
|
||||
ExFreePoolWithTag(ListItem, POOL_TAG_APC);
|
||||
entry->Next = Entry->Next;
|
||||
ExFreePoolWithTag(Entry, POOL_TAG_THREAD_LIST);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
entry = entry->next;
|
||||
entry = entry->Next;
|
||||
}
|
||||
|
||||
unlock:
|
||||
KeReleaseSpinLock(&ListHead->lock, irql);
|
||||
KeReleaseSpinLock(Lock, irql);
|
||||
}
|
||||
|
|
|
@ -34,19 +34,6 @@ typedef struct _REPORT_HEADER
|
|||
|
||||
}REPORT_HEADER, * PREPORT_HEADER;
|
||||
|
||||
typedef struct _LIST_ITEM
|
||||
{
|
||||
struct _LIST_ITEM* next;
|
||||
|
||||
}LIST_ITEM, * PLIST_ITEM;
|
||||
|
||||
typedef struct _LIST_HEAD
|
||||
{
|
||||
PLIST_ITEM start;
|
||||
KSPIN_LOCK lock;
|
||||
|
||||
}LIST_HEAD, * PLIST_HEAD;
|
||||
|
||||
#define LIST_POOL_TAG 'list'
|
||||
|
||||
VOID
|
||||
|
@ -80,24 +67,34 @@ FreeGlobalReportQueueObjects();
|
|||
|
||||
VOID
|
||||
ListInit(
|
||||
_Inout_ PLIST_HEAD ListHead
|
||||
_Inout_ PSINGLE_LIST_ENTRY Head,
|
||||
_Inout_ PKSPIN_LOCK Lock
|
||||
);
|
||||
|
||||
PLIST_ITEM
|
||||
VOID
|
||||
ListInsert(
|
||||
_Inout_ PLIST_HEAD ListHead,
|
||||
_Inout_ PLIST_ITEM Data
|
||||
_Inout_ PSINGLE_LIST_ENTRY Head,
|
||||
_Inout_ PSINGLE_LIST_ENTRY NewEntry,
|
||||
_In_ PKSPIN_LOCK Lock
|
||||
);
|
||||
|
||||
PVOID
|
||||
ListRemoveFirst(
|
||||
_Inout_ PLIST_HEAD ListHead
|
||||
BOOLEAN
|
||||
ListFreeFirstEntry(
|
||||
_Inout_ PSINGLE_LIST_ENTRY Head,
|
||||
_In_ PKSPIN_LOCK Lock
|
||||
);
|
||||
|
||||
PVOID
|
||||
ListRemoveItem(
|
||||
_Inout_ PLIST_HEAD ListHead,
|
||||
_Inout_ PLIST_ITEM ListItem
|
||||
VOID
|
||||
ListRemoveEntry(
|
||||
_Inout_ PSINGLE_LIST_ENTRY Head,
|
||||
_Inout_ PSINGLE_LIST_ENTRY Entry,
|
||||
_In_ PKSPIN_LOCK Lock
|
||||
);
|
||||
|
||||
VOID
|
||||
EnumerateThreadListWithCallbackRoutine(
|
||||
_In_ PVOID CallbackRoutine,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
#endif
|
|
@ -71,7 +71,7 @@ DWORD WINAPI Init(HINSTANCE hinstDLL)
|
|||
kmanager.CheckForAttachedThreads();
|
||||
break;
|
||||
case 7:
|
||||
//kmanager.InitiateApcStackwalkOperation();
|
||||
kmanager.InitiateApcStackwalkOperation();
|
||||
break;
|
||||
case 8:
|
||||
kmanager.CheckForHiddenThreads();
|
||||
|
@ -81,6 +81,7 @@ DWORD WINAPI Init(HINSTANCE hinstDLL)
|
|||
break;
|
||||
}
|
||||
|
||||
kmanager.InitiateApcStackwalkOperation();
|
||||
kmanager.MonitorCallbackReports();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
|
|
Loading…
Reference in a new issue