mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
some refactoring
This commit is contained in:
parent
19619119df
commit
c5e8beaf99
17 changed files with 1161 additions and 1184 deletions
220
driver/apc.c
Normal file
220
driver/apc.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
#include "apc.h"
|
||||
|
||||
#include "driver.h"
|
||||
#include "imports.h"
|
||||
|
||||
VOID
|
||||
GetApcContextByIndex(_Out_ PVOID* Context, _In_ INT Index)
|
||||
{
|
||||
AcquireDriverConfigLock();
|
||||
*Context = GetApcContextArray()[Index];
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
VOID
|
||||
GetApcContext(_Out_ PVOID* Context, _In_ LONG ContextIdentifier)
|
||||
{
|
||||
AcquireDriverConfigLock();
|
||||
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++)
|
||||
{
|
||||
PAPC_CONTEXT_HEADER header = GetApcContextArray()[index];
|
||||
|
||||
if (!header)
|
||||
continue;
|
||||
|
||||
if (header->context_id != ContextIdentifier)
|
||||
continue;
|
||||
|
||||
*Context = header;
|
||||
goto unlock;
|
||||
}
|
||||
unlock:
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
/*
|
||||
* No need to hold the lock here as the thread freeing the APCs will
|
||||
* already hold the configuration lock. We also dont want to release and
|
||||
* reclaim the lock before calling this function since we need to ensure
|
||||
* we hold the lock during the entire decrement and free process.
|
||||
*/
|
||||
BOOLEAN
|
||||
FreeApcContextStructure(_Out_ PAPC_CONTEXT_HEADER Context)
|
||||
{
|
||||
DEBUG_VERBOSE("All APCs executed, freeing context structure");
|
||||
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++)
|
||||
{
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
|
||||
if (entry[index] != Context)
|
||||
continue;
|
||||
|
||||
if (Context->count > 0)
|
||||
return FALSE;
|
||||
|
||||
ImpExFreePoolWithTag(Context, POOL_TAG_APC);
|
||||
entry[index] = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
IncrementApcCount(_In_ LONG ContextId)
|
||||
{
|
||||
PAPC_CONTEXT_HEADER header = NULL;
|
||||
GetApcContext(&header, ContextId);
|
||||
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
/* i actually dont think we need this lock here */
|
||||
AcquireDriverConfigLock();
|
||||
header->count += 1;
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
VOID
|
||||
FreeApcAndDecrementApcCount(_Inout_ PRKAPC Apc, _In_ LONG ContextId)
|
||||
{
|
||||
PAPC_CONTEXT_HEADER context = NULL;
|
||||
|
||||
ImpExFreePoolWithTag(Apc, POOL_TAG_APC);
|
||||
GetApcContext(&context, ContextId);
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
AcquireDriverConfigLock();
|
||||
context->count -= 1;
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
/*
|
||||
* The reason we use a query model rather then checking the count of queued APCs
|
||||
* after each APC free and decrement is that the lock will be recursively acquired by
|
||||
* freeing threads (i.e executing APCs) rather then APC allocation threads. The reason for this
|
||||
* being that freeing threads are executing at a higher IRQL then the APC allocation
|
||||
* thread, hence they are granted higher priority by the scheduler when determining
|
||||
* which thread will accquire the lock next:
|
||||
*
|
||||
* [+] Freeing thread -> ApcKernelRoutine IRQL: 1 (APC_LEVEL)
|
||||
* [+] Allocation thread -> ValidateThreadViaKernelApcCallback IRQL: 0 (PASSIVE_LEVEL)
|
||||
*
|
||||
* As a result, once an APC is executed and reaches the freeing stage, it will acquire the
|
||||
* lock and decrement it. Then, if atleast 1 APC execution thread is waiting on the lock,
|
||||
* it will be prioritised due to its higher IRQL and the cycle will continue. Eventually,
|
||||
* the count will reach 0 due to recursive acquisition by the executing APC threads and then
|
||||
* the function will free the APC context structure. This will then cause a bug check the next
|
||||
* time a thread accesses the context structure and hence not good :c.
|
||||
*
|
||||
* So to combat this, we add in a flag specifying whether or not an allocation of APCs is
|
||||
* in progress, and even if the count is 0 we will not free the context structure until
|
||||
* the count is 0 and allocation_in_progress is 0. We can then call this function alongside
|
||||
* other query callbacks via IOCTL to constantly monitor the status of open APC contexts.
|
||||
*/
|
||||
NTSTATUS
|
||||
QueryActiveApcContextsForCompletion()
|
||||
{
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++)
|
||||
{
|
||||
PAPC_CONTEXT_HEADER entry = NULL;
|
||||
GetApcContextByIndex(&entry, index);
|
||||
AcquireDriverConfigLock();
|
||||
|
||||
if (!entry)
|
||||
goto increment;
|
||||
|
||||
if (entry->count > 0 || entry->allocation_in_progress == TRUE)
|
||||
goto increment;
|
||||
|
||||
switch (entry->context_id)
|
||||
{
|
||||
case APC_CONTEXT_ID_STACKWALK:
|
||||
FreeApcStackwalkApcContextInformation(entry);
|
||||
FreeApcContextStructure(entry);
|
||||
break;
|
||||
}
|
||||
|
||||
increment:
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
InsertApcContext(_In_ PVOID Context)
|
||||
{
|
||||
if (IsDriverUnloading())
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
AcquireDriverConfigLock();
|
||||
PAPC_CONTEXT_HEADER header = Context;
|
||||
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++)
|
||||
{
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
|
||||
if (entry[index] == NULL)
|
||||
{
|
||||
entry[index] = Context;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
end:
|
||||
ReleaseDriverConfigLock();
|
||||
}
|
||||
|
||||
/*
|
||||
* The driver config structure holds an array of pointers to APC context structures. These
|
||||
* APC context structures are unique to each APC operation that this driver will perform. For
|
||||
* example, a single context will manage all APCs that are used to stackwalk, whilst another
|
||||
* context will be used to manage all APCs used to query a threads memory for example.
|
||||
*
|
||||
* Due to the nature of APCs, its important to keep a total or count of the number of APCs we
|
||||
* have allocated and queued to threads. This information is stored in the APC_CONTEXT_HEADER which
|
||||
* all APC context structures will contain as the first entry in their structure. It holds the
|
||||
* ContextId which is a unique identifier for the type of APC operation it is managing aswell as the
|
||||
* number of currently queued APCs.
|
||||
*
|
||||
* When an APC is allocated a queued, we increment this count. When an APC is completed and freed,
|
||||
* we decrement this counter and free the APC itself. If all APCs have been freed and the counter is
|
||||
* 0,the following objects will be freed:
|
||||
*
|
||||
* 1. Any additional allocations used by the APC stored in the context structure
|
||||
* 2. The APC context structure for the given APC operation
|
||||
* 3. The APC context entry in g_DriverConfig->>apc_contexts will be zero'd.
|
||||
*
|
||||
* It's important to remember that the driver can unload when pending APC's have not been freed due
|
||||
* to the limitations windows places on APCs, however I am in the process of finding a solution for
|
||||
* this.
|
||||
*/
|
||||
BOOLEAN
|
||||
DrvUnloadFreeAllApcContextStructures()
|
||||
{
|
||||
AcquireDriverConfigLock();
|
||||
|
||||
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++)
|
||||
{
|
||||
PUINT64 entry = GetApcContextArray();
|
||||
|
||||
if (entry[index] == NULL)
|
||||
continue;
|
||||
|
||||
PAPC_CONTEXT_HEADER context = entry[index];
|
||||
|
||||
if (context->count > 0)
|
||||
{
|
||||
ReleaseDriverConfigLock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ImpExFreePoolWithTag(entry, POOL_TAG_APC);
|
||||
}
|
||||
unlock:
|
||||
ReleaseDriverConfigLock();
|
||||
return TRUE;
|
||||
}
|
35
driver/apc.h
Normal file
35
driver/apc.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef APC_H
|
||||
#define APC_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "apc.h"
|
||||
|
||||
#include "driver.h"
|
||||
#include "imports.h"
|
||||
|
||||
VOID
|
||||
GetApcContextByIndex(_Out_ PVOID* Context, _In_ INT Index);
|
||||
|
||||
VOID
|
||||
GetApcContext(_Out_ PVOID* Context, _In_ LONG ContextIdentifier);
|
||||
|
||||
BOOLEAN
|
||||
FreeApcContextStructure(_Out_ PAPC_CONTEXT_HEADER Context);
|
||||
|
||||
VOID
|
||||
IncrementApcCount(_In_ LONG ContextId);
|
||||
|
||||
VOID
|
||||
FreeApcAndDecrementApcCount(_Inout_ PRKAPC Apc, _In_ LONG ContextId);
|
||||
|
||||
NTSTATUS
|
||||
QueryActiveApcContextsForCompletion();
|
||||
|
||||
VOID
|
||||
InsertApcContext(_In_ PVOID Context);
|
||||
|
||||
BOOLEAN
|
||||
DrvUnloadFreeAllApcContextStructures();
|
||||
|
||||
#endif
|
|
@ -8,44 +8,6 @@
|
|||
#include "modules.h"
|
||||
#include "imports.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
|
||||
* to ensure atomicity.
|
||||
*/
|
||||
typedef struct _THREAD_LIST
|
||||
{
|
||||
SINGLE_LIST_ENTRY start;
|
||||
volatile BOOLEAN active;
|
||||
KGUARDED_MUTEX 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;
|
||||
|
||||
typedef struct _PROCESS_LIST
|
||||
{
|
||||
SINGLE_LIST_ENTRY start;
|
||||
volatile BOOLEAN active;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} PROCESS_LIST, *PPROCESS_LIST;
|
||||
|
||||
PPROCESS_LIST process_list = NULL;
|
||||
|
||||
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;
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
|
||||
|
@ -83,62 +45,55 @@ CleanupThreadListFreeCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry)
|
|||
VOID
|
||||
CleanupProcessListOnDriverUnload()
|
||||
{
|
||||
InterlockedExchange(&process_list->active, FALSE);
|
||||
PPROCESS_LIST_HEAD list = GetProcessList();
|
||||
InterlockedExchange(&list->active, FALSE);
|
||||
ImpPsSetCreateProcessNotifyRoutine(ProcessCreateNotifyRoutine, TRUE);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!ListFreeFirstEntry(
|
||||
&process_list->start, &process_list->lock, CleanupProcessListFreeCallback))
|
||||
{
|
||||
ImpExFreePoolWithTag(process_list, POOL_TAG_THREAD_LIST);
|
||||
if (!ListFreeFirstEntry(&list->start, &list->lock, CleanupProcessListFreeCallback))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
CleanupThreadListOnDriverUnload()
|
||||
{
|
||||
InterlockedExchange(&thread_list->active, FALSE);
|
||||
PTHREAD_LIST_HEAD list = GetThreadList();
|
||||
InterlockedExchange(&list->active, FALSE);
|
||||
ImpPsRemoveCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!ListFreeFirstEntry(
|
||||
&thread_list->start, &thread_list->lock, CleanupThreadListFreeCallback))
|
||||
{
|
||||
ImpExFreePoolWithTag(thread_list, POOL_TAG_THREAD_LIST);
|
||||
if (!ListFreeFirstEntry(&list->start, &list->lock, CleanupThreadListFreeCallback))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
CleanupDriverListOnDriverUnload()
|
||||
{
|
||||
InterlockedExchange(&driver_list->active, FALSE);
|
||||
PDRIVER_LIST_HEAD list = GetDriverList();
|
||||
InterlockedExchange(&list->active, FALSE);
|
||||
PsRemoveLoadImageNotifyRoutine(ImageLoadNotifyRoutineCallback);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!ListFreeFirstEntry(&driver_list->start, &driver_list->lock, NULL))
|
||||
{
|
||||
ImpExFreePoolWithTag(driver_list, POOL_TAG_DRIVER_LIST);
|
||||
if (!ListFreeFirstEntry(&list->start, &list->lock, NULL))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
EnumerateThreadListWithCallbackRoutine(_In_ PVOID CallbackRoutine, _In_opt_ PVOID Context)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(&thread_list->lock);
|
||||
PTHREAD_LIST_HEAD list = GetThreadList();
|
||||
ImpKeAcquireGuardedMutex(&list->lock);
|
||||
|
||||
if (!CallbackRoutine)
|
||||
goto unlock;
|
||||
|
||||
PTHREAD_LIST_ENTRY entry = thread_list->start.Next;
|
||||
PTHREAD_LIST_ENTRY entry = list->start.Next;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
|
@ -148,18 +103,19 @@ EnumerateThreadListWithCallbackRoutine(_In_ PVOID CallbackRoutine, _In_opt_ PVOI
|
|||
}
|
||||
|
||||
unlock:
|
||||
ImpKeReleaseGuardedMutex(&thread_list->lock);
|
||||
ImpKeReleaseGuardedMutex(&list->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
EnumerateProcessListWithCallbackRoutine(_In_ PVOID CallbackRoutine, _In_opt_ PVOID Context)
|
||||
{
|
||||
ImpKeAcquireGuardedMutex(&process_list->lock);
|
||||
PPROCESS_LIST_HEAD list = GetProcessList();
|
||||
ImpKeAcquireGuardedMutex(&list->lock);
|
||||
|
||||
if (!CallbackRoutine)
|
||||
goto unlock;
|
||||
|
||||
PPROCESS_LIST_ENTRY entry = process_list->start.Next;
|
||||
PPROCESS_LIST_ENTRY entry = list->start.Next;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
|
@ -169,7 +125,7 @@ EnumerateProcessListWithCallbackRoutine(_In_ PVOID CallbackRoutine, _In_opt_ PVO
|
|||
}
|
||||
|
||||
unlock:
|
||||
ImpKeReleaseGuardedMutex(&process_list->lock);
|
||||
ImpKeReleaseGuardedMutex(&list->lock);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -181,15 +137,10 @@ InitialiseDriverList()
|
|||
SYSTEM_MODULES modules = {0};
|
||||
PDRIVER_LIST_ENTRY entry = NULL;
|
||||
PRTL_MODULE_EXTENDED_INFO module_entry = NULL;
|
||||
PDRIVER_LIST_HEAD list = GetDriverList();
|
||||
|
||||
driver_list =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(DRIVER_LIST), POOL_TAG_DRIVER_LIST);
|
||||
|
||||
if (!driver_list)
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
|
||||
InterlockedExchange(&driver_list->active, TRUE);
|
||||
ListInit(&driver_list->start, &driver_list->lock);
|
||||
InterlockedExchange(&list->active, TRUE);
|
||||
ListInit(&list->start, &list->lock);
|
||||
|
||||
status = GetSystemModuleInformation(&modules);
|
||||
|
||||
|
@ -230,7 +181,7 @@ InitialiseDriverList()
|
|||
entry->hashed = FALSE;
|
||||
}
|
||||
|
||||
ListInsert(&driver_list->start, entry, &driver_list->lock);
|
||||
ListInsert(&list->start, entry, &list->lock);
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -247,10 +198,11 @@ end:
|
|||
VOID
|
||||
FindDriverEntryByBaseAddress(_In_ PVOID ImageBase, _Out_ PDRIVER_LIST_ENTRY* Entry)
|
||||
{
|
||||
PDRIVER_LIST_HEAD list = GetDriverList();
|
||||
ImpKeAcquireGuardedMutex(&list->lock);
|
||||
*Entry = NULL;
|
||||
ImpKeAcquireGuardedMutex(&driver_list->lock);
|
||||
|
||||
PDRIVER_LIST_ENTRY entry = (PDRIVER_LIST_ENTRY)driver_list->start.Next;
|
||||
PDRIVER_LIST_ENTRY entry = (PDRIVER_LIST_ENTRY)list->start.Next;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
|
@ -263,7 +215,7 @@ FindDriverEntryByBaseAddress(_In_ PVOID ImageBase, _Out_ PDRIVER_LIST_ENTRY* Ent
|
|||
entry = entry->list.Next;
|
||||
}
|
||||
unlock:
|
||||
ImpKeReleaseGuardedMutex(&driver_list->lock);
|
||||
ImpKeReleaseGuardedMutex(&list->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -274,8 +226,9 @@ ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName,
|
|||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PDRIVER_LIST_ENTRY entry = NULL;
|
||||
RTL_MODULE_EXTENDED_INFO module = {0};
|
||||
PDRIVER_LIST_HEAD list = GetDriverList();
|
||||
|
||||
if (InterlockedExchange(&driver_list->active, driver_list->active) == FALSE)
|
||||
if (InterlockedExchange(&list->active, list->active) == FALSE)
|
||||
return;
|
||||
|
||||
if (ImageInfo->SystemModeImage == FALSE)
|
||||
|
@ -315,50 +268,33 @@ ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName,
|
|||
entry->hashed = FALSE;
|
||||
}
|
||||
|
||||
ListInsert(&driver_list->start, entry, &driver_list->lock);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
InitialiseProcessList()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
process_list =
|
||||
ImpExAllocatePool2(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;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
InitialiseThreadList()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
thread_list =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(THREAD_LIST), POOL_TAG_THREAD_LIST);
|
||||
|
||||
if (!thread_list)
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
|
||||
InterlockedExchange(&thread_list->active, TRUE);
|
||||
ListInit(&thread_list->start, &thread_list->lock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
ListInsert(&list->start, entry, &list->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
FindProcessListEntryByProcess(_In_ PKPROCESS Process, _Inout_ PPROCESS_LIST_ENTRY* Entry)
|
||||
InitialiseProcessList()
|
||||
{
|
||||
*Entry = NULL;
|
||||
ImpKeAcquireGuardedMutex(&process_list->lock);
|
||||
PPROCESS_LIST_HEAD list = GetProcessList();
|
||||
InterlockedExchange(&list->active, TRUE);
|
||||
ListInit(&list->start, &list->lock);
|
||||
}
|
||||
|
||||
PPROCESS_LIST_ENTRY entry = (PPROCESS_LIST_ENTRY)process_list->start.Next;
|
||||
VOID
|
||||
InitialiseThreadList()
|
||||
{
|
||||
PTHREAD_LIST_HEAD list = GetThreadList();
|
||||
InterlockedExchange(&list->active, TRUE);
|
||||
ListInit(&list->start, &list->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
FindProcessListEntryByProcess(_In_ PKPROCESS Process, _Out_ PPROCESS_LIST_ENTRY* Entry)
|
||||
{
|
||||
PPROCESS_LIST_HEAD list = GetProcessList();
|
||||
ImpKeAcquireGuardedMutex(&list->lock);
|
||||
*Entry = NULL;
|
||||
|
||||
PPROCESS_LIST_ENTRY entry = (PPROCESS_LIST_ENTRY)list->start.Next;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
|
@ -371,16 +307,17 @@ FindProcessListEntryByProcess(_In_ PKPROCESS Process, _Inout_ PPROCESS_LIST_ENTR
|
|||
entry = entry->list.Next;
|
||||
}
|
||||
unlock:
|
||||
ImpKeReleaseGuardedMutex(&process_list->lock);
|
||||
ImpKeReleaseGuardedMutex(&list->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
FindThreadListEntryByThreadAddress(_In_ PKTHREAD Thread, _Inout_ PTHREAD_LIST_ENTRY* Entry)
|
||||
FindThreadListEntryByThreadAddress(_In_ PKTHREAD Thread, _Out_ PTHREAD_LIST_ENTRY* Entry)
|
||||
{
|
||||
PTHREAD_LIST_HEAD list = GetThreadList();
|
||||
ImpKeAcquireGuardedMutex(&list->lock);
|
||||
*Entry = NULL;
|
||||
ImpKeAcquireGuardedMutex(&thread_list->lock);
|
||||
|
||||
PTHREAD_LIST_ENTRY entry = (PTHREAD_LIST_ENTRY)thread_list->start.Next;
|
||||
PTHREAD_LIST_ENTRY entry = (PTHREAD_LIST_ENTRY)list->start.Next;
|
||||
|
||||
while (entry)
|
||||
{
|
||||
|
@ -393,7 +330,7 @@ FindThreadListEntryByThreadAddress(_In_ PKTHREAD Thread, _Inout_ PTHREAD_LIST_EN
|
|||
entry = entry->list.Next;
|
||||
}
|
||||
unlock:
|
||||
ImpKeReleaseGuardedMutex(&thread_list->lock);
|
||||
ImpKeReleaseGuardedMutex(&list->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -402,8 +339,9 @@ ProcessCreateNotifyRoutine(_In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOO
|
|||
PPROCESS_LIST_ENTRY entry = NULL;
|
||||
PKPROCESS parent = NULL;
|
||||
PKPROCESS process = NULL;
|
||||
PPROCESS_LIST_HEAD list = GetProcessList();
|
||||
|
||||
if (InterlockedExchange(&process_list->active, process_list->active) == FALSE)
|
||||
if (InterlockedExchange(&list->active, list->active) == FALSE)
|
||||
return;
|
||||
|
||||
ImpPsLookupProcessByProcessId(ParentId, &parent);
|
||||
|
@ -426,7 +364,7 @@ ProcessCreateNotifyRoutine(_In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOO
|
|||
entry->parent = parent;
|
||||
entry->process = process;
|
||||
|
||||
ListInsert(&process_list->start, entry, &process_list->lock);
|
||||
ListInsert(&list->start, entry, &list->lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -438,7 +376,7 @@ ProcessCreateNotifyRoutine(_In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOO
|
|||
ImpObDereferenceObject(entry->parent);
|
||||
ImpObDereferenceObject(entry->process);
|
||||
|
||||
ListRemoveEntry(&process_list->start, entry, &process_list->lock);
|
||||
ListRemoveEntry(&list->start, entry, &list->lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,9 +386,10 @@ ThreadCreateNotifyRoutine(_In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ BOOL
|
|||
PTHREAD_LIST_ENTRY entry = NULL;
|
||||
PKTHREAD thread = NULL;
|
||||
PKPROCESS process = NULL;
|
||||
PTHREAD_LIST_HEAD list = GetThreadList();
|
||||
|
||||
/* ensure we don't insert new entries if we are unloading */
|
||||
if (InterlockedExchange(&thread_list->active, thread_list->active) == FALSE)
|
||||
if (InterlockedExchange(&list->active, list->active) == FALSE)
|
||||
return;
|
||||
|
||||
ImpPsLookupThreadByThreadId(ThreadId, &thread);
|
||||
|
@ -475,7 +414,7 @@ ThreadCreateNotifyRoutine(_In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ BOOL
|
|||
entry->apc = NULL;
|
||||
entry->apc_queued = FALSE;
|
||||
|
||||
ListInsert(&thread_list->start, &entry->list, &thread_list->lock);
|
||||
ListInsert(&list->start, &entry->list, &list->lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -487,7 +426,7 @@ ThreadCreateNotifyRoutine(_In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ BOOL
|
|||
ImpObDereferenceObject(entry->thread);
|
||||
ImpObDereferenceObject(entry->owning_process);
|
||||
|
||||
ListRemoveEntry(&thread_list->start, entry, &thread_list->lock);
|
||||
ListRemoveEntry(&list->start, entry, &list->lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -856,7 +795,7 @@ TimerObjectCallbackRoutine(_In_ PKDPC Dpc,
|
|||
_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;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#ifndef CALLBACKS_H
|
||||
#define CALLBACKS_H
|
||||
|
||||
#include <ntifs.h>
|
||||
#include <wdftypes.h>
|
||||
#include <wdf.h>
|
||||
|
@ -25,7 +24,7 @@ typedef struct _OPEN_HANDLE_FAILURE_REPORT
|
|||
#define PROCESS_CREATE_PROCESS 0x0080
|
||||
#define PROCESS_TERMINATE 0x0001
|
||||
#define PROCESS_CREATE_THREAD 0x0002
|
||||
#define PROCESS_DUP_HANDLE 0x0040
|
||||
//#define PROCESS_DUP_HANDLE 0x0040
|
||||
#define PROCESS_QUERY_INFORMATION 0x0400
|
||||
#define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
|
||||
#define PROCESS_SET_INFORMATION 0x0200
|
||||
|
@ -45,24 +44,6 @@ static const uintptr_t EPROCESS_PLIST_ENTRY_OFFSET = 0x448;
|
|||
static UNICODE_STRING OBJECT_TYPE_PROCESS = RTL_CONSTANT_STRING(L"Process");
|
||||
static UNICODE_STRING OBJECT_TYPE_THREAD = RTL_CONSTANT_STRING(L"Thread");
|
||||
|
||||
typedef struct _THREAD_LIST_ENTRY
|
||||
{
|
||||
SINGLE_LIST_ENTRY list;
|
||||
PKTHREAD thread;
|
||||
PKPROCESS owning_process;
|
||||
BOOLEAN apc_queued;
|
||||
PKAPC apc;
|
||||
|
||||
} THREAD_LIST_ENTRY, *PTHREAD_LIST_ENTRY;
|
||||
|
||||
typedef struct _PROCESS_LIST_ENTRY
|
||||
{
|
||||
SINGLE_LIST_ENTRY list;
|
||||
PKPROCESS process;
|
||||
PKPROCESS parent;
|
||||
|
||||
} PROCESS_LIST_ENTRY, *PPROCESS_LIST_ENTRY;
|
||||
|
||||
#define DRIVER_PATH_LENGTH 0x100
|
||||
#define SHA_256_HASH_LENGTH 32
|
||||
|
||||
|
@ -94,10 +75,10 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
|
|||
NTSTATUS
|
||||
EnumerateProcessHandles(_In_ PPROCESS_LIST_ENTRY ProcessListEntry, _In_opt_ PVOID Context);
|
||||
|
||||
NTSTATUS
|
||||
VOID
|
||||
InitialiseThreadList();
|
||||
|
||||
NTSTATUS
|
||||
VOID
|
||||
InitialiseProcessList();
|
||||
|
||||
VOID
|
||||
|
|
145
driver/common.h
145
driver/common.h
|
@ -39,6 +39,149 @@
|
|||
|
||||
#define STATIC static
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
typedef struct _THREAD_LIST_HEAD
|
||||
{
|
||||
SINGLE_LIST_ENTRY start;
|
||||
volatile BOOLEAN active;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} THREAD_LIST_HEAD, *PTHREAD_LIST_HEAD;
|
||||
|
||||
typedef struct _PROCESS_LIST_HEAD
|
||||
{
|
||||
SINGLE_LIST_ENTRY start;
|
||||
volatile BOOLEAN active;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} PROCESS_LIST_HEAD, *PPROCESS_LIST_HEAD;
|
||||
|
||||
typedef struct _DRIVER_LIST_HEAD
|
||||
{
|
||||
SINGLE_LIST_ENTRY start;
|
||||
volatile ULONG count;
|
||||
volatile BOOLEAN active;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} DRIVER_LIST_HEAD, *PDRIVER_LIST_HEAD;
|
||||
|
||||
typedef struct _THREAD_LIST_ENTRY
|
||||
{
|
||||
SINGLE_LIST_ENTRY list;
|
||||
PKTHREAD thread;
|
||||
PKPROCESS owning_process;
|
||||
BOOLEAN apc_queued;
|
||||
PKAPC apc;
|
||||
|
||||
} THREAD_LIST_ENTRY, *PTHREAD_LIST_ENTRY;
|
||||
|
||||
typedef struct _PROCESS_LIST_ENTRY
|
||||
{
|
||||
SINGLE_LIST_ENTRY list;
|
||||
PKPROCESS process;
|
||||
PKPROCESS parent;
|
||||
|
||||
} PROCESS_LIST_ENTRY, *PPROCESS_LIST_ENTRY;
|
||||
|
||||
#define DRIVER_PATH_MAX_LENGTH 512
|
||||
#define MOTHERBOARD_SERIAL_CODE_LENGTH 64
|
||||
#define DEVICE_DRIVE_0_SERIAL_CODE_LENGTH 64
|
||||
|
||||
#define MAX_REPORTS_PER_IRP 20
|
||||
|
||||
#define POOL_TAG_STRINGS 'strs'
|
||||
|
||||
#define IOCTL_STORAGE_QUERY_PROPERTY 0x002D1400
|
||||
|
||||
#define MAXIMUM_APC_CONTEXTS 10
|
||||
|
||||
/*
|
||||
* ioctl_flag consists of the first 16 bits of the Function part of the CTL code
|
||||
* cookie_value consists of a static 16 bit value generated by the user mode app on startup
|
||||
* which is then passed to the driver and stored.
|
||||
*/
|
||||
typedef union _SECURITY_COOKIE
|
||||
{
|
||||
struct
|
||||
{
|
||||
UINT32 ioctl_flag : 16;
|
||||
UINT32 cookie_value : 16;
|
||||
} bits;
|
||||
|
||||
UINT32 flags;
|
||||
|
||||
} SECURITY_COOKIE, *PSECURITY_COOKIE;
|
||||
|
||||
typedef struct _TIMER_OBJECT
|
||||
{
|
||||
/*
|
||||
* state = 1: callback in progress
|
||||
* state = 0: no callback in progress (i.e safe to free and unregister)
|
||||
*/
|
||||
volatile LONG state;
|
||||
|
||||
PKTIMER timer;
|
||||
PKDPC dpc;
|
||||
PIO_WORKITEM work_item;
|
||||
|
||||
} TIMER_OBJECT, *PTIMER_OBJECT;
|
||||
|
||||
typedef enum _ENVIRONMENT_TYPE
|
||||
{
|
||||
NativeWindows = 0,
|
||||
Vmware,
|
||||
VirtualBox
|
||||
|
||||
} ENVIRONMENT_TYPE;
|
||||
|
||||
typedef enum _PROCESSOR_TYPE
|
||||
{
|
||||
Unknown = 0,
|
||||
GenuineIntel,
|
||||
AuthenticAmd
|
||||
|
||||
} PROCESSOR_TYPE;
|
||||
|
||||
#define VENDOR_STRING_MAX_LENGTH 256
|
||||
|
||||
typedef struct _SYSTEM_INFORMATION
|
||||
{
|
||||
CHAR motherboard_serial[MOTHERBOARD_SERIAL_CODE_LENGTH];
|
||||
CHAR drive_0_serial[DEVICE_DRIVE_0_SERIAL_CODE_LENGTH];
|
||||
CHAR vendor[VENDOR_STRING_MAX_LENGTH];
|
||||
BOOLEAN virtualised_environment;
|
||||
ENVIRONMENT_TYPE environment;
|
||||
PROCESSOR_TYPE processor;
|
||||
RTL_OSVERSIONINFOW os_information;
|
||||
|
||||
} SYSTEM_INFORMATION, *PSYSTEM_INFORMATION;
|
||||
|
||||
typedef struct _OB_CALLBACKS_CONFIG
|
||||
{
|
||||
PVOID registration_handle;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} OB_CALLBACKS_CONFIG, *POB_CALLBACKS_CONFIG;
|
||||
|
||||
typedef struct _IRP_QUEUE_HEAD
|
||||
{
|
||||
SINGLE_LIST_ENTRY start;
|
||||
volatile INT count;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} IRP_QUEUE_HEAD, *PIRP_QUEUE_HEAD;
|
||||
|
||||
typedef struct _IRP_QUEUE_ENTRY
|
||||
{
|
||||
SINGLE_LIST_ENTRY entry;
|
||||
PIRP irp;
|
||||
|
||||
} IRP_QUEUE_ENTRY, *PIRP_QUEUE_ENTRY;
|
||||
|
||||
#define NMI_CONTEXT_POOL '7331'
|
||||
#define STACK_FRAMES_POOL 'loop'
|
||||
#define INVALID_DRIVER_LIST_HEAD_POOL 'rwar'
|
||||
|
@ -69,7 +212,7 @@
|
|||
#define POOL_TAG_THREAD_LIST 'list'
|
||||
#define POOL_TAG_DRIVER_LIST 'drvl'
|
||||
#define POOL_TAG_IRP_QUEUE 'irpp'
|
||||
#define POOL_TAG_TIMER 'time'
|
||||
#define POOL_TAG_TIMER 'time'
|
||||
|
||||
#define IA32_APERF_MSR 0x000000E8
|
||||
|
||||
|
|
1369
driver/driver.c
1369
driver/driver.c
File diff suppressed because it is too large
Load diff
160
driver/driver.h
160
driver/driver.h
|
@ -9,84 +9,7 @@
|
|||
#include "queue.h"
|
||||
#include "modules.h"
|
||||
#include "integrity.h"
|
||||
|
||||
#define DRIVER_PATH_MAX_LENGTH 512
|
||||
#define MOTHERBOARD_SERIAL_CODE_LENGTH 64
|
||||
#define DEVICE_DRIVE_0_SERIAL_CODE_LENGTH 64
|
||||
|
||||
#define MAX_REPORTS_PER_IRP 20
|
||||
|
||||
#define POOL_TAG_STRINGS 'strs'
|
||||
|
||||
#define IOCTL_STORAGE_QUERY_PROPERTY 0x002D1400
|
||||
|
||||
#define MAXIMUM_APC_CONTEXTS 10
|
||||
|
||||
typedef struct _TIMER_OBJECT
|
||||
{
|
||||
/*
|
||||
* state = 1: callback in progress
|
||||
* state = 0: no callback in progress (i.e safe to free and unregister)
|
||||
*/
|
||||
volatile LONG state;
|
||||
|
||||
PKTIMER timer;
|
||||
PKDPC dpc;
|
||||
PIO_WORKITEM work_item;
|
||||
|
||||
} TIMER_OBJECT, *PTIMER_OBJECT;
|
||||
|
||||
typedef enum _ENVIRONMENT_TYPE
|
||||
{
|
||||
NativeWindows = 0,
|
||||
Vmware,
|
||||
VirtualBox
|
||||
|
||||
} ENVIRONMENT_TYPE;
|
||||
|
||||
typedef enum _PROCESSOR_TYPE
|
||||
{
|
||||
Unknown = 0,
|
||||
GenuineIntel,
|
||||
AuthenticAmd
|
||||
|
||||
} PROCESSOR_TYPE;
|
||||
|
||||
#define VENDOR_STRING_MAX_LENGTH 256
|
||||
|
||||
typedef struct _SYSTEM_INFORMATION
|
||||
{
|
||||
CHAR motherboard_serial[MOTHERBOARD_SERIAL_CODE_LENGTH];
|
||||
CHAR drive_0_serial[DEVICE_DRIVE_0_SERIAL_CODE_LENGTH];
|
||||
CHAR vendor[VENDOR_STRING_MAX_LENGTH];
|
||||
BOOLEAN virtualised_environment;
|
||||
ENVIRONMENT_TYPE environment;
|
||||
PROCESSOR_TYPE processor;
|
||||
RTL_OSVERSIONINFOW os_information;
|
||||
|
||||
} SYSTEM_INFORMATION, *PSYSTEM_INFORMATION;
|
||||
|
||||
typedef struct _OB_CALLBACKS_CONFIG
|
||||
{
|
||||
PVOID registration_handle;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} OB_CALLBACKS_CONFIG, *POB_CALLBACKS_CONFIG;
|
||||
|
||||
typedef struct _IRP_QUEUE_HEAD
|
||||
{
|
||||
SINGLE_LIST_ENTRY start;
|
||||
volatile INT count;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} IRP_QUEUE_HEAD, *PIRP_QUEUE_HEAD;
|
||||
|
||||
typedef struct _IRP_QUEUE_ENTRY
|
||||
{
|
||||
SINGLE_LIST_ENTRY entry;
|
||||
PIRP irp;
|
||||
|
||||
} IRP_QUEUE_ENTRY, *PIRP_QUEUE_ENTRY;
|
||||
#include "callbacks.h"
|
||||
|
||||
NTSTATUS
|
||||
ProcLoadInitialiseProcessConfig(_In_ PIRP Irp);
|
||||
|
@ -100,27 +23,6 @@ GetProtectedProcessId(_Out_ PLONG ProcessId);
|
|||
VOID
|
||||
ReadProcessInitialisedConfigFlag(_Out_ PBOOLEAN Flag);
|
||||
|
||||
VOID
|
||||
GetDriverPath(_Out_ PUNICODE_STRING DriverPath);
|
||||
|
||||
VOID
|
||||
GetDriverConfigSystemInformation(_Out_ PSYSTEM_INFORMATION* SystemInformation);
|
||||
|
||||
VOID
|
||||
GetApcContext(_Inout_ PVOID* Context, _In_ LONG ContextIdentifier);
|
||||
|
||||
VOID
|
||||
InsertApcContext(_In_ PVOID Context);
|
||||
|
||||
VOID
|
||||
GetApcContextByIndex(_Inout_ PVOID* Context, _In_ INT Index);
|
||||
|
||||
VOID
|
||||
IncrementApcCount(_In_ LONG ContextId);
|
||||
|
||||
VOID
|
||||
FreeApcAndDecrementApcCount(_Inout_ PRKAPC Apc, _In_ LONG ContextId);
|
||||
|
||||
NTSTATUS
|
||||
QueryActiveApcContextsForCompletion();
|
||||
|
||||
|
@ -139,30 +41,58 @@ ProcCloseClearProcessConfiguration();
|
|||
VOID
|
||||
GetCallbackConfigStructure(_Out_ POB_CALLBACKS_CONFIG* CallbackConfiguration);
|
||||
|
||||
VOID
|
||||
ImageLoadSetProcessId(_In_ HANDLE ProcessId);
|
||||
|
||||
VOID
|
||||
GetDriverDeviceName(_Out_ PUNICODE_STRING DeviceName);
|
||||
|
||||
VOID
|
||||
GetDriverRegistryPath(_Out_ PUNICODE_STRING RegistryPath);
|
||||
|
||||
VOID
|
||||
GetDriverName(_Out_ LPCSTR* DriverName);
|
||||
|
||||
VOID
|
||||
GetDriverSymbolicLink(_Out_ PUNICODE_STRING DeviceSymbolicLink);
|
||||
LPCSTR
|
||||
GetDriverName();
|
||||
|
||||
PDEVICE_OBJECT
|
||||
GetDriverDeviceObject();
|
||||
|
||||
GetSystemModuleValidationContext(_Out_ PSYS_MODULE_VAL_CONTEXT* Context);
|
||||
|
||||
PDRIVER_OBJECT
|
||||
GetDriverObject();
|
||||
|
||||
PIRP_QUEUE_HEAD
|
||||
GetIrpQueueHead();
|
||||
|
||||
PSYS_MODULE_VAL_CONTEXT
|
||||
GetSystemModuleValidationContext();
|
||||
|
||||
PUNICODE_STRING
|
||||
GetDriverPath();
|
||||
|
||||
PUNICODE_STRING
|
||||
GetDriverRegistryPath();
|
||||
|
||||
PUNICODE_STRING
|
||||
GetDriverDeviceName();
|
||||
|
||||
PUNICODE_STRING
|
||||
GetDriverSymbolicLink();
|
||||
|
||||
PSYSTEM_INFORMATION
|
||||
GetDriverConfigSystemInformation();
|
||||
|
||||
PREPORT_QUEUE_HEAD
|
||||
GetDriverReportQueue();
|
||||
|
||||
PTHREAD_LIST_HEAD
|
||||
GetThreadList();
|
||||
|
||||
PDRIVER_LIST_HEAD
|
||||
GetDriverList();
|
||||
|
||||
PPROCESS_LIST_HEAD
|
||||
GetProcessList();
|
||||
|
||||
PUINT64
|
||||
GetApcContextArray();
|
||||
|
||||
VOID
|
||||
AcquireDriverConfigLock();
|
||||
|
||||
VOID
|
||||
ReleaseDriverConfigLock();
|
||||
|
||||
BOOLEAN
|
||||
IsDriverUnloading();
|
||||
|
||||
#endif
|
|
@ -188,6 +188,7 @@
|
|||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="apc.c" />
|
||||
<ClCompile Include="callbacks.c" />
|
||||
<ClCompile Include="driver.c" />
|
||||
<ClCompile Include="hv.c" />
|
||||
|
@ -200,6 +201,7 @@
|
|||
<ClCompile Include="thread.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="apc.h" />
|
||||
<ClInclude Include="callbacks.h" />
|
||||
<ClInclude Include="common.h" />
|
||||
<ClInclude Include="driver.h" />
|
||||
|
|
|
@ -54,6 +54,9 @@
|
|||
<ClCompile Include="imports.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="apc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="driver.h">
|
||||
|
@ -92,6 +95,9 @@
|
|||
<ClInclude Include="imports.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="apc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="arch.asm">
|
||||
|
|
|
@ -101,7 +101,7 @@ FindNtExport(PCZPSTR ExportName)
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
ResolveNtImports()
|
||||
ResolveDynamicImports(_In_ PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ VOID
|
|||
FreeDriverImportsStructure();
|
||||
|
||||
NTSTATUS
|
||||
ResolveNtImports();
|
||||
ResolveDynamicImports(_In_ PDRIVER_OBJECT DriverObject);
|
||||
|
||||
#define IMPORT_FUNCTION_MAX_LENGTH 128
|
||||
#define IMPORT_FUNCTION_COUNT 256
|
||||
|
|
|
@ -117,18 +117,10 @@ GetDriverImageSize(_Inout_ PIRP Irp)
|
|||
PAGED_CODE();
|
||||
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
LPCSTR driver_name = NULL;
|
||||
LPCSTR driver_name = GetDriverName();
|
||||
SYSTEM_MODULES modules = {0};
|
||||
PRTL_MODULE_EXTENDED_INFO driver_info = NULL;
|
||||
|
||||
GetDriverName(&driver_name);
|
||||
|
||||
if (!driver_name)
|
||||
{
|
||||
DEBUG_ERROR("GetDriverName failed with no status.");
|
||||
return status;
|
||||
}
|
||||
|
||||
status = GetSystemModuleInformation(&modules);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
|
@ -172,18 +164,10 @@ GetModuleInformationByName(_Out_ PRTL_MODULE_EXTENDED_INFO ModuleInfo, _In_ LPCS
|
|||
PAGED_CODE();
|
||||
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
LPCSTR driver_name = NULL;
|
||||
LPCSTR driver_name = GetDriverName();
|
||||
SYSTEM_MODULES modules = {0};
|
||||
PRTL_MODULE_EXTENDED_INFO driver_info = NULL;
|
||||
|
||||
GetDriverName(&driver_name);
|
||||
|
||||
if (!driver_name)
|
||||
{
|
||||
DEBUG_ERROR("GetDriverName failed with no status.");
|
||||
return status;
|
||||
}
|
||||
|
||||
status = GetSystemModuleInformation(&modules);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
|
@ -562,18 +546,10 @@ RetrieveInMemoryModuleExecutableSections(_Inout_ PIRP Irp)
|
|||
PAGED_CODE();
|
||||
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
LPCSTR driver_name = NULL;
|
||||
SIZE_T bytes_written = NULL;
|
||||
PVOID buffer = NULL;
|
||||
RTL_MODULE_EXTENDED_INFO module_info = {0};
|
||||
|
||||
GetDriverName(&driver_name);
|
||||
|
||||
if (!driver_name)
|
||||
{
|
||||
DEBUG_ERROR("GetDriverName failed with no status");
|
||||
return status;
|
||||
}
|
||||
LPCSTR driver_name = GetDriverName();
|
||||
|
||||
status = GetModuleInformationByName(&module_info, driver_name);
|
||||
|
||||
|
@ -1570,22 +1546,13 @@ NTSTATUS
|
|||
ValidateOurDriverImage()
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
LPCSTR driver_name = NULL;
|
||||
UNICODE_STRING path = {0};
|
||||
SYSTEM_MODULES modules = {0};
|
||||
PRTL_MODULE_EXTENDED_INFO module_info = NULL;
|
||||
PVOID memory_hash = NULL;
|
||||
ULONG memory_hash_size = 0;
|
||||
PDRIVER_LIST_ENTRY entry = NULL;
|
||||
|
||||
GetDriverPath(&path);
|
||||
GetDriverName(&driver_name);
|
||||
|
||||
if (!driver_name)
|
||||
{
|
||||
DEBUG_ERROR("GetDriverName failed with no status");
|
||||
return status;
|
||||
}
|
||||
LPCSTR driver_name = GetDriverName();
|
||||
PUNICODE_STRING path = GetDriverPath();
|
||||
|
||||
status = GetSystemModuleInformation(&modules);
|
||||
|
||||
|
@ -1772,10 +1739,8 @@ NTSTATUS
|
|||
SystemModuleVerificationDispatcher()
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PSYS_MODULE_VAL_CONTEXT context = NULL;
|
||||
PIO_WORKITEM work_item = NULL;
|
||||
|
||||
GetSystemModuleValidationContext(&context);
|
||||
PSYS_MODULE_VAL_CONTEXT context = GetSystemModuleValidationContext();
|
||||
|
||||
if (context->complete)
|
||||
{
|
||||
|
|
|
@ -194,9 +194,8 @@ ValidateIrpInputBuffer(_In_ PIRP Irp, _In_ ULONG RequiredSize)
|
|||
|
||||
//_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
|
||||
NTSTATUS
|
||||
DeviceControl(_In_ PDRIVER_OBJECT DriverObject, _Inout_ PIRP Irp)
|
||||
DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(DriverObject);
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
|
|
@ -14,7 +14,7 @@ typedef struct _DRIVER_INITIATION_INFORMATION
|
|||
|
||||
//_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
|
||||
NTSTATUS
|
||||
DeviceControl(_In_ PDRIVER_OBJECT DriverObject, _Inout_ PIRP Irp);
|
||||
DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp);
|
||||
|
||||
_Dispatch_type_(IRP_MJ_CLOSE) NTSTATUS
|
||||
DeviceClose(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "ioctl.h"
|
||||
#include "ia32.h"
|
||||
#include "imports.h"
|
||||
|
||||
#include "apc.h"
|
||||
#include "thread.h"
|
||||
|
||||
#define WHITELISTED_MODULE_TAG 'whte'
|
||||
|
@ -139,7 +139,7 @@ AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules,
|
|||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
LaunchNonMaskableInterrupt(_Inout_ PNMI_CONTEXT NmiContext);
|
||||
LaunchNonMaskableInterrupt();
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
|
|
|
@ -11,55 +11,20 @@
|
|||
#include "common.h"
|
||||
#include "imports.h"
|
||||
|
||||
/*
|
||||
* This mutex is to prevent a new item being pushed to the queue
|
||||
* while the HandlePeriodicCallbackReportQueue is iterating through
|
||||
* the objects. This can be an issue because the spinlock is released
|
||||
* after each report is placed in the IRP buffer which means a new report
|
||||
* can be pushed into the queue before the next iteration can take ownership
|
||||
* of the spinlock.
|
||||
*/
|
||||
typedef struct _REPORT_QUEUE_CONFIGURATION
|
||||
{
|
||||
QUEUE_HEAD head;
|
||||
volatile BOOLEAN is_driver_unloading;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} REPORT_QUEUE_CONFIGURATION, *PREPORT_QUEUE_CONFIGURATION;
|
||||
|
||||
REPORT_QUEUE_CONFIGURATION report_queue_config = {0};
|
||||
|
||||
VOID
|
||||
InitialiseGlobalReportQueue(_Out_ PBOOLEAN Status)
|
||||
InitialiseGlobalReportQueue()
|
||||
{
|
||||
report_queue_config.head.start = NULL;
|
||||
report_queue_config.head.end = NULL;
|
||||
report_queue_config.head.entries = 0;
|
||||
report_queue_config.is_driver_unloading = FALSE;
|
||||
PREPORT_QUEUE_HEAD queue = GetDriverReportQueue();
|
||||
|
||||
ImpKeInitializeGuardedMutex(&report_queue_config.head.lock);
|
||||
ImpKeInitializeGuardedMutex(&report_queue_config.lock);
|
||||
queue->head.start = NULL;
|
||||
queue->head.end = NULL;
|
||||
queue->head.entries = 0;
|
||||
queue->is_driver_unloading = FALSE;
|
||||
|
||||
*Status = TRUE;
|
||||
ImpKeInitializeGuardedMutex(&queue->head.lock);
|
||||
ImpKeInitializeGuardedMutex(&queue->lock);
|
||||
}
|
||||
|
||||
// PQUEUE_HEAD QueueCreate()
|
||||
//{
|
||||
// PQUEUE_HEAD head = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( QUEUE_HEAD ),
|
||||
// QUEUE_POOL_TAG );
|
||||
//
|
||||
// if ( !head )
|
||||
// return NULL;
|
||||
//
|
||||
// head->end = NULL;
|
||||
// head->start = NULL;
|
||||
// head->entries = 0;
|
||||
//
|
||||
// KeInitializeSpinLock( &head->lock );
|
||||
//
|
||||
// return head;
|
||||
// }
|
||||
|
||||
VOID
|
||||
QueuePush(_Inout_ PQUEUE_HEAD Head, _In_ PVOID Data)
|
||||
{
|
||||
|
@ -115,33 +80,34 @@ end:
|
|||
VOID
|
||||
InsertReportToQueue(_In_ PVOID Report)
|
||||
{
|
||||
if (InterlockedExchange(&report_queue_config.is_driver_unloading,
|
||||
report_queue_config.is_driver_unloading))
|
||||
PREPORT_QUEUE_HEAD queue = GetDriverReportQueue();
|
||||
|
||||
if (InterlockedExchange(&queue->is_driver_unloading, queue->is_driver_unloading))
|
||||
return;
|
||||
|
||||
ImpKeAcquireGuardedMutex(&report_queue_config.lock);
|
||||
QueuePush(&report_queue_config.head, Report);
|
||||
ImpKeReleaseGuardedMutex(&report_queue_config.lock);
|
||||
ImpKeAcquireGuardedMutex(&queue->lock);
|
||||
QueuePush(&queue->head, Report);
|
||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
||||
}
|
||||
|
||||
VOID
|
||||
FreeGlobalReportQueueObjects()
|
||||
{
|
||||
InterlockedExchange(&report_queue_config.is_driver_unloading, TRUE);
|
||||
ImpKeAcquireGuardedMutex(&report_queue_config.lock);
|
||||
PREPORT_QUEUE_HEAD queue = GetDriverReportQueue();
|
||||
|
||||
PVOID report = QueuePop(&report_queue_config.head);
|
||||
InterlockedExchange(&queue->is_driver_unloading, TRUE);
|
||||
ImpKeAcquireGuardedMutex(&queue->lock);
|
||||
|
||||
while (report != NULL)
|
||||
PVOID report = QueuePop(&queue->head);
|
||||
|
||||
while (report)
|
||||
{
|
||||
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
|
||||
report = QueuePop(&report_queue_config.head);
|
||||
DEBUG_VERBOSE("Unloading report queue. Entries remaining: %i",
|
||||
report_queue_config.head.entries);
|
||||
report = QueuePop(&queue->head);
|
||||
}
|
||||
|
||||
end:
|
||||
ImpKeReleaseGuardedMutex(&report_queue_config.lock);
|
||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -153,7 +119,7 @@ end:
|
|||
* reports generated from ObRegisterCallbacks for example much easier.
|
||||
*/
|
||||
NTSTATUS
|
||||
HandlePeriodicGlobalReportQueueQuery(_Inout_ PIRP Irp)
|
||||
HandlePeriodicGlobalReportQueueQuery(_Out_ PIRP Irp)
|
||||
{
|
||||
INT count = 0;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
|
@ -163,8 +129,9 @@ HandlePeriodicGlobalReportQueueQuery(_Inout_ PIRP Irp)
|
|||
ULONG report_buffer_size = 0;
|
||||
PREPORT_HEADER report_header = NULL;
|
||||
GLOBAL_REPORT_QUEUE_HEADER header = {0};
|
||||
PREPORT_QUEUE_HEAD queue = GetDriverReportQueue();
|
||||
|
||||
ImpKeAcquireGuardedMutex(&report_queue_config.lock);
|
||||
ImpKeAcquireGuardedMutex(&queue->lock);
|
||||
|
||||
report_buffer_size = sizeof(INVALID_PROCESS_ALLOCATION_REPORT) * MAX_REPORTS_PER_IRP +
|
||||
sizeof(GLOBAL_REPORT_QUEUE_HEADER);
|
||||
|
@ -174,7 +141,7 @@ HandlePeriodicGlobalReportQueueQuery(_Inout_ PIRP Irp)
|
|||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("ValidateIrpOutputBuffer failed with status %x", status);
|
||||
ImpKeReleaseGuardedMutex(&report_queue_config.lock);
|
||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -183,11 +150,11 @@ HandlePeriodicGlobalReportQueueQuery(_Inout_ PIRP Irp)
|
|||
|
||||
if (!report_buffer)
|
||||
{
|
||||
ImpKeReleaseGuardedMutex(&report_queue_config.lock);
|
||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
|
||||
report = QueuePop(&report_queue_config.head);
|
||||
report = QueuePop(&queue->head);
|
||||
|
||||
if (report == NULL)
|
||||
{
|
||||
|
@ -278,13 +245,13 @@ HandlePeriodicGlobalReportQueueQuery(_Inout_ PIRP Irp)
|
|||
/* QueuePop frees the node, but we still need to free the returned data */
|
||||
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
|
||||
|
||||
report = QueuePop(&report_queue_config.head);
|
||||
report = QueuePop(&queue->head);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
ImpKeReleaseGuardedMutex(&report_queue_config.lock);
|
||||
ImpKeReleaseGuardedMutex(&queue->lock);
|
||||
|
||||
Irp->IoStatus.Information = sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size;
|
||||
header.count = count;
|
||||
|
|
|
@ -6,13 +6,6 @@
|
|||
|
||||
#define MAX_REPORTS_PER_IRP 20
|
||||
|
||||
typedef struct _QUEUE_NODE
|
||||
{
|
||||
struct _QUEUE_NODE* next;
|
||||
PVOID data;
|
||||
|
||||
} QUEUE_NODE, *PQUEUE_NODE;
|
||||
|
||||
typedef struct QUEUE_HEAD
|
||||
{
|
||||
struct _QUEUE_NODE* start;
|
||||
|
@ -22,6 +15,29 @@ typedef struct QUEUE_HEAD
|
|||
|
||||
} QUEUE_HEAD, *PQUEUE_HEAD;
|
||||
|
||||
/*
|
||||
* This mutex is to prevent a new item being pushed to the queue
|
||||
* while the HandlePeriodicCallbackReportQueue is iterating through
|
||||
* the objects. This can be an issue because the spinlock is released
|
||||
* after each report is placed in the IRP buffer which means a new report
|
||||
* can be pushed into the queue before the next iteration can take ownership
|
||||
* of the spinlock.
|
||||
*/
|
||||
typedef struct _REPORT_QUEUE_HEAD
|
||||
{
|
||||
QUEUE_HEAD head;
|
||||
volatile BOOLEAN is_driver_unloading;
|
||||
KGUARDED_MUTEX lock;
|
||||
|
||||
} REPORT_QUEUE_HEAD, *PREPORT_QUEUE_HEAD;
|
||||
|
||||
typedef struct _QUEUE_NODE
|
||||
{
|
||||
struct _QUEUE_NODE* next;
|
||||
PVOID data;
|
||||
|
||||
} QUEUE_NODE, *PQUEUE_NODE;
|
||||
|
||||
typedef struct _GLOBAL_REPORT_QUEUE_HEADER
|
||||
{
|
||||
INT count;
|
||||
|
@ -43,16 +59,16 @@ PVOID
|
|||
QueuePop(_Inout_ PQUEUE_HEAD Head);
|
||||
|
||||
VOID
|
||||
InitialiseGlobalReportQueue(_Out_ PBOOLEAN Status);
|
||||
InitialiseGlobalReportQueue();
|
||||
|
||||
VOID
|
||||
InsertReportToQueue(_In_ PVOID Report);
|
||||
|
||||
NTSTATUS
|
||||
HandlePeriodicGlobalReportQueueQuery(_Inout_ PIRP Irp);
|
||||
HandlePeriodicGlobalReportQueueQuery(_Out_ PIRP Irp);
|
||||
|
||||
VOID
|
||||
FreeGlobalReportQueueObjects();
|
||||
NTSTATUS
|
||||
HandlePeriodicGlobalReportQueueQuery(_Out_ PIRP Irp);
|
||||
|
||||
VOID
|
||||
ListInit(_Inout_ PSINGLE_LIST_ENTRY Head, _Inout_ PKGUARDED_MUTEX Lock);
|
||||
|
@ -72,4 +88,7 @@ ListRemoveEntry(_Inout_ PSINGLE_LIST_ENTRY Head,
|
|||
_Inout_ PSINGLE_LIST_ENTRY Entry,
|
||||
_In_ PKGUARDED_MUTEX Lock);
|
||||
|
||||
VOID
|
||||
FreeGlobalReportQueueObjects();
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue