2023-08-29 19:36:58 +02:00
|
|
|
#include "thread.h"
|
|
|
|
|
|
|
|
#include "pool.h"
|
|
|
|
#include "callbacks.h"
|
|
|
|
|
2023-08-30 11:19:41 +02:00
|
|
|
#include <intrin.h>
|
|
|
|
|
2023-08-29 19:36:58 +02:00
|
|
|
/*
|
|
|
|
* How this will work:
|
|
|
|
*
|
|
|
|
* 1. The KPCRB (processor control block) contains 3 pointers to 3 threads:
|
|
|
|
*
|
|
|
|
* +0x008 CurrentThread : Ptr64 _KTHREAD
|
|
|
|
* +0x010 NextThread : Ptr64 _KTHREAD
|
|
|
|
* +0x018 IdleThread : Ptr64 _KTHREAD
|
|
|
|
*
|
|
|
|
* 2. These threads are stored in a list that is seperate to the KTHREADs linked list.
|
|
|
|
* We know this because if you unlink a process, the threads are still scheduled by
|
|
|
|
* the OS, meaning the OS has a seperate list that it uses to schedule these threads.
|
|
|
|
*
|
|
|
|
* 3. Now from here, we can get thread ID and pass it to PsLookupThreadByThreadId which
|
|
|
|
* takes the thread ID and returns a pointer to the ETHREAD structure. It does this
|
|
|
|
* by indexing the PspCidTable using the TID we pass in.
|
|
|
|
*
|
|
|
|
* What we can potentially observer is that any threads that have been removed from the
|
|
|
|
* PspCidTable will return a null ptr from PsLookupThreadById. In addition to this, we
|
|
|
|
* can also check if the KTHREAD address referenced in the KPCRB is not in the KTHREAD
|
|
|
|
* linked list. Allowing us to find threads removed from both the PspCidTable and the
|
|
|
|
* KTHREAD linked list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IDEA: we can run a thread on each core to maximise the search, so it would be 3 * num procs
|
|
|
|
*/
|
|
|
|
|
2023-08-30 11:19:41 +02:00
|
|
|
UINT8 thread_found_in_pspcidtable = FALSE;
|
|
|
|
UINT8 thread_found_in_kthreadlist = FALSE;
|
|
|
|
BOOLEAN finished = FALSE;
|
2023-08-29 19:36:58 +02:00
|
|
|
|
2023-08-30 11:19:41 +02:00
|
|
|
UINT64 current_kpcrb_thread = NULL;
|
2023-08-29 19:36:58 +02:00
|
|
|
|
2023-08-30 11:19:41 +02:00
|
|
|
VOID ProcessEnumerationCallback(
|
|
|
|
_In_ PEPROCESS Process
|
2023-08-29 19:36:58 +02:00
|
|
|
)
|
|
|
|
{
|
2023-08-30 11:19:41 +02:00
|
|
|
NTSTATUS status;
|
|
|
|
PLIST_ENTRY thread_list_head;
|
|
|
|
PLIST_ENTRY thread_list_entry;
|
|
|
|
PETHREAD current_thread;
|
|
|
|
UINT32 thread_id;
|
|
|
|
|
|
|
|
if ( finished == TRUE )
|
|
|
|
return;
|
|
|
|
|
|
|
|
thread_list_head = ( PLIST_ENTRY )( ( UINT64 )Process + KPROCESS_THREADLIST_OFFSET );
|
|
|
|
thread_list_entry = thread_list_head->Flink;
|
|
|
|
|
|
|
|
while ( thread_list_entry != thread_list_head )
|
|
|
|
{
|
|
|
|
current_thread = ( PETHREAD )( ( UINT64 )thread_list_entry - KTHREAD_THREADLIST_OFFSET );
|
|
|
|
|
|
|
|
if ( current_thread == current_kpcrb_thread )
|
|
|
|
{
|
|
|
|
thread_found_in_kthreadlist = TRUE;
|
|
|
|
|
|
|
|
thread_id = PsGetThreadId( current_thread );
|
|
|
|
|
|
|
|
if ( thread_id != NULL )
|
|
|
|
{
|
|
|
|
thread_found_in_pspcidtable = TRUE;
|
|
|
|
finished = TRUE;
|
|
|
|
}
|
|
|
|
}
|
2023-08-29 19:36:58 +02:00
|
|
|
|
2023-08-30 11:19:41 +02:00
|
|
|
thread_list_entry = thread_list_entry->Flink;
|
|
|
|
}
|
2023-08-29 19:36:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS ValidateKPCRBThreads(
|
|
|
|
//_In_ PIRP Irp
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
2023-08-30 11:19:41 +02:00
|
|
|
UINT64 kpcr;
|
|
|
|
UINT64 kprcb;
|
|
|
|
KAFFINITY old_affinity = { 0 };
|
|
|
|
|
|
|
|
for ( LONG processor_index = 0; processor_index < KeQueryActiveProcessorCount( 0 ); processor_index++ )
|
|
|
|
{
|
|
|
|
old_affinity = KeSetSystemAffinityThreadEx( ( KAFFINITY )( 1 << processor_index ) );
|
|
|
|
|
|
|
|
kpcr = __readmsr( IA32_GS_BASE );
|
|
|
|
kprcb = kpcr + KPRCB_OFFSET_FROM_GS_BASE;
|
|
|
|
current_kpcrb_thread = *( UINT64* )( kprcb + KPCRB_CURRENT_THREAD );
|
|
|
|
|
|
|
|
DEBUG_LOG( "Current processor: %lx, current kprcb: %llx, current thread: %llx", KeGetCurrentProcessorNumber(), kprcb, current_kpcrb_thread );
|
|
|
|
|
|
|
|
EnumerateProcessListWithCallbackFunction(
|
|
|
|
ProcessEnumerationCallback
|
|
|
|
);
|
|
|
|
|
|
|
|
DEBUG_LOG( "Thread in psp: %i, thread in list: %i", thread_found_in_pspcidtable, thread_found_in_kthreadlist );
|
|
|
|
|
|
|
|
if ( thread_found_in_kthreadlist == FALSE || thread_found_in_pspcidtable == FALSE )
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
current_kpcrb_thread = NULL;
|
|
|
|
thread_found_in_pspcidtable = FALSE;
|
|
|
|
thread_found_in_kthreadlist = FALSE;
|
|
|
|
finished = FALSE;
|
|
|
|
|
|
|
|
KeRevertToUserAffinityThreadEx( old_affinity );
|
|
|
|
}
|
|
|
|
|
2023-08-29 19:36:58 +02:00
|
|
|
}
|