This commit is contained in:
donnaskiez 2024-08-01 14:21:53 +10:00
parent 18109448bc
commit 197796d004
18 changed files with 2130 additions and 1836 deletions

View file

@ -1,9 +1,9 @@
BasedOnStyle: webkit BasedOnStyle: webkit
AccessModifierOffset: -4 AccessModifierOffset: -4
AlignAfterOpenBracket: Align AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: true AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: true AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true AlignConsecutiveMacros: true
@ -73,7 +73,7 @@ MaxEmptyLinesToKeep: 1
NamespaceIndentation: None #All NamespaceIndentation: None #All
PointerAlignment: Left PointerAlignment: Left
ReflowComments: true ReflowComments: true
SortIncludes: false SortIncludes: true
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true

View file

@ -137,7 +137,8 @@ QueryActiveApcContextsForCompletion()
switch (entry->context_id) { switch (entry->context_id) {
case APC_CONTEXT_ID_STACKWALK: case APC_CONTEXT_ID_STACKWALK:
FreeApcStackwalkApcContextInformation((PAPC_STACKWALK_CONTEXT)entry); FreeApcStackwalkApcContextInformation(
(PAPC_STACKWALK_CONTEXT)entry);
FreeApcContextStructure(entry); FreeApcContextStructure(entry);
break; break;
} }

View file

@ -2,27 +2,28 @@
#include "driver.h" #include "driver.h"
#include "pool.h"
#include "thread.h"
#include "modules.h"
#include "imports.h"
#include "session.h"
#include "crypt.h" #include "crypt.h"
#include "imports.h"
#include "modules.h"
#include "pool.h"
#include "session.h"
#include "thread.h"
#include "util.h" #include "util.h"
#include "lib/stdlib.h" #include "lib/stdlib.h"
#include "containers/tree.h"
#include "containers/map.h" #include "containers/map.h"
#include "containers/tree.h"
#define PROCESS_HASHMAP_BUCKET_COUNT 101 #define PROCESS_HASHMAP_BUCKET_COUNT 101
STATIC STATIC
BOOLEAN BOOLEAN
EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable, EnumHandleCallback(
_In_ PHANDLE_TABLE_ENTRY Entry, _In_ PHANDLE_TABLE HandleTable,
_In_ HANDLE Handle, _In_ PHANDLE_TABLE_ENTRY Entry,
_In_ PVOID Context); _In_ HANDLE Handle,
_In_ PVOID Context);
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
# pragma alloc_text(PAGE, ObPostOpCallbackRoutine) # pragma alloc_text(PAGE, ObPostOpCallbackRoutine)
@ -75,15 +76,15 @@ CleanupThreadListOnDriverUnload()
VOID VOID
CleanupDriverListOnDriverUnload() CleanupDriverListOnDriverUnload()
{ {
PDRIVER_LIST_HEAD head = GetDriverList(); PDRIVER_LIST_HEAD head = GetDriverList();
PLIST_ENTRY entry = NULL; PLIST_ENTRY entry = NULL;
PDRIVER_LIST_ENTRY driver = NULL;
ImpKeAcquireGuardedMutex(&head->lock); ImpKeAcquireGuardedMutex(&head->lock);
while (!IsListEmpty(&head->list_entry)) { while (!IsListEmpty(&head->list_entry)) {
entry = RemoveHeadList(&head->list_entry); entry = RemoveHeadList(&head->list_entry);
PDRIVER_LIST_ENTRY driverEntry = driver = CONTAINING_RECORD(entry, DRIVER_LIST_ENTRY, list_entry);
CONTAINING_RECORD(entry, DRIVER_LIST_ENTRY, list_entry);
ExFreePoolWithTag(entry, POOL_TAG_DRIVER_LIST); ExFreePoolWithTag(entry, POOL_TAG_DRIVER_LIST);
} }
@ -94,8 +95,8 @@ VOID
EnumerateDriverListWithCallbackRoutine( EnumerateDriverListWithCallbackRoutine(
_In_ DRIVERLIST_CALLBACK_ROUTINE CallbackRoutine, _In_opt_ PVOID Context) _In_ DRIVERLIST_CALLBACK_ROUTINE CallbackRoutine, _In_opt_ PVOID Context)
{ {
PDRIVER_LIST_HEAD head = GetDriverList(); PDRIVER_LIST_HEAD head = GetDriverList();
PLIST_ENTRY list_entry = NULL; PLIST_ENTRY list_entry = NULL;
PDRIVER_LIST_ENTRY driver_entry = NULL; PDRIVER_LIST_ENTRY driver_entry = NULL;
ImpKeAcquireGuardedMutex(&head->lock); ImpKeAcquireGuardedMutex(&head->lock);
@ -114,13 +115,15 @@ EnumerateDriverListWithCallbackRoutine(
} }
VOID VOID
DriverListEntryToExtendedModuleInfo(_In_ PDRIVER_LIST_ENTRY Entry, DriverListEntryToExtendedModuleInfo(
_Out_ PRTL_MODULE_EXTENDED_INFO Extended) _In_ PDRIVER_LIST_ENTRY Entry, _Out_ PRTL_MODULE_EXTENDED_INFO Extended)
{ {
Extended->ImageBase = Entry->ImageBase; Extended->ImageBase = Entry->ImageBase;
Extended->ImageSize = Entry->ImageSize; Extended->ImageSize = Entry->ImageSize;
IntCopyMemory( IntCopyMemory(
Extended->FullPathName, Entry->path, sizeof(Extended->FullPathName)); Extended->FullPathName,
Entry->path,
sizeof(Extended->FullPathName));
} }
NTSTATUS NTSTATUS
@ -128,11 +131,11 @@ InitialiseDriverList()
{ {
PAGED_CODE(); PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
SYSTEM_MODULES modules = {0}; SYSTEM_MODULES modules = {0};
PDRIVER_LIST_ENTRY entry = NULL; PDRIVER_LIST_ENTRY entry = NULL;
PRTL_MODULE_EXTENDED_INFO module_entry = NULL; PRTL_MODULE_EXTENDED_INFO module_entry = NULL;
PDRIVER_LIST_HEAD head = GetDriverList(); PDRIVER_LIST_HEAD head = GetDriverList();
InterlockedExchange(&head->active, TRUE); InterlockedExchange(&head->active, TRUE);
InitializeListHead(&head->list_entry); InitializeListHead(&head->list_entry);
@ -140,7 +143,7 @@ InitialiseDriverList()
KeInitializeGuardedMutex(&head->lock); KeInitializeGuardedMutex(&head->lock);
head->can_hash_x86 = FALSE; head->can_hash_x86 = FALSE;
head->work_item = IoAllocateWorkItem(GetDriverDeviceObject()); head->work_item = IoAllocateWorkItem(GetDriverDeviceObject());
if (!head->work_item) if (!head->work_item)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
@ -156,30 +159,33 @@ InitialiseDriverList()
/* skip hal.dll and ntoskrnl.exe */ /* skip hal.dll and ntoskrnl.exe */
for (UINT32 index = 2; index < modules.module_count; index++) { for (UINT32 index = 2; index < modules.module_count; index++) {
entry = ImpExAllocatePool2(POOL_FLAG_NON_PAGED, entry = ImpExAllocatePool2(
sizeof(DRIVER_LIST_ENTRY), POOL_FLAG_NON_PAGED,
POOL_TAG_DRIVER_LIST); sizeof(DRIVER_LIST_ENTRY),
POOL_TAG_DRIVER_LIST);
if (!entry) if (!entry)
continue; continue;
module_entry = &((PRTL_MODULE_EXTENDED_INFO)modules.address)[index]; module_entry = &((PRTL_MODULE_EXTENDED_INFO)modules.address)[index];
entry->hashed = TRUE; entry->hashed = TRUE;
entry->ImageBase = module_entry->ImageBase; entry->ImageBase = module_entry->ImageBase;
entry->ImageSize = module_entry->ImageSize; entry->ImageSize = module_entry->ImageSize;
IntCopyMemory(entry->path, IntCopyMemory(
module_entry->FullPathName, entry->path,
sizeof(module_entry->FullPathName)); module_entry->FullPathName,
sizeof(module_entry->FullPathName));
status = HashModule(module_entry, entry->text_hash); status = HashModule(module_entry, entry->text_hash);
if (status == STATUS_INVALID_IMAGE_WIN_32) { if (status == STATUS_INVALID_IMAGE_WIN_32) {
DEBUG_ERROR("32 bit module not hashed, will hash later. %x", DEBUG_ERROR(
status); "32 bit module not hashed, will hash later. %x",
status);
entry->hashed = FALSE; entry->hashed = FALSE;
entry->x86 = TRUE; entry->x86 = TRUE;
InsertHeadList(&head->deferred_list, &entry->deferred_entry); InsertHeadList(&head->deferred_list, &entry->deferred_entry);
} }
else if (!NT_SUCCESS(status)) { else if (!NT_SUCCESS(status)) {
@ -206,11 +212,11 @@ InitialiseDriverList()
* think! * think!
*/ */
VOID VOID
FindDriverEntryByBaseAddress(_In_ PVOID ImageBase, FindDriverEntryByBaseAddress(
_Out_ PDRIVER_LIST_ENTRY* Entry) _In_ PVOID ImageBase, _Out_ PDRIVER_LIST_ENTRY* Entry)
{ {
PDRIVER_LIST_HEAD head = GetDriverList(); PDRIVER_LIST_HEAD head = GetDriverList();
PLIST_ENTRY list_entry = NULL; PLIST_ENTRY list_entry = NULL;
PDRIVER_LIST_ENTRY driver_entry = NULL; PDRIVER_LIST_ENTRY driver_entry = NULL;
ImpKeAcquireGuardedMutex(&head->lock); ImpKeAcquireGuardedMutex(&head->lock);
@ -253,17 +259,17 @@ ProcessHashmapHashFunction(_In_ UINT64 Key)
STATIC STATIC
VOID VOID
ImageLoadInsertNonSystemImageIntoProcessHashmap(_In_ PIMAGE_INFO ImageInfo, ImageLoadInsertNonSystemImageIntoProcessHashmap(
_In_ HANDLE ProcessId, _In_ PIMAGE_INFO ImageInfo,
_In_opt_ PUNICODE_STRING _In_ HANDLE ProcessId,
FullImageName) _In_opt_ PUNICODE_STRING FullImageName)
{ {
INT32 index = 0; INT32 index = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS process = NULL; PEPROCESS process = NULL;
PRTL_HASHMAP map = GetProcessHashmap(); PRTL_HASHMAP map = GetProcessHashmap();
PPROCESS_LIST_ENTRY entry = NULL; PPROCESS_LIST_ENTRY entry = NULL;
PPROCESS_MAP_MODULE_ENTRY module = NULL; PPROCESS_MAP_MODULE_ENTRY module = NULL;
PPROCESS_MODULE_MAP_CONTEXT context = NULL; PPROCESS_MODULE_MAP_CONTEXT context = NULL;
if (!map->active) if (!map->active)
@ -288,7 +294,7 @@ ImageLoadInsertNonSystemImageIntoProcessHashmap(_In_ PIMAGE_INFO ImageInfo,
} }
context = (PPROCESS_MODULE_MAP_CONTEXT)map->context; context = (PPROCESS_MODULE_MAP_CONTEXT)map->context;
module = ExAllocateFromLookasideListEx(&context->pool); module = ExAllocateFromLookasideListEx(&context->pool);
if (!module) if (!module)
goto end; goto end;
@ -303,7 +309,9 @@ ImageLoadInsertNonSystemImageIntoProcessHashmap(_In_ PIMAGE_INFO ImageInfo,
*/ */
if (FullImageName) if (FullImageName)
UnicodeToCharBufString( UnicodeToCharBufString(
FullImageName, module->path, sizeof(module->path)); FullImageName,
module->path,
sizeof(module->path));
InsertTailList(&entry->module_list, &module->entry); InsertTailList(&entry->module_list, &module->entry);
entry->list_count++; entry->list_count++;
@ -313,24 +321,27 @@ end:
} }
VOID VOID
ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName, ImageLoadNotifyRoutineCallback(
_In_ HANDLE ProcessId, _In_opt_ PUNICODE_STRING FullImageName,
_In_ PIMAGE_INFO ImageInfo) _In_ HANDLE ProcessId,
_In_ PIMAGE_INFO ImageInfo)
{ {
UNREFERENCED_PARAMETER(ProcessId); UNREFERENCED_PARAMETER(ProcessId);
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PDRIVER_LIST_ENTRY entry = NULL; PDRIVER_LIST_ENTRY entry = NULL;
RTL_MODULE_EXTENDED_INFO module = {0}; RTL_MODULE_EXTENDED_INFO module = {0};
PDRIVER_LIST_HEAD head = GetDriverList(); PDRIVER_LIST_HEAD head = GetDriverList();
ANSI_STRING ansi_path = {0}; ANSI_STRING ansi_path = {0};
if (InterlockedExchange(&head->active, head->active) == FALSE) if (InterlockedExchange(&head->active, head->active) == FALSE)
return; return;
if (ImageInfo->SystemModeImage == FALSE) { if (ImageInfo->SystemModeImage == FALSE) {
ImageLoadInsertNonSystemImageIntoProcessHashmap( ImageLoadInsertNonSystemImageIntoProcessHashmap(
ImageInfo, ProcessId, FullImageName); ImageInfo,
ProcessId,
FullImageName);
return; return;
} }
@ -341,13 +352,15 @@ ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName,
return; return;
entry = ExAllocatePool2( entry = ExAllocatePool2(
POOL_FLAG_NON_PAGED, sizeof(DRIVER_LIST_ENTRY), POOL_TAG_DRIVER_LIST); POOL_FLAG_NON_PAGED,
sizeof(DRIVER_LIST_ENTRY),
POOL_TAG_DRIVER_LIST);
if (!entry) if (!entry)
return; return;
entry->hashed = TRUE; entry->hashed = TRUE;
entry->x86 = FALSE; entry->x86 = FALSE;
entry->ImageBase = ImageInfo->ImageBase; entry->ImageBase = ImageInfo->ImageBase;
entry->ImageSize = ImageInfo->ImageSize; entry->ImageSize = ImageInfo->ImageSize;
@ -356,9 +369,13 @@ ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName,
if (FullImageName) { if (FullImageName) {
UnicodeToCharBufString( UnicodeToCharBufString(
FullImageName, module.FullPathName, sizeof(module.FullPathName)); FullImageName,
module.FullPathName,
sizeof(module.FullPathName));
IntCopyMemory( IntCopyMemory(
entry->path, module.FullPathName, sizeof(module.FullPathName)); entry->path,
module.FullPathName,
sizeof(module.FullPathName));
} }
DEBUG_VERBOSE("New system image ansi: %s", entry->path); DEBUG_VERBOSE("New system image ansi: %s", entry->path);
@ -368,7 +385,7 @@ hash:
if (status == STATUS_INVALID_IMAGE_WIN_32) { if (status == STATUS_INVALID_IMAGE_WIN_32) {
DEBUG_ERROR("32 bit module not hashed, will hash later. %x", status); DEBUG_ERROR("32 bit module not hashed, will hash later. %x", status);
entry->x86 = TRUE; entry->x86 = TRUE;
entry->hashed = FALSE; entry->hashed = FALSE;
} }
else if (!NT_SUCCESS(status)) { else if (!NT_SUCCESS(status)) {
@ -383,18 +400,18 @@ hash:
/* assumes map lock is held */ /* assumes map lock is held */
VOID VOID
FreeProcessEntryModuleList(_In_ PPROCESS_LIST_ENTRY Entry, FreeProcessEntryModuleList(
_In_opt_ PVOID Context) _In_ PPROCESS_LIST_ENTRY Entry, _In_opt_ PVOID Context)
{ {
UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(Context);
PRTL_HASHMAP map = GetProcessHashmap(); PRTL_HASHMAP map = GetProcessHashmap();
PLIST_ENTRY list = NULL; PLIST_ENTRY list = NULL;
PPROCESS_MAP_MODULE_ENTRY list_entry = NULL; PPROCESS_MAP_MODULE_ENTRY list_entry = NULL;
PPROCESS_MODULE_MAP_CONTEXT context = map->context; PPROCESS_MODULE_MAP_CONTEXT context = map->context;
while (!IsListEmpty(&Entry->module_list)) { while (!IsListEmpty(&Entry->module_list)) {
list = RemoveTailList(&Entry->module_list); list = RemoveTailList(&Entry->module_list);
list_entry = CONTAINING_RECORD(list, PROCESS_MAP_MODULE_ENTRY, entry); list_entry = CONTAINING_RECORD(list, PROCESS_MAP_MODULE_ENTRY, entry);
ExFreeToLookasideListEx(&context->pool, list_entry); ExFreeToLookasideListEx(&context->pool, list_entry);
@ -402,15 +419,16 @@ FreeProcessEntryModuleList(_In_ PPROCESS_LIST_ENTRY Entry,
} }
VOID VOID
EnumerateProcessModuleList(_In_ HANDLE ProcessId, EnumerateProcessModuleList(
_In_ PROCESS_MODULE_CALLBACK Callback, _In_ HANDLE ProcessId,
_In_opt_ PVOID Context) _In_ PROCESS_MODULE_CALLBACK Callback,
_In_opt_ PVOID Context)
{ {
INT32 index = 0; INT32 index = 0;
PRTL_HASHMAP map = GetProcessHashmap(); PRTL_HASHMAP map = GetProcessHashmap();
BOOLEAN ret = FALSE; BOOLEAN ret = FALSE;
PPROCESS_LIST_ENTRY entry = NULL; PPROCESS_LIST_ENTRY entry = NULL;
PLIST_ENTRY list = NULL; PLIST_ENTRY list = NULL;
PPROCESS_MAP_MODULE_ENTRY module = NULL; PPROCESS_MAP_MODULE_ENTRY module = NULL;
if (!map->active) if (!map->active)
@ -439,15 +457,15 @@ end:
} }
VOID VOID
FindOurUserModeModuleEntry(_In_ PROCESS_MODULE_CALLBACK Callback, FindOurUserModeModuleEntry(
_In_opt_ PVOID Context) _In_ PROCESS_MODULE_CALLBACK Callback, _In_opt_ PVOID Context)
{ {
INT32 index = 0; INT32 index = 0;
PRTL_HASHMAP map = GetProcessHashmap(); PRTL_HASHMAP map = GetProcessHashmap();
PPROCESS_LIST_ENTRY entry = NULL; PPROCESS_LIST_ENTRY entry = NULL;
PACTIVE_SESSION session = GetActiveSession(); PACTIVE_SESSION session = GetActiveSession();
PLIST_ENTRY list = NULL; PLIST_ENTRY list = NULL;
PPROCESS_MAP_MODULE_ENTRY module = NULL; PPROCESS_MAP_MODULE_ENTRY module = NULL;
if (!map->active) if (!map->active)
return; return;
@ -480,10 +498,10 @@ end:
VOID VOID
CleanupProcessHashmap() CleanupProcessHashmap()
{ {
PRTL_HASHMAP map = GetProcessHashmap(); PRTL_HASHMAP map = GetProcessHashmap();
PRTL_HASHMAP_ENTRY entry = NULL; PRTL_HASHMAP_ENTRY entry = NULL;
PRTL_HASHMAP_ENTRY temp = NULL; PRTL_HASHMAP_ENTRY temp = NULL;
PLIST_ENTRY list = NULL; PLIST_ENTRY list = NULL;
PPROCESS_MODULE_MAP_CONTEXT context = NULL; PPROCESS_MODULE_MAP_CONTEXT context = NULL;
RtlHashmapSetInactive(map); RtlHashmapSetInactive(map);
@ -517,36 +535,39 @@ InitialiseProcessHashmap()
{ {
PAGED_CODE(); PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PPROCESS_MODULE_MAP_CONTEXT context = NULL; PPROCESS_MODULE_MAP_CONTEXT context = NULL;
context = ExAllocatePool2(POOL_FLAG_NON_PAGED, context = ExAllocatePool2(
sizeof(PROCESS_MODULE_MAP_CONTEXT), POOL_FLAG_NON_PAGED,
POOL_TAG_HASHMAP); sizeof(PROCESS_MODULE_MAP_CONTEXT),
POOL_TAG_HASHMAP);
if (!context) if (!context)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
status = ExInitializeLookasideListEx(&context->pool, status = ExInitializeLookasideListEx(
NULL, &context->pool,
NULL, NULL,
NonPagedPoolNx, NULL,
0, NonPagedPoolNx,
sizeof(PROCESS_MAP_MODULE_ENTRY), 0,
POOL_TAG_MODULE_LIST, sizeof(PROCESS_MAP_MODULE_ENTRY),
0); POOL_TAG_MODULE_LIST,
0);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
ExFreePoolWithTag(context, POOL_TAG_HASHMAP); ExFreePoolWithTag(context, POOL_TAG_HASHMAP);
return status; return status;
} }
status = RtlHashmapCreate(PROCESS_HASHMAP_BUCKET_COUNT, status = RtlHashmapCreate(
sizeof(PROCESS_LIST_ENTRY), PROCESS_HASHMAP_BUCKET_COUNT,
ProcessHashmapHashFunction, sizeof(PROCESS_LIST_ENTRY),
ProcessHashmapCompareFunction, ProcessHashmapHashFunction,
context, ProcessHashmapCompareFunction,
GetProcessHashmap()); context,
GetProcessHashmap());
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("RtlCreateHashmap: %lx", status); DEBUG_ERROR("RtlCreateHashmap: %lx", status);
@ -577,7 +598,7 @@ NTSTATUS
InitialiseThreadList() InitialiseThreadList()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PRB_TREE tree = GetThreadTree(); PRB_TREE tree = GetThreadTree();
status = status =
RtlRbTreeCreate(ThreadListTreeCompare, sizeof(THREAD_LIST_ENTRY), tree); RtlRbTreeCreate(ThreadListTreeCompare, sizeof(THREAD_LIST_ENTRY), tree);
@ -590,8 +611,8 @@ InitialiseThreadList()
} }
VOID VOID
FindThreadListEntryByThreadAddress(_In_ HANDLE ThreadId, FindThreadListEntryByThreadAddress(
_Out_ PTHREAD_LIST_ENTRY* Entry) _In_ HANDLE ThreadId, _Out_ PTHREAD_LIST_ENTRY* Entry)
{ {
PRB_TREE tree = GetThreadTree(); PRB_TREE tree = GetThreadTree();
RtlRbTreeAcquireLock(tree); RtlRbTreeAcquireLock(tree);
@ -604,8 +625,9 @@ STATIC
BOOLEAN BOOLEAN
CanInitiateDeferredHashing(_In_ LPCSTR ProcessName, _In_ PDRIVER_LIST_HEAD Head) CanInitiateDeferredHashing(_In_ LPCSTR ProcessName, _In_ PDRIVER_LIST_HEAD Head)
{ {
return !IntCompareString(ProcessName, "winlogon.exe") && Head->work_item ? TRUE return !IntCompareString(ProcessName, "winlogon.exe") && Head->work_item
: FALSE; ? TRUE
: FALSE;
} }
STATIC STATIC
@ -613,7 +635,7 @@ VOID
PrintHashmapCallback(_In_ PPROCESS_LIST_ENTRY Entry, _In_opt_ PVOID Context) PrintHashmapCallback(_In_ PPROCESS_LIST_ENTRY Entry, _In_opt_ PVOID Context)
{ {
PPROCESS_MAP_MODULE_ENTRY module = NULL; PPROCESS_MAP_MODULE_ENTRY module = NULL;
PLIST_ENTRY list = NULL; PLIST_ENTRY list = NULL;
UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(Context);
DEBUG_VERBOSE("Process ID: %p", Entry->process_id); DEBUG_VERBOSE("Process ID: %p", Entry->process_id);
@ -621,10 +643,11 @@ PrintHashmapCallback(_In_ PPROCESS_LIST_ENTRY Entry, _In_opt_ PVOID Context)
for (list = Entry->module_list.Flink; list != &Entry->module_list; for (list = Entry->module_list.Flink; list != &Entry->module_list;
list = list->Flink) { list = list->Flink) {
module = CONTAINING_RECORD(list, PROCESS_MAP_MODULE_ENTRY, entry); module = CONTAINING_RECORD(list, PROCESS_MAP_MODULE_ENTRY, entry);
DEBUG_VERBOSE(" -> Module Base: %p, size: %lx, path: %s", DEBUG_VERBOSE(
(PVOID)module->base, " -> Module Base: %p, size: %lx, path: %s",
module->size, (PVOID)module->base,
module->path); module->size,
module->path);
} }
} }
@ -635,17 +658,16 @@ EnumerateAndPrintProcessHashmap()
} }
VOID VOID
ProcessCreateNotifyRoutine(_In_ HANDLE ParentId, ProcessCreateNotifyRoutine(
_In_ HANDLE ProcessId, _In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOOLEAN Create)
_In_ BOOLEAN Create)
{ {
INT32 index = 0; INT32 index = 0;
PKPROCESS parent = NULL; PKPROCESS parent = NULL;
PKPROCESS process = NULL; PKPROCESS process = NULL;
PDRIVER_LIST_HEAD driver_list = GetDriverList(); PDRIVER_LIST_HEAD driver_list = GetDriverList();
LPCSTR process_name = NULL; LPCSTR process_name = NULL;
PRTL_HASHMAP map = GetProcessHashmap(); PRTL_HASHMAP map = GetProcessHashmap();
PPROCESS_LIST_ENTRY entry = NULL; PPROCESS_LIST_ENTRY entry = NULL;
if (!map->active) if (!map->active)
return; return;
@ -657,7 +679,7 @@ ProcessCreateNotifyRoutine(_In_ HANDLE ParentId,
return; return;
process_name = ImpPsGetProcessImageFileName(process); process_name = ImpPsGetProcessImageFileName(process);
index = RtlHashmapHashKeyAndAcquireBucket(map, ProcessId); index = RtlHashmapHashKeyAndAcquireBucket(map, ProcessId);
if (index == STATUS_INVALID_HASHMAP_INDEX) if (index == STATUS_INVALID_HASHMAP_INDEX)
return; return;
@ -669,8 +691,8 @@ ProcessCreateNotifyRoutine(_In_ HANDLE ParentId,
goto end; goto end;
entry->process_id = ProcessId; entry->process_id = ProcessId;
entry->process = process; entry->process = process;
entry->parent = parent; entry->parent = parent;
InitializeListHead(&entry->module_list); InitializeListHead(&entry->module_list);
@ -681,10 +703,11 @@ ProcessCreateNotifyRoutine(_In_ HANDLE ParentId,
* any x86 modules that werent hashed. * any x86 modules that werent hashed.
*/ */
if (CanInitiateDeferredHashing(process_name, driver_list)) { if (CanInitiateDeferredHashing(process_name, driver_list)) {
IoQueueWorkItem(driver_list->work_item, IoQueueWorkItem(
DeferredModuleHashingCallback, driver_list->work_item,
NormalWorkQueue, DeferredModuleHashingCallback,
NULL); NormalWorkQueue,
NULL);
} }
} }
else { else {
@ -707,14 +730,13 @@ end:
} }
VOID VOID
ThreadCreateNotifyRoutine(_In_ HANDLE ProcessId, ThreadCreateNotifyRoutine(
_In_ HANDLE ThreadId, _In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ BOOLEAN Create)
_In_ BOOLEAN Create)
{ {
PTHREAD_LIST_ENTRY entry = NULL; PTHREAD_LIST_ENTRY entry = NULL;
PKTHREAD thread = NULL; PKTHREAD thread = NULL;
PKPROCESS process = NULL; PKPROCESS process = NULL;
PRB_TREE tree = GetThreadTree(); PRB_TREE tree = GetThreadTree();
/* ensure we don't insert new entries if we are unloading */ /* ensure we don't insert new entries if we are unloading */
if (!tree->active) if (!tree->active)
@ -736,11 +758,11 @@ ThreadCreateNotifyRoutine(_In_ HANDLE ProcessId,
if (!entry) if (!entry)
goto end; goto end;
entry->thread_id = ThreadId; entry->thread_id = ThreadId;
entry->thread = thread; entry->thread = thread;
entry->owning_process = process; entry->owning_process = process;
entry->apc = NULL; entry->apc = NULL;
entry->apc_queued = FALSE; entry->apc_queued = FALSE;
} }
else { else {
entry = RtlRbTreeFindNodeObject(tree, &ThreadId); entry = RtlRbTreeFindNodeObject(tree, &ThreadId);
@ -759,9 +781,9 @@ end:
} }
VOID VOID
ObPostOpCallbackRoutine(_In_ PVOID RegistrationContext, ObPostOpCallbackRoutine(
_In_ POB_POST_OPERATION_INFORMATION _In_ PVOID RegistrationContext,
OperationInformation) _In_ POB_POST_OPERATION_INFORMATION OperationInformation)
{ {
PAGED_CODE(); PAGED_CODE();
UNREFERENCED_PARAMETER(RegistrationContext); UNREFERENCED_PARAMETER(RegistrationContext);
@ -777,17 +799,19 @@ ObPostOpCallbackRoutine(_In_ PVOID RegistrationContext,
#define DOWNGRADE_MSMPENG 3 #define DOWNGRADE_MSMPENG 3
CHAR PROCESS_HANDLE_OPEN_DOWNGRADE[PROCESS_HANDLE_OPEN_DOWNGRADE_COUNT] CHAR PROCESS_HANDLE_OPEN_DOWNGRADE[PROCESS_HANDLE_OPEN_DOWNGRADE_COUNT]
[MAX_PROCESS_NAME_LENGTH] = {"lsass.exe", [MAX_PROCESS_NAME_LENGTH] = {
"csrss.exe", "lsass.exe",
"WerFault.exe", "csrss.exe",
"MsMpEng.exe"}; "WerFault.exe",
"MsMpEng.exe"};
#define PROCESS_HANDLE_OPEN_WHITELIST_COUNT 3 #define PROCESS_HANDLE_OPEN_WHITELIST_COUNT 3
CHAR PROCESS_HANDLE_OPEN_WHITELIST[PROCESS_HANDLE_OPEN_WHITELIST_COUNT] CHAR PROCESS_HANDLE_OPEN_WHITELIST[PROCESS_HANDLE_OPEN_WHITELIST_COUNT]
[MAX_PROCESS_NAME_LENGTH] = {"Discord.exe", [MAX_PROCESS_NAME_LENGTH] = {
"svchost.exe", "Discord.exe",
"explorer.exe"}; "svchost.exe",
"explorer.exe"};
STATIC STATIC
BOOLEAN BOOLEAN
@ -795,7 +819,9 @@ IsWhitelistedHandleOpenProcess(_In_ LPCSTR ProcessName)
{ {
for (UINT32 index = 0; index < PROCESS_HANDLE_OPEN_WHITELIST_COUNT; for (UINT32 index = 0; index < PROCESS_HANDLE_OPEN_WHITELIST_COUNT;
index++) { index++) {
if (!IntCompareString(ProcessName, PROCESS_HANDLE_OPEN_WHITELIST[index])) if (!IntCompareString(
ProcessName,
PROCESS_HANDLE_OPEN_WHITELIST[index]))
return TRUE; return TRUE;
} }
@ -808,7 +834,9 @@ IsDowngradeHandleOpenProcess(_In_ LPCSTR ProcessName)
{ {
for (UINT32 index = 0; index < PROCESS_HANDLE_OPEN_DOWNGRADE_COUNT; for (UINT32 index = 0; index < PROCESS_HANDLE_OPEN_DOWNGRADE_COUNT;
index++) { index++) {
if (!IntCompareString(ProcessName, PROCESS_HANDLE_OPEN_DOWNGRADE[index])) if (!IntCompareString(
ProcessName,
PROCESS_HANDLE_OPEN_DOWNGRADE[index]))
return TRUE; return TRUE;
} }
@ -819,8 +847,9 @@ IsDowngradeHandleOpenProcess(_In_ LPCSTR ProcessName)
#define GET_OBJECT_HEADER_FROM_HANDLE(x) ((x << 4) | 0xffff000000000000); #define GET_OBJECT_HEADER_FROM_HANDLE(x) ((x << 4) | 0xffff000000000000);
OB_PREOP_CALLBACK_STATUS OB_PREOP_CALLBACK_STATUS
ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext, ObPreOpCallbackRoutine(
_In_ POB_PRE_OPERATION_INFORMATION OperationInformation) _In_ PVOID RegistrationContext,
_In_ POB_PRE_OPERATION_INFORMATION OperationInformation)
{ {
PAGED_CODE(); PAGED_CODE();
@ -833,17 +862,17 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
* This callback routine is executed in the context of the thread that * This callback routine is executed in the context of the thread that
* is requesting to open said handle * is requesting to open said handle
*/ */
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS process_creator = PsGetCurrentProcess(); PEPROCESS process_creator = PsGetCurrentProcess();
PEPROCESS protected_process = NULL; PEPROCESS protected_process = NULL;
PEPROCESS target_process = (PEPROCESS)OperationInformation->Object; PEPROCESS target_process = (PEPROCESS)OperationInformation->Object;
HANDLE process_creator_id = ImpPsGetProcessId(process_creator); HANDLE process_creator_id = ImpPsGetProcessId(process_creator);
LONG protected_process_id = 0; LONG protected_process_id = 0;
LPCSTR process_creator_name = NULL; LPCSTR process_creator_name = NULL;
LPCSTR target_process_name = NULL; LPCSTR target_process_name = NULL;
LPCSTR protected_process_name = NULL; LPCSTR protected_process_name = NULL;
POB_CALLBACKS_CONFIG configuration = NULL; POB_CALLBACKS_CONFIG configuration = NULL;
UINT32 report_size = 0; UINT32 report_size = 0;
/* /*
* This is to prevent the condition where the thread executing this * This is to prevent the condition where the thread executing this
@ -863,8 +892,8 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
if (!protected_process_id || !protected_process) if (!protected_process_id || !protected_process)
goto end; goto end;
process_creator_name = ImpPsGetProcessImageFileName(process_creator); process_creator_name = ImpPsGetProcessImageFileName(process_creator);
target_process_name = ImpPsGetProcessImageFileName(target_process); target_process_name = ImpPsGetProcessImageFileName(target_process);
protected_process_name = ImpPsGetProcessImageFileName(protected_process); protected_process_name = ImpPsGetProcessImageFileName(protected_process);
if (!protected_process_name || !target_process_name) if (!protected_process_name || !target_process_name)
@ -910,7 +939,9 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
sizeof(OPEN_HANDLE_FAILURE_REPORT)); sizeof(OPEN_HANDLE_FAILURE_REPORT));
POPEN_HANDLE_FAILURE_REPORT report = ImpExAllocatePool2( POPEN_HANDLE_FAILURE_REPORT report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, report_size, REPORT_POOL_TAG); POOL_FLAG_NON_PAGED,
report_size,
REPORT_POOL_TAG);
if (!report) if (!report)
goto end; goto end;
@ -918,14 +949,15 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
INIT_REPORT_PACKET(report, REPORT_ILLEGAL_HANDLE_OPERATION, 0); INIT_REPORT_PACKET(report, REPORT_ILLEGAL_HANDLE_OPERATION, 0);
report->is_kernel_handle = OperationInformation->KernelHandle; report->is_kernel_handle = OperationInformation->KernelHandle;
report->process_id = process_creator_id; report->process_id = process_creator_id;
report->thread_id = ImpPsGetCurrentThreadId(); report->thread_id = ImpPsGetCurrentThreadId();
report->access = OperationInformation->Parameters report->access = OperationInformation->Parameters
->CreateHandleInformation.DesiredAccess; ->CreateHandleInformation.DesiredAccess;
IntCopyMemory(report->process_name, IntCopyMemory(
process_creator_name, report->process_name,
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH); process_creator_name,
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
status = CryptEncryptBuffer(report, report_size); status = CryptEncryptBuffer(report, report_size);
@ -946,8 +978,8 @@ end:
/* stolen from ReactOS xD */ /* stolen from ReactOS xD */
VOID NTAPI VOID NTAPI
ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable, ExUnlockHandleTableEntry(
IN PHANDLE_TABLE_ENTRY HandleTableEntry) IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
{ {
INT64 old_value; INT64 old_value;
PAGED_CODE(); PAGED_CODE();
@ -971,43 +1003,46 @@ GetHandleAccessMask(_In_ PHANDLE_TABLE_ENTRY Entry)
} }
static UNICODE_STRING OBJECT_TYPE_PROCESS = RTL_CONSTANT_STRING(L"Process"); static UNICODE_STRING OBJECT_TYPE_PROCESS = RTL_CONSTANT_STRING(L"Process");
static UNICODE_STRING OBJECT_TYPE_THREAD = RTL_CONSTANT_STRING(L"Thread"); static UNICODE_STRING OBJECT_TYPE_THREAD = RTL_CONSTANT_STRING(L"Thread");
STATIC STATIC
BOOLEAN BOOLEAN
EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable, EnumHandleCallback(
_In_ PHANDLE_TABLE_ENTRY Entry, _In_ PHANDLE_TABLE HandleTable,
_In_ HANDLE Handle, _In_ PHANDLE_TABLE_ENTRY Entry,
_In_ PVOID Context) _In_ HANDLE Handle,
_In_ PVOID Context)
{ {
PAGED_CODE(); PAGED_CODE();
UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(Context);
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PVOID object = NULL; PVOID object = NULL;
PVOID object_header = NULL; PVOID object_header = NULL;
POBJECT_TYPE object_type = NULL; POBJECT_TYPE object_type = NULL;
PEPROCESS process = NULL; PEPROCESS process = NULL;
PEPROCESS protected_process = NULL; PEPROCESS protected_process = NULL;
LPCSTR process_name = NULL; LPCSTR process_name = NULL;
LPCSTR protected_process_name = NULL; LPCSTR protected_process_name = NULL;
ACCESS_MASK handle_access_mask = 0; ACCESS_MASK handle_access_mask = 0;
UINT32 report_size = 0; UINT32 report_size = 0;
object_header = GET_OBJECT_HEADER_FROM_HANDLE(Entry->ObjectPointerBits); object_header = GET_OBJECT_HEADER_FROM_HANDLE(Entry->ObjectPointerBits);
/* Object header is the first 30 bytes of the object */ /* Object header is the first 30 bytes of the object */
object = (uintptr_t)object_header + OBJECT_HEADER_SIZE; object = (uintptr_t)object_header + OBJECT_HEADER_SIZE;
object_type = ImpObGetObjectType(object); object_type = ImpObGetObjectType(object);
/* TODO: check for threads aswell */ /* TODO: check for threads aswell */
if (ImpRtlCompareUnicodeString( if (ImpRtlCompareUnicodeString(
&object_type->Name, &OBJECT_TYPE_PROCESS, TRUE)) { &object_type->Name,
&OBJECT_TYPE_PROCESS,
TRUE)) {
goto end; goto end;
} }
process = (PEPROCESS)object; process = (PEPROCESS)object;
process_name = ImpPsGetProcessImageFileName(process); process_name = ImpPsGetProcessImageFileName(process);
SessionGetProcess(&protected_process); SessionGetProcess(&protected_process);
@ -1114,13 +1149,14 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
INIT_REPORT_PACKET(report, REPORT_ILLEGAL_HANDLE_OPERATION, 0); INIT_REPORT_PACKET(report, REPORT_ILLEGAL_HANDLE_OPERATION, 0);
report->is_kernel_handle = Entry->Attributes & OBJ_KERNEL_HANDLE; report->is_kernel_handle = Entry->Attributes & OBJ_KERNEL_HANDLE;
report->process_id = ImpPsGetProcessId(process); report->process_id = ImpPsGetProcessId(process);
report->thread_id = 0; report->thread_id = 0;
report->access = handle_access_mask; report->access = handle_access_mask;
IntCopyMemory(&report->process_name, IntCopyMemory(
process_name, &report->process_name,
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH); process_name,
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
status = CryptEncryptBuffer(report, report_size); status = CryptEncryptBuffer(report, report_size);
@ -1175,12 +1211,12 @@ EnumerateProcessHandles(_In_ PPROCESS_LIST_ENTRY Entry, _In_opt_ PVOID Context)
STATIC STATIC
VOID VOID
TimerObjectValidateProcessModuleCallback(_In_ PPROCESS_MAP_MODULE_ENTRY Entry, TimerObjectValidateProcessModuleCallback(
_In_opt_ PVOID Context) _In_ PPROCESS_MAP_MODULE_ENTRY Entry, _In_opt_ PVOID Context)
{ {
CHAR hash[SHA_256_HASH_LENGTH] = {0}; CHAR hash[SHA_256_HASH_LENGTH] = {0};
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION session = (PACTIVE_SESSION)Context; PACTIVE_SESSION session = (PACTIVE_SESSION)Context;
if (!ARGUMENT_PRESENT(Context)) if (!ARGUMENT_PRESENT(Context))
return; return;
@ -1203,13 +1239,13 @@ TimerObjectValidateProcessModuleCallback(_In_ PPROCESS_MAP_MODULE_ENTRY Entry,
STATIC STATIC
VOID VOID
TimerObjectWorkItemRoutine(_In_ PDEVICE_OBJECT DeviceObject, TimerObjectWorkItemRoutine(
_In_opt_ PVOID Context) _In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PTIMER_OBJECT timer = (PTIMER_OBJECT)Context; PTIMER_OBJECT timer = (PTIMER_OBJECT)Context;
PDRIVER_LIST_HEAD list = GetDriverList(); PDRIVER_LIST_HEAD list = GetDriverList();
PACTIVE_SESSION session = GetActiveSession(); PACTIVE_SESSION session = GetActiveSession();
UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(DeviceObject);
@ -1238,8 +1274,9 @@ TimerObjectWorkItemRoutine(_In_ PDEVICE_OBJECT DeviceObject,
goto end; goto end;
} }
FindOurUserModeModuleEntry(TimerObjectValidateProcessModuleCallback, FindOurUserModeModuleEntry(
session); TimerObjectValidateProcessModuleCallback,
session);
KeReleaseGuardedMutex(&session->lock); KeReleaseGuardedMutex(&session->lock);
end: end:
@ -1251,10 +1288,11 @@ end:
*/ */
STATIC STATIC
VOID VOID
TimerObjectCallbackRoutine(_In_ PKDPC Dpc, TimerObjectCallbackRoutine(
_In_opt_ PVOID DeferredContext, _In_ PKDPC Dpc,
_In_opt_ PVOID SystemArgument1, _In_opt_ PVOID DeferredContext,
_In_opt_ PVOID SystemArgument2) _In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2)
{ {
UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument1);
@ -1272,10 +1310,11 @@ TimerObjectCallbackRoutine(_In_ PKDPC Dpc,
/* we queue a work item because DPCs run at IRQL = DISPATCH_LEVEL and we /* we queue a work item because DPCs run at IRQL = DISPATCH_LEVEL and we
* need certain routines which cannot be run at an IRQL this high.*/ * need certain routines which cannot be run at an IRQL this high.*/
InterlockedExchange(&timer->state, TRUE); InterlockedExchange(&timer->state, TRUE);
IoQueueWorkItem(timer->work_item, IoQueueWorkItem(
TimerObjectWorkItemRoutine, timer->work_item,
BackgroundWorkQueue, TimerObjectWorkItemRoutine,
timer); BackgroundWorkQueue,
timer);
} }
NTSTATUS NTSTATUS
@ -1335,9 +1374,9 @@ RegisterProcessObCallbacks()
{ {
PAGED_CODE(); PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION config = GetActiveSession(); PACTIVE_SESSION config = GetActiveSession();
OB_CALLBACK_REGISTRATION callback_registration = {0}; OB_CALLBACK_REGISTRATION callback_registration = {0};
OB_OPERATION_REGISTRATION operation_registration = {0}; OB_OPERATION_REGISTRATION operation_registration = {0};
DEBUG_VERBOSE("Enabling ObRegisterCallbacks."); DEBUG_VERBOSE("Enabling ObRegisterCallbacks.");
@ -1346,13 +1385,13 @@ RegisterProcessObCallbacks()
operation_registration.ObjectType = PsProcessType; operation_registration.ObjectType = PsProcessType;
operation_registration.Operations |= OB_OPERATION_HANDLE_CREATE; operation_registration.Operations |= OB_OPERATION_HANDLE_CREATE;
operation_registration.Operations |= OB_OPERATION_HANDLE_DUPLICATE; operation_registration.Operations |= OB_OPERATION_HANDLE_DUPLICATE;
operation_registration.PreOperation = ObPreOpCallbackRoutine; operation_registration.PreOperation = ObPreOpCallbackRoutine;
operation_registration.PostOperation = ObPostOpCallbackRoutine; operation_registration.PostOperation = ObPostOpCallbackRoutine;
callback_registration.Version = OB_FLT_REGISTRATION_VERSION; callback_registration.Version = OB_FLT_REGISTRATION_VERSION;
callback_registration.OperationRegistration = &operation_registration; callback_registration.OperationRegistration = &operation_registration;
callback_registration.OperationRegistrationCount = 1; callback_registration.OperationRegistrationCount = 1;
callback_registration.RegistrationContext = NULL; callback_registration.RegistrationContext = NULL;
status = ImpObRegisterCallbacks( status = ImpObRegisterCallbacks(
&callback_registration, &callback_registration,

View file

@ -11,29 +11,33 @@ RtlHashmapDelete(_In_ PRTL_HASHMAP Hashmap)
} }
NTSTATUS NTSTATUS
RtlHashmapCreate(_In_ UINT32 BucketCount, RtlHashmapCreate(
_In_ UINT32 EntryObjectSize, _In_ UINT32 BucketCount,
_In_ HASH_FUNCTION HashFunction, _In_ UINT32 EntryObjectSize,
_In_ COMPARE_FUNCTION CompareFunction, _In_ HASH_FUNCTION HashFunction,
_In_opt_ PVOID Context, _In_ COMPARE_FUNCTION CompareFunction,
_Out_ PRTL_HASHMAP Hashmap) _In_opt_ PVOID Context,
_Out_ PRTL_HASHMAP Hashmap)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 entry_size = sizeof(RTL_HASHMAP_ENTRY) + EntryObjectSize; UINT32 entry_size = sizeof(RTL_HASHMAP_ENTRY) + EntryObjectSize;
PRTL_HASHMAP_ENTRY entry = NULL; PRTL_HASHMAP_ENTRY entry = NULL;
if (!CompareFunction || !HashFunction) if (!CompareFunction || !HashFunction)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
Hashmap->buckets = ExAllocatePool2( Hashmap->buckets = ExAllocatePool2(
POOL_FLAG_NON_PAGED, BucketCount * entry_size, POOL_TAG_HASHMAP); POOL_FLAG_NON_PAGED,
BucketCount * entry_size,
POOL_TAG_HASHMAP);
if (!Hashmap->buckets) if (!Hashmap->buckets)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
Hashmap->locks = ExAllocatePool2(POOL_FLAG_NON_PAGED, Hashmap->locks = ExAllocatePool2(
sizeof(KGUARDED_MUTEX) * BucketCount, POOL_FLAG_NON_PAGED,
POOL_TAG_HASHMAP); sizeof(KGUARDED_MUTEX) * BucketCount,
POOL_TAG_HASHMAP);
if (!Hashmap->locks) { if (!Hashmap->locks) {
ExFreePoolWithTag(Hashmap->buckets, POOL_TAG_HASHMAP); ExFreePoolWithTag(Hashmap->buckets, POOL_TAG_HASHMAP);
@ -41,20 +45,21 @@ RtlHashmapCreate(_In_ UINT32 BucketCount,
} }
for (UINT32 index = 0; index < BucketCount; index++) { for (UINT32 index = 0; index < BucketCount; index++) {
entry = &Hashmap->buckets[index]; entry = &Hashmap->buckets[index];
entry->in_use = FALSE; entry->in_use = FALSE;
InitializeListHead(&entry->entry); InitializeListHead(&entry->entry);
KeInitializeGuardedMutex(&Hashmap->locks[index]); KeInitializeGuardedMutex(&Hashmap->locks[index]);
} }
status = ExInitializeLookasideListEx(&Hashmap->pool, status = ExInitializeLookasideListEx(
NULL, &Hashmap->pool,
NULL, NULL,
NonPagedPoolNx, NULL,
0, NonPagedPoolNx,
entry_size, 0,
POOL_TAG_HASHMAP, entry_size,
0); POOL_TAG_HASHMAP,
0);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ExInitializeLookasideListEx: %x", status); DEBUG_ERROR("ExInitializeLookasideListEx: %x", status);
@ -63,12 +68,12 @@ RtlHashmapCreate(_In_ UINT32 BucketCount,
return status; return status;
} }
Hashmap->bucket_count = BucketCount; Hashmap->bucket_count = BucketCount;
Hashmap->hash_function = HashFunction; Hashmap->hash_function = HashFunction;
Hashmap->compare_function = CompareFunction; Hashmap->compare_function = CompareFunction;
Hashmap->object_size = EntryObjectSize; Hashmap->object_size = EntryObjectSize;
Hashmap->active = TRUE; Hashmap->active = TRUE;
Hashmap->context = Context; Hashmap->context = Context;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -78,8 +83,8 @@ STATIC
PRTL_HASHMAP_ENTRY PRTL_HASHMAP_ENTRY
RtlpHashmapFindUnusedEntry(_In_ PLIST_ENTRY Head) RtlpHashmapFindUnusedEntry(_In_ PLIST_ENTRY Head)
{ {
PRTL_HASHMAP_ENTRY entry = NULL; PRTL_HASHMAP_ENTRY entry = NULL;
PLIST_ENTRY list_entry = Head->Flink; PLIST_ENTRY list_entry = Head->Flink;
while (list_entry != Head) { while (list_entry != Head) {
entry = CONTAINING_RECORD(list_entry, RTL_HASHMAP_ENTRY, entry); entry = CONTAINING_RECORD(list_entry, RTL_HASHMAP_ENTRY, entry);
@ -141,16 +146,16 @@ RtlHashmapReleaseBucket(_Inout_ PRTL_HASHMAP Hashmap, _In_ UINT32 Index)
PVOID PVOID
RtlHashmapEntryInsert(_In_ PRTL_HASHMAP Hashmap, _In_ UINT32 Index) RtlHashmapEntryInsert(_In_ PRTL_HASHMAP Hashmap, _In_ UINT32 Index)
{ {
UINT32 index = 0; UINT32 index = 0;
PLIST_ENTRY list_head = NULL; PLIST_ENTRY list_head = NULL;
PRTL_HASHMAP_ENTRY entry = NULL; PRTL_HASHMAP_ENTRY entry = NULL;
PRTL_HASHMAP_ENTRY new_entry = NULL; PRTL_HASHMAP_ENTRY new_entry = NULL;
if (!Hashmap->active) if (!Hashmap->active)
return NULL; return NULL;
list_head = &(&Hashmap->buckets[index])->entry; list_head = &(&Hashmap->buckets[index])->entry;
entry = RtlpHashmapFindUnusedEntry(list_head); entry = RtlpHashmapFindUnusedEntry(list_head);
if (entry) if (entry)
return entry; return entry;
@ -172,11 +177,10 @@ RtlHashmapEntryInsert(_In_ PRTL_HASHMAP Hashmap, _In_ UINT32 Index)
* Also assumes lock is held. * Also assumes lock is held.
*/ */
PVOID PVOID
RtlHashmapEntryLookup(_In_ PRTL_HASHMAP Hashmap, RtlHashmapEntryLookup(
_In_ UINT32 Index, _In_ PRTL_HASHMAP Hashmap, _In_ UINT32 Index, _In_ PVOID Compare)
_In_ PVOID Compare)
{ {
UINT32 index = 0; UINT32 index = 0;
PRTL_HASHMAP_ENTRY entry = NULL; PRTL_HASHMAP_ENTRY entry = NULL;
if (!Hashmap->active) if (!Hashmap->active)
@ -201,19 +205,18 @@ RtlHashmapEntryLookup(_In_ PRTL_HASHMAP Hashmap,
/* Assumes lock is held */ /* Assumes lock is held */
BOOLEAN BOOLEAN
RtlHashmapEntryDelete(_Inout_ PRTL_HASHMAP Hashmap, RtlHashmapEntryDelete(
_In_ UINT32 Index, _Inout_ PRTL_HASHMAP Hashmap, _In_ UINT32 Index, _In_ PVOID Compare)
_In_ PVOID Compare)
{ {
UINT32 index = 0; UINT32 index = 0;
PLIST_ENTRY list_head = NULL; PLIST_ENTRY list_head = NULL;
PLIST_ENTRY list_entry = NULL; PLIST_ENTRY list_entry = NULL;
PRTL_HASHMAP_ENTRY entry = NULL; PRTL_HASHMAP_ENTRY entry = NULL;
if (!Hashmap->active) if (!Hashmap->active)
return FALSE; return FALSE;
list_head = &(&Hashmap->buckets[index])->entry; list_head = &(&Hashmap->buckets[index])->entry;
list_entry = list_head->Flink; list_entry = list_head->Flink;
while (list_entry != list_head) { while (list_entry != list_head) {
@ -240,18 +243,19 @@ RtlHashmapEntryDelete(_Inout_ PRTL_HASHMAP Hashmap,
/* assumes lock is held */ /* assumes lock is held */
VOID VOID
RtlHashmapEnumerate(_In_ PRTL_HASHMAP Hashmap, RtlHashmapEnumerate(
_In_ ENUMERATE_HASHMAP EnumerationCallback, _In_ PRTL_HASHMAP Hashmap,
_In_opt_ PVOID Context) _In_ ENUMERATE_HASHMAP EnumerationCallback,
_In_opt_ PVOID Context)
{ {
PLIST_ENTRY list_head = NULL; PLIST_ENTRY list_head = NULL;
PLIST_ENTRY list_entry = NULL; PLIST_ENTRY list_entry = NULL;
PRTL_HASHMAP_ENTRY entry = NULL; PRTL_HASHMAP_ENTRY entry = NULL;
for (UINT32 index = 0; index < Hashmap->bucket_count; index++) { for (UINT32 index = 0; index < Hashmap->bucket_count; index++) {
KeAcquireGuardedMutex(&Hashmap->locks[index]); KeAcquireGuardedMutex(&Hashmap->locks[index]);
list_head = &Hashmap->buckets[index]; list_head = &Hashmap->buckets[index];
list_entry = list_head->Flink; list_entry = list_head->Flink;
while (list_entry != list_head) { while (list_entry != list_head) {

View file

@ -108,9 +108,9 @@ RtlRbTreePrintCurrentStatistics(_In_ PRB_TREE Tree)
* - This stores the size of the objects that will be stored in the tree. It * - This stores the size of the objects that will be stored in the tree. It
* is used to allocate memory for the nodes. * is used to allocate memory for the nodes.
* - Lets say each node needs to have a THREAD_LIST_ENTRY object. The * - Lets say each node needs to have a THREAD_LIST_ENTRY object. The
* ObjectSize = sizeof(THREAD_LIST_OBJECT) and in turn will mean each node will * ObjectSize = sizeof(THREAD_LIST_OBJECT) and in turn will mean each node
* be of size: sizeof(THREAD_LIST_OBJECT) + sizeof(RB_TREE_NODE). This is also * will be of size: sizeof(THREAD_LIST_OBJECT) + sizeof(RB_TREE_NODE). This is
* this size the lookaside list pools will be set to. * also this size the lookaside list pools will be set to.
* *
* > `LOOKASIDE_LIST_EX pool`: * > `LOOKASIDE_LIST_EX pool`:
* - This is a lookaside list that provides a fast, efficient way to allocate * - This is a lookaside list that provides a fast, efficient way to allocate
@ -118,31 +118,31 @@ RtlRbTreePrintCurrentStatistics(_In_ PRB_TREE Tree)
* block is `ObjectSize + sizeof(RB_TREE_NODE)`. * block is `ObjectSize + sizeof(RB_TREE_NODE)`.
*/ */
NTSTATUS NTSTATUS
RtlRbTreeCreate(_In_ RB_COMPARE Compare, RtlRbTreeCreate(
_In_ UINT32 ObjectSize, _In_ RB_COMPARE Compare, _In_ UINT32 ObjectSize, _Out_ PRB_TREE Tree)
_Out_ PRB_TREE Tree)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
if (!ARGUMENT_PRESENT(Compare) || ObjectSize == 0) if (!ARGUMENT_PRESENT(Compare) || ObjectSize == 0)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
status = ExInitializeLookasideListEx(&Tree->pool, status = ExInitializeLookasideListEx(
NULL, &Tree->pool,
NULL, NULL,
NonPagedPoolNx, NULL,
0, NonPagedPoolNx,
ObjectSize + sizeof(RB_TREE_NODE), 0,
POOL_TAG_RB_TREE, ObjectSize + sizeof(RB_TREE_NODE),
0); POOL_TAG_RB_TREE,
0);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
return status; return status;
Tree->compare = Compare; Tree->compare = Compare;
Tree->deletion_count = 0; Tree->deletion_count = 0;
Tree->insertion_count = 0; Tree->insertion_count = 0;
Tree->node_count = 0; Tree->node_count = 0;
KeInitializeGuardedMutex(&Tree->lock); KeInitializeGuardedMutex(&Tree->lock);
@ -167,7 +167,7 @@ VOID
RtlpRbTreeRotateLeft(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node) RtlpRbTreeRotateLeft(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
{ {
PRB_TREE_NODE right_child = Node->right; PRB_TREE_NODE right_child = Node->right;
Node->right = right_child->left; Node->right = right_child->left;
if (right_child->left) if (right_child->left)
right_child->left->parent = Node; right_child->left->parent = Node;
@ -182,7 +182,7 @@ RtlpRbTreeRotateLeft(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
Node->parent->right = right_child; Node->parent->right = right_child;
right_child->left = Node; right_child->left = Node;
Node->parent = right_child; Node->parent = right_child;
} }
/* /*
@ -205,7 +205,7 @@ VOID
RtlpRbTreeRotateRight(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node) RtlpRbTreeRotateRight(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
{ {
PRB_TREE_NODE left_child = Node->left; PRB_TREE_NODE left_child = Node->left;
Node->left = left_child->right; Node->left = left_child->right;
if (left_child->right) if (left_child->right)
left_child->right->parent = Node; left_child->right->parent = Node;
@ -220,7 +220,7 @@ RtlpRbTreeRotateRight(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
Node->parent->left = left_child; Node->parent->left = left_child;
left_child->right = Node; left_child->right = Node;
Node->parent = left_child; Node->parent = left_child;
} }
/* /*
@ -241,8 +241,8 @@ STATIC
VOID VOID
RtlpRbTreeFixupInsert(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node) RtlpRbTreeFixupInsert(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
{ {
PRB_TREE_NODE uncle = NULL; PRB_TREE_NODE uncle = NULL;
PRB_TREE_NODE parent = NULL; PRB_TREE_NODE parent = NULL;
PRB_TREE_NODE grandparent = NULL; PRB_TREE_NODE grandparent = NULL;
while ((parent = Node->parent) && parent->colour == red) { while ((parent = Node->parent) && parent->colour == red) {
@ -252,19 +252,19 @@ RtlpRbTreeFixupInsert(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
uncle = grandparent->right; uncle = grandparent->right;
if (uncle && uncle->colour == red) { if (uncle && uncle->colour == red) {
parent->colour = black; parent->colour = black;
uncle->colour = black; uncle->colour = black;
grandparent->colour = red; grandparent->colour = red;
Node = grandparent; Node = grandparent;
} }
else { else {
if (Node == parent->right) { if (Node == parent->right) {
RtlpRbTreeRotateLeft(Tree, parent); RtlpRbTreeRotateLeft(Tree, parent);
Node = parent; Node = parent;
parent = Node->parent; parent = Node->parent;
} }
parent->colour = black; parent->colour = black;
grandparent->colour = red; grandparent->colour = red;
RtlpRbTreeRotateRight(Tree, grandparent); RtlpRbTreeRotateRight(Tree, grandparent);
} }
@ -273,19 +273,19 @@ RtlpRbTreeFixupInsert(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
uncle = grandparent->left; uncle = grandparent->left;
if (uncle && uncle->colour == red) { if (uncle && uncle->colour == red) {
parent->colour = black; parent->colour = black;
uncle->colour = black; uncle->colour = black;
grandparent->colour = red; grandparent->colour = red;
Node = grandparent; Node = grandparent;
} }
else { else {
if (Node == parent->left) { if (Node == parent->left) {
RtlpRbTreeRotateRight(Tree, parent); RtlpRbTreeRotateRight(Tree, parent);
Node = parent; Node = parent;
parent = Node->parent; parent = Node->parent;
} }
parent->colour = black; parent->colour = black;
grandparent->colour = red; grandparent->colour = red;
RtlpRbTreeRotateLeft(Tree, grandparent); RtlpRbTreeRotateLeft(Tree, grandparent);
} }
@ -325,9 +325,9 @@ RtlpRbTreeFixupInsert(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
PVOID PVOID
RtlRbTreeInsertNode(_In_ PRB_TREE Tree, _In_ PVOID Key) RtlRbTreeInsertNode(_In_ PRB_TREE Tree, _In_ PVOID Key)
{ {
UINT32 result = 0; UINT32 result = 0;
PRB_TREE_NODE node = NULL; PRB_TREE_NODE node = NULL;
PRB_TREE_NODE parent = NULL; PRB_TREE_NODE parent = NULL;
PRB_TREE_NODE current = NULL; PRB_TREE_NODE current = NULL;
node = ExAllocateFromLookasideListEx(&Tree->pool); node = ExAllocateFromLookasideListEx(&Tree->pool);
@ -336,8 +336,8 @@ RtlRbTreeInsertNode(_In_ PRB_TREE Tree, _In_ PVOID Key)
return NULL; return NULL;
node->parent = NULL; node->parent = NULL;
node->left = NULL; node->left = NULL;
node->right = NULL; node->right = NULL;
node->colour = red; node->colour = red;
current = Tree->root; current = Tree->root;
@ -437,7 +437,7 @@ RtlpRbTreeFixupDelete(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
sibling = Node->parent->right; sibling = Node->parent->right;
if (sibling && sibling->colour == red) { if (sibling && sibling->colour == red) {
sibling->colour = black; sibling->colour = black;
Node->parent->colour = red; Node->parent->colour = red;
RtlpRbTreeRotateLeft(Tree, Node->parent); RtlpRbTreeRotateLeft(Tree, Node->parent);
sibling = Node->parent->right; sibling = Node->parent->right;
@ -446,7 +446,7 @@ RtlpRbTreeFixupDelete(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
if (sibling && (!sibling->left || sibling->left->colour == black) && if (sibling && (!sibling->left || sibling->left->colour == black) &&
(!sibling->right || sibling->right->colour == black)) { (!sibling->right || sibling->right->colour == black)) {
sibling->colour = red; sibling->colour = red;
Node = Node->parent; Node = Node->parent;
} }
else { else {
if (sibling && if (sibling &&
@ -460,7 +460,7 @@ RtlpRbTreeFixupDelete(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
} }
if (sibling) { if (sibling) {
sibling->colour = Node->parent->colour; sibling->colour = Node->parent->colour;
Node->parent->colour = black; Node->parent->colour = black;
if (sibling->right) if (sibling->right)
@ -476,7 +476,7 @@ RtlpRbTreeFixupDelete(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
sibling = Node->parent->left; sibling = Node->parent->left;
if (sibling && sibling->colour == red) { if (sibling && sibling->colour == red) {
sibling->colour = black; sibling->colour = black;
Node->parent->colour = red; Node->parent->colour = red;
RtlpRbTreeRotateRight(Tree, Node->parent); RtlpRbTreeRotateRight(Tree, Node->parent);
sibling = Node->parent->left; sibling = Node->parent->left;
@ -486,7 +486,7 @@ RtlpRbTreeFixupDelete(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
(!sibling->right || sibling->right->colour == black) && (!sibling->right || sibling->right->colour == black) &&
(!sibling->left || sibling->left->colour == black)) { (!sibling->left || sibling->left->colour == black)) {
sibling->colour = red; sibling->colour = red;
Node = Node->parent; Node = Node->parent;
} }
else { else {
if (sibling && if (sibling &&
@ -500,7 +500,7 @@ RtlpRbTreeFixupDelete(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
} }
if (sibling) { if (sibling) {
sibling->colour = Node->parent->colour; sibling->colour = Node->parent->colour;
Node->parent->colour = black; Node->parent->colour = black;
if (sibling->left) if (sibling->left)
@ -538,9 +538,10 @@ RtlpRbTreeFixupDelete(_In_ PRB_TREE Tree, _In_ PRB_TREE_NODE Node)
*/ */
STATIC STATIC
VOID VOID
RtlpRbTreeTransplant(_In_ PRB_TREE Tree, RtlpRbTreeTransplant(
_In_ PRB_TREE_NODE Target, _In_ PRB_TREE Tree,
_In_ PRB_TREE_NODE Replacement) _In_ PRB_TREE_NODE Target,
_In_ PRB_TREE_NODE Replacement)
{ {
if (!Target->parent) if (!Target->parent)
Tree->root = Replacement; Tree->root = Replacement;
@ -557,7 +558,7 @@ STATIC
PRB_TREE_NODE PRB_TREE_NODE
RtlpRbTreeFindNode(_In_ PRB_TREE Tree, _In_ PVOID Key) RtlpRbTreeFindNode(_In_ PRB_TREE Tree, _In_ PVOID Key)
{ {
INT32 result = 0; INT32 result = 0;
PRB_TREE_NODE current = Tree->root; PRB_TREE_NODE current = Tree->root;
while (current) { while (current) {
@ -597,10 +598,10 @@ RtlpRbTreeFindNode(_In_ PRB_TREE Tree, _In_ PVOID Key)
VOID VOID
RtlRbTreeDeleteNode(_In_ PRB_TREE Tree, _In_ PVOID Key) RtlRbTreeDeleteNode(_In_ PRB_TREE Tree, _In_ PVOID Key)
{ {
PRB_TREE_NODE target = NULL; PRB_TREE_NODE target = NULL;
PRB_TREE_NODE child = NULL; PRB_TREE_NODE child = NULL;
PRB_TREE_NODE successor = NULL; PRB_TREE_NODE successor = NULL;
COLOUR colour = {0}; COLOUR colour = {0};
/* We want the node not the object */ /* We want the node not the object */
target = RtlpRbTreeFindNode(Tree, Key); target = RtlpRbTreeFindNode(Tree, Key);
@ -620,8 +621,8 @@ RtlRbTreeDeleteNode(_In_ PRB_TREE Tree, _In_ PVOID Key)
} }
else { else {
successor = RtlpRbTreeMinimum(target->right); successor = RtlpRbTreeMinimum(target->right);
colour = successor->colour; colour = successor->colour;
child = successor->right; child = successor->right;
if (successor->parent == target) { if (successor->parent == target) {
if (child) if (child)
@ -629,14 +630,14 @@ RtlRbTreeDeleteNode(_In_ PRB_TREE Tree, _In_ PVOID Key)
} }
else { else {
RtlpRbTreeTransplant(Tree, successor, successor->right); RtlpRbTreeTransplant(Tree, successor, successor->right);
successor->right = target->right; successor->right = target->right;
successor->right->parent = successor; successor->right->parent = successor;
} }
RtlpRbTreeTransplant(Tree, target, successor); RtlpRbTreeTransplant(Tree, target, successor);
successor->left = target->left; successor->left = target->left;
successor->left->parent = successor; successor->left->parent = successor;
successor->colour = target->colour; successor->colour = target->colour;
} }
if (colour == black && child) if (colour == black && child)
@ -654,7 +655,7 @@ RtlRbTreeDeleteNode(_In_ PRB_TREE Tree, _In_ PVOID Key)
PVOID PVOID
RtlRbTreeFindNodeObject(_In_ PRB_TREE Tree, _In_ PVOID Key) RtlRbTreeFindNodeObject(_In_ PRB_TREE Tree, _In_ PVOID Key)
{ {
INT32 result = 0; INT32 result = 0;
PRB_TREE_NODE current = Tree->root; PRB_TREE_NODE current = Tree->root;
while (current) { while (current) {
@ -673,9 +674,10 @@ RtlRbTreeFindNodeObject(_In_ PRB_TREE Tree, _In_ PVOID Key)
STATIC STATIC
VOID VOID
RtlpRbTreeEnumerate(_In_ PRB_TREE_NODE Node, RtlpRbTreeEnumerate(
_In_ RB_ENUM_CALLBACK Callback, _In_ PRB_TREE_NODE Node,
_In_opt_ PVOID Context) _In_ RB_ENUM_CALLBACK Callback,
_In_opt_ PVOID Context)
{ {
if (Node == NULL) if (Node == NULL)
return; return;
@ -686,9 +688,8 @@ RtlpRbTreeEnumerate(_In_ PRB_TREE_NODE Node,
} }
VOID VOID
RtlRbTreeEnumerate(_In_ PRB_TREE Tree, RtlRbTreeEnumerate(
_In_ RB_ENUM_CALLBACK Callback, _In_ PRB_TREE Tree, _In_ RB_ENUM_CALLBACK Callback, _In_opt_ PVOID Context)
_In_opt_ PVOID Context)
{ {
if (Tree->root == NULL) if (Tree->root == NULL)
return; return;
@ -708,11 +709,12 @@ RtlpPrintInOrder(PRB_TREE_NODE Node)
RtlpPrintInOrder(Node->left); RtlpPrintInOrder(Node->left);
const char* color = (Node->colour == red) ? "Red" : "Black"; const char* color = (Node->colour == red) ? "Red" : "Black";
DbgPrintEx(DPFLTR_DEFAULT_ID, DbgPrintEx(
DPFLTR_INFO_LEVEL, DPFLTR_DEFAULT_ID,
"Node: Key=%p, Color=%s\n", DPFLTR_INFO_LEVEL,
*((PHANDLE)Node->object), "Node: Key=%p, Color=%s\n",
color); *((PHANDLE)Node->object),
color);
RtlpPrintInOrder(Node->right); RtlpPrintInOrder(Node->right);
} }
@ -722,7 +724,7 @@ RtlRbTreeInOrderPrint(_In_ PRB_TREE Tree)
{ {
DEBUG_ERROR("*************************************************"); DEBUG_ERROR("*************************************************");
DEBUG_ERROR("<><><><>STARTING IN ORDER PRINT <><><><><><"); DEBUG_ERROR("<><><><>STARTING IN ORDER PRINT <><><><><><");
RtlRbTreeAcquireLock(Tree); RtlRbTreeAcquireLock(Tree);
RtlpPrintInOrder(Tree->root); RtlpPrintInOrder(Tree->root);
RtlRbTreeReleaselock(Tree); RtlRbTreeReleaselock(Tree);
DEBUG_ERROR("<><><><>ENDING IN ORDER PRINT <><><><><><"); DEBUG_ERROR("<><><><>ENDING IN ORDER PRINT <><><><><><");

View file

@ -1,8 +1,8 @@
#include "crypt.h" #include "crypt.h"
#include "driver.h"
#include "imports.h" #include "imports.h"
#include "session.h" #include "session.h"
#include "driver.h"
#include "util.h" #include "util.h"
#include "types/tpm20.h" #include "types/tpm20.h"
@ -10,8 +10,8 @@
#include "lib/stdlib.h" #include "lib/stdlib.h"
#include <immintrin.h>
#include <bcrypt.h> #include <bcrypt.h>
#include <immintrin.h>
FORCEINLINE FORCEINLINE
STATIC STATIC
@ -25,7 +25,7 @@ STATIC
__m256i __m256i
CryptXorKeyGenerate_m256i() CryptXorKeyGenerate_m256i()
{ {
UINT32 seed = (UINT32)__rdtsc(); UINT32 seed = (UINT32)__rdtsc();
UINT64 key_1 = CryptGenerateRandomKey64(&seed); UINT64 key_1 = CryptGenerateRandomKey64(&seed);
UINT64 key_2 = CryptGenerateRandomKey64(&seed); UINT64 key_2 = CryptGenerateRandomKey64(&seed);
UINT64 key_3 = CryptGenerateRandomKey64(&seed); UINT64 key_3 = CryptGenerateRandomKey64(&seed);
@ -45,8 +45,8 @@ VOID
CryptEncryptImportsArray(_In_ PUINT64 Array, _In_ UINT32 Entries) CryptEncryptImportsArray(_In_ PUINT64 Array, _In_ UINT32 Entries)
{ {
__m256i* imports_key = GetDriverImportsKey(); __m256i* imports_key = GetDriverImportsKey();
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64); UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
UINT32 block_count = Entries / block_size; UINT32 block_count = Entries / block_size;
*imports_key = CryptXorKeyGenerate_m256i(); *imports_key = CryptXorKeyGenerate_m256i();
@ -57,19 +57,21 @@ CryptEncryptImportsArray(_In_ PUINT64 Array, _In_ UINT32 Entries)
*/ */
for (UINT32 block_index = 0; block_index < block_count; block_index++) { for (UINT32 block_index = 0; block_index < block_count; block_index++) {
__m256i current_block = {0}; __m256i current_block = {0};
__m256i load_block = {0}; __m256i load_block = {0};
__m256i xored_block = {0}; __m256i xored_block = {0};
IntCopyMemory(&current_block, IntCopyMemory(
&Array[block_index * block_size], &current_block,
sizeof(__m256i)); &Array[block_index * block_size],
sizeof(__m256i));
load_block = _mm256_loadu_si256(&current_block); load_block = _mm256_loadu_si256(&current_block);
xored_block = _mm256_xor_si256(load_block, *imports_key); xored_block = _mm256_xor_si256(load_block, *imports_key);
IntCopyMemory(&Array[block_index * block_size], IntCopyMemory(
&xored_block, &Array[block_index * block_size],
sizeof(__m256i)); &xored_block,
sizeof(__m256i));
} }
} }
@ -78,13 +80,14 @@ INLINE
__m256i __m256i
CryptDecryptImportBlock(_In_ PUINT64 Array, _In_ UINT32 BlockIndex) CryptDecryptImportBlock(_In_ PUINT64 Array, _In_ UINT32 BlockIndex)
{ {
__m256i load_block = {0}; __m256i load_block = {0};
__m256i* imports_key = GetDriverImportsKey(); __m256i* imports_key = GetDriverImportsKey();
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64); UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
IntCopyMemory(&load_block, IntCopyMemory(
&Array[BlockIndex * block_size], &load_block,
sizeof(__m256i)); &Array[BlockIndex * block_size],
sizeof(__m256i));
return _mm256_xor_si256(load_block, *imports_key); return _mm256_xor_si256(load_block, *imports_key);
} }
@ -92,23 +95,24 @@ CryptDecryptImportBlock(_In_ PUINT64 Array, _In_ UINT32 BlockIndex)
FORCEINLINE FORCEINLINE
INLINE INLINE
VOID VOID
CryptFindContainingBlockForArrayIndex(_In_ UINT32 EntryIndex, CryptFindContainingBlockForArrayIndex(
_In_ UINT32 BlockSize, _In_ UINT32 EntryIndex,
_Out_ PUINT32 ContainingBlockIndex, _In_ UINT32 BlockSize,
_Out_ PUINT32 BlockSubIndex) _Out_ PUINT32 ContainingBlockIndex,
_Out_ PUINT32 BlockSubIndex)
{ {
UINT32 containing_block = EntryIndex; UINT32 containing_block = EntryIndex;
UINT32 block_index = 0; UINT32 block_index = 0;
if (EntryIndex < BlockSize) { if (EntryIndex < BlockSize) {
*ContainingBlockIndex = 0; *ContainingBlockIndex = 0;
*BlockSubIndex = EntryIndex; *BlockSubIndex = EntryIndex;
return; return;
} }
if (EntryIndex == BlockSize) { if (EntryIndex == BlockSize) {
*ContainingBlockIndex = 1; *ContainingBlockIndex = 1;
*BlockSubIndex = 0; *BlockSubIndex = 0;
return; return;
} }
@ -118,25 +122,25 @@ CryptFindContainingBlockForArrayIndex(_In_ UINT32 EntryIndex,
} }
*ContainingBlockIndex = containing_block / BlockSize; *ContainingBlockIndex = containing_block / BlockSize;
*BlockSubIndex = block_index; *BlockSubIndex = block_index;
} }
UINT64 UINT64
CryptDecryptImportsArrayEntry(_In_ PUINT64 Array, CryptDecryptImportsArrayEntry(
_In_ UINT32 Entries, _In_ PUINT64 Array, _In_ UINT32 Entries, _In_ UINT32 EntryIndex)
_In_ UINT32 EntryIndex)
{ {
__m256i original_block = {0}; __m256i original_block = {0};
__m128i original_half = {0}; __m128i original_half = {0};
UINT32 block_size = sizeof(__m256i) / sizeof(UINT64); UINT32 block_size = sizeof(__m256i) / sizeof(UINT64);
UINT32 containing_block_index = 0; UINT32 containing_block_index = 0;
UINT32 block_sub_index = 0; UINT32 block_sub_index = 0;
UINT64 pointer = 0; UINT64 pointer = 0;
CryptFindContainingBlockForArrayIndex(EntryIndex, CryptFindContainingBlockForArrayIndex(
block_size, EntryIndex,
&containing_block_index, block_size,
&block_sub_index); &containing_block_index,
&block_sub_index);
original_block = CryptDecryptImportBlock(Array, containing_block_index); original_block = CryptDecryptImportBlock(Array, containing_block_index);
@ -164,21 +168,22 @@ STATIC
PBCRYPT_KEY_DATA_BLOB_HEADER PBCRYPT_KEY_DATA_BLOB_HEADER
CryptBuildBlobForKeyImport(_In_ PACTIVE_SESSION Session) CryptBuildBlobForKeyImport(_In_ PACTIVE_SESSION Session)
{ {
PBCRYPT_KEY_DATA_BLOB_HEADER blob = PBCRYPT_KEY_DATA_BLOB_HEADER blob = ExAllocatePool2(
ExAllocatePool2(POOL_FLAG_NON_PAGED, POOL_FLAG_NON_PAGED,
sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + AES_256_KEY_SIZE, sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + AES_256_KEY_SIZE,
POOL_TAG_CRYPT); POOL_TAG_CRYPT);
if (!blob) if (!blob)
return NULL; return NULL;
blob->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC; blob->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
blob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1; blob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
blob->cbKeyData = AES_256_KEY_SIZE; blob->cbKeyData = AES_256_KEY_SIZE;
IntCopyMemory((UINT64)blob + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER), IntCopyMemory(
Session->aes_key, (UINT64)blob + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER),
AES_256_KEY_SIZE); Session->aes_key,
AES_256_KEY_SIZE);
return blob; return blob;
} }
@ -211,12 +216,12 @@ CryptRequestRequiredBufferLength(_In_ UINT32 BufferLength)
NTSTATUS NTSTATUS
CryptEncryptBuffer(_In_ PVOID Buffer, _In_ UINT32 BufferLength) CryptEncryptBuffer(_In_ PVOID Buffer, _In_ UINT32 BufferLength)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 data_copied = 0; UINT32 data_copied = 0;
PACTIVE_SESSION session = GetActiveSession(); PACTIVE_SESSION session = GetActiveSession();
UCHAR local_iv[sizeof(session->iv)] = {0}; UCHAR local_iv[sizeof(session->iv)] = {0};
UINT64 buffer = (UINT64)Buffer; UINT64 buffer = (UINT64)Buffer;
UINT32 length = BufferLength; UINT32 length = BufferLength;
/* The IV is consumed during every encrypt / decrypt procedure, so to ensure /* The IV is consumed during every encrypt / decrypt procedure, so to ensure
* we have access to the iv we need to create a local copy.*/ * we have access to the iv we need to create a local copy.*/
@ -226,16 +231,17 @@ CryptEncryptBuffer(_In_ PVOID Buffer, _In_ UINT32 BufferLength)
buffer = buffer + AES_256_BLOCK_SIZE; buffer = buffer + AES_256_BLOCK_SIZE;
length = length - AES_256_BLOCK_SIZE; length = length - AES_256_BLOCK_SIZE;
status = BCryptEncrypt(session->key_handle, status = BCryptEncrypt(
buffer, session->key_handle,
length, buffer,
NULL, length,
local_iv, NULL,
sizeof(local_iv), local_iv,
buffer, sizeof(local_iv),
length, buffer,
&data_copied, length,
0); &data_copied,
0);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("CryptEncryptBuffer -> BCryptEncrypt: %x", status); DEBUG_ERROR("CryptEncryptBuffer -> BCryptEncrypt: %x", status);
@ -265,52 +271,55 @@ CryptCloseSessionCryptObjects()
NTSTATUS NTSTATUS
CryptInitialiseSessionCryptObjects() CryptInitialiseSessionCryptObjects()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 data_copied = 0; UINT32 data_copied = 0;
PACTIVE_SESSION session = GetActiveSession(); PACTIVE_SESSION session = GetActiveSession();
PBCRYPT_KEY_DATA_BLOB_HEADER blob = NULL; PBCRYPT_KEY_DATA_BLOB_HEADER blob = NULL;
BCRYPT_ALG_HANDLE* handle = GetCryptHandle_AES(); BCRYPT_ALG_HANDLE* handle = GetCryptHandle_AES();
blob = CryptBuildBlobForKeyImport(session); blob = CryptBuildBlobForKeyImport(session);
if (!blob) if (!blob)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
status = BCryptGetProperty(*handle, status = BCryptGetProperty(
BCRYPT_OBJECT_LENGTH, *handle,
&session->key_object_length, BCRYPT_OBJECT_LENGTH,
sizeof(UINT32), &session->key_object_length,
&data_copied, sizeof(UINT32),
0); &data_copied,
0);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("BCryptGetProperty: %x", status); DEBUG_ERROR("BCryptGetProperty: %x", status);
goto end; goto end;
} }
session->key_object = ExAllocatePool2(POOL_FLAG_NON_PAGED, session->key_object = ExAllocatePool2(
session->key_object_length, POOL_FLAG_NON_PAGED,
POOL_TAG_CRYPT); session->key_object_length,
POOL_TAG_CRYPT);
if (!session->key_object) { if (!session->key_object) {
status = STATUS_INSUFFICIENT_RESOURCES; status = STATUS_INSUFFICIENT_RESOURCES;
goto end; goto end;
} }
DEBUG_INFO("key object: %llx, key_object_length: %lx", DEBUG_INFO(
session->key_object, "key object: %llx, key_object_length: %lx",
session->key_object_length); session->key_object,
session->key_object_length);
status = status = BCryptImportKey(
BCryptImportKey(*handle, *handle,
NULL, NULL,
BCRYPT_KEY_DATA_BLOB, BCRYPT_KEY_DATA_BLOB,
&session->key_handle, &session->key_handle,
session->key_object, session->key_object,
session->key_object_length, session->key_object_length,
blob, blob,
sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + AES_256_KEY_SIZE, sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + AES_256_KEY_SIZE,
0); 0);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("BCryptImportKey: %x", status); DEBUG_ERROR("BCryptImportKey: %x", status);
@ -328,13 +337,14 @@ end:
NTSTATUS NTSTATUS
CryptInitialiseProvider() CryptInitialiseProvider()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
BCRYPT_ALG_HANDLE* handle = GetCryptHandle_AES(); BCRYPT_ALG_HANDLE* handle = GetCryptHandle_AES();
status = BCryptOpenAlgorithmProvider(handle, status = BCryptOpenAlgorithmProvider(
BCRYPT_AES_ALGORITHM, handle,
NULL, BCRYPT_AES_ALGORITHM,
BCRYPT_PROV_DISPATCH); NULL,
BCRYPT_PROV_DISPATCH);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("BCryptOpenAlgorithmProvider: %x", status); DEBUG_ERROR("BCryptOpenAlgorithmProvider: %x", status);
@ -384,7 +394,7 @@ STATIC
NTSTATUS NTSTATUS
TpmCheckPtpRegisterPresence(_In_ PVOID Register, _Out_ PUINT32 Result) TpmCheckPtpRegisterPresence(_In_ PVOID Register, _Out_ PUINT32 Result)
{ {
UINT8 value = 0; UINT8 value = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
*Result = FALSE; *Result = FALSE;
@ -406,7 +416,7 @@ FORCEINLINE
STATIC STATIC
TPM2_PTP_INTERFACE_TYPE TPM2_PTP_INTERFACE_TYPE
TpmExtractInterfaceTypeFromCapabilityAndId( TpmExtractInterfaceTypeFromCapabilityAndId(
_In_ PTP_CRB_INTERFACE_IDENTIFIER* Identifier, _In_ PTP_CRB_INTERFACE_IDENTIFIER* Identifier,
_In_ PTP_FIFO_INTERFACE_CAPABILITY* Capability) _In_ PTP_FIFO_INTERFACE_CAPABILITY* Capability)
{ {
if ((Identifier->Bits.InterfaceType == if ((Identifier->Bits.InterfaceType ==
@ -441,11 +451,11 @@ TpmExtractInterfaceTypeFromCapabilityAndId(
*/ */
STATIC STATIC
NTSTATUS NTSTATUS
TpmGetPtpInterfaceType(_In_ PVOID Register, TpmGetPtpInterfaceType(
_Out_ TPM2_PTP_INTERFACE_TYPE* InterfaceType) _In_ PVOID Register, _Out_ TPM2_PTP_INTERFACE_TYPE* InterfaceType)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PTP_CRB_INTERFACE_IDENTIFIER identifier = {0}; PTP_CRB_INTERFACE_IDENTIFIER identifier = {0};
PTP_FIFO_INTERFACE_CAPABILITY capability = {0}; PTP_FIFO_INTERFACE_CAPABILITY capability = {0};
*InterfaceType = 0; *InterfaceType = 0;
@ -481,9 +491,9 @@ TpmGetPtpInterfaceType(_In_ PVOID Register,
NTSTATUS NTSTATUS
TpmExtractEndorsementKey() TpmExtractEndorsementKey()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
BOOLEAN presence = FALSE; BOOLEAN presence = FALSE;
TPM2_PTP_INTERFACE_TYPE type = {0}; TPM2_PTP_INTERFACE_TYPE type = {0};
if (!TpmIsPlatformSupported()) if (!TpmIsPlatformSupported())
return STATUS_NOT_SUPPORTED; return STATUS_NOT_SUPPORTED;
@ -512,23 +522,24 @@ TpmExtractEndorsementKey()
} }
NTSTATUS NTSTATUS
CryptHashBuffer_sha256(_In_ PVOID Buffer, CryptHashBuffer_sha256(
_In_ ULONG BufferSize, _In_ PVOID Buffer,
_Out_ PVOID* HashResult, _In_ ULONG BufferSize,
_Out_ PULONG HashResultSize) _Out_ PVOID* HashResult,
_Out_ PULONG HashResultSize)
{ {
PAGED_CODE(); PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
BCRYPT_ALG_HANDLE* algo_handle = GetCryptHandle_Sha256(); BCRYPT_ALG_HANDLE* algo_handle = GetCryptHandle_Sha256();
BCRYPT_HASH_HANDLE hash_handle = NULL; BCRYPT_HASH_HANDLE hash_handle = NULL;
ULONG bytes_copied = 0; ULONG bytes_copied = 0;
ULONG resulting_hash_size = 0; ULONG resulting_hash_size = 0;
ULONG hash_object_size = 0; ULONG hash_object_size = 0;
PCHAR hash_object = NULL; PCHAR hash_object = NULL;
PCHAR resulting_hash = NULL; PCHAR resulting_hash = NULL;
*HashResult = NULL; *HashResult = NULL;
*HashResultSize = 0; *HashResultSize = 0;
/* /*
@ -536,21 +547,23 @@ CryptHashBuffer_sha256(_In_ PVOID Buffer,
* the buffer that will store the resulting hash, instead this will be * the buffer that will store the resulting hash, instead this will be
* used to store the hash object used to create the hash. * used to store the hash object used to create the hash.
*/ */
status = BCryptGetProperty(*algo_handle, status = BCryptGetProperty(
BCRYPT_OBJECT_LENGTH, *algo_handle,
(PCHAR)&hash_object_size, BCRYPT_OBJECT_LENGTH,
sizeof(ULONG), (PCHAR)&hash_object_size,
&bytes_copied, sizeof(ULONG),
NULL); &bytes_copied,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("BCryptGetProperty failed with status %x", status); DEBUG_ERROR("BCryptGetProperty failed with status %x", status);
goto end; goto end;
} }
hash_object = ImpExAllocatePool2(POOL_FLAG_NON_PAGED, hash_object = ImpExAllocatePool2(
hash_object_size, POOL_FLAG_NON_PAGED,
POOL_TAG_INTEGRITY); hash_object_size,
POOL_TAG_INTEGRITY);
if (!hash_object) { if (!hash_object) {
status = STATUS_MEMORY_NOT_ALLOCATED; status = STATUS_MEMORY_NOT_ALLOCATED;
@ -561,21 +574,23 @@ CryptHashBuffer_sha256(_In_ PVOID Buffer,
* This call gets the size of the resulting hash, which we will use to * This call gets the size of the resulting hash, which we will use to
* allocate the resulting hash buffer. * allocate the resulting hash buffer.
*/ */
status = BCryptGetProperty(*algo_handle, status = BCryptGetProperty(
BCRYPT_HASH_LENGTH, *algo_handle,
(PCHAR)&resulting_hash_size, BCRYPT_HASH_LENGTH,
sizeof(ULONG), (PCHAR)&resulting_hash_size,
&bytes_copied, sizeof(ULONG),
NULL); &bytes_copied,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("BCryptGetProperty failed with status %x", status); DEBUG_ERROR("BCryptGetProperty failed with status %x", status);
goto end; goto end;
} }
resulting_hash = ImpExAllocatePool2(POOL_FLAG_NON_PAGED, resulting_hash = ImpExAllocatePool2(
resulting_hash_size, POOL_FLAG_NON_PAGED,
POOL_TAG_INTEGRITY); resulting_hash_size,
POOL_TAG_INTEGRITY);
if (!resulting_hash) { if (!resulting_hash) {
status = STATUS_MEMORY_NOT_ALLOCATED; status = STATUS_MEMORY_NOT_ALLOCATED;
@ -586,13 +601,14 @@ CryptHashBuffer_sha256(_In_ PVOID Buffer,
* Here we create our hash object and store it in the hash_object * Here we create our hash object and store it in the hash_object
* buffer. * buffer.
*/ */
status = BCryptCreateHash(*algo_handle, status = BCryptCreateHash(
&hash_handle, *algo_handle,
hash_object, &hash_handle,
hash_object_size, hash_object,
NULL, hash_object_size,
NULL, NULL,
NULL); NULL,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("BCryptCreateHash failed with status %x", status); DEBUG_ERROR("BCryptCreateHash failed with status %x", status);
@ -615,17 +631,18 @@ CryptHashBuffer_sha256(_In_ PVOID Buffer,
* As said in the previous comment, this is where we retrieve the final * As said in the previous comment, this is where we retrieve the final
* hash and store it in our output buffer. * hash and store it in our output buffer.
*/ */
status = BCryptFinishHash(hash_handle, status = BCryptFinishHash(
resulting_hash, hash_handle,
resulting_hash_size, resulting_hash,
NULL); resulting_hash_size,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("BCryptFinishHash failed with status %x", status); DEBUG_ERROR("BCryptFinishHash failed with status %x", status);
goto end; goto end;
} }
*HashResult = resulting_hash; *HashResult = resulting_hash;
*HashResultSize = resulting_hash_size; *HashResultSize = resulting_hash_size;
end: end:

View file

@ -1,18 +1,18 @@
#include "driver.h" #include "driver.h"
#include "common.h"
#include "io.h"
#include "callbacks.h"
#include "hv.h"
#include "pool.h"
#include "thread.h"
#include "modules.h"
#include "integrity.h"
#include "imports.h"
#include "apc.h" #include "apc.h"
#include "callbacks.h"
#include "common.h"
#include "crypt.h" #include "crypt.h"
#include "session.h" #include "hv.h"
#include "hw.h" #include "hw.h"
#include "imports.h"
#include "integrity.h"
#include "io.h"
#include "modules.h"
#include "pool.h"
#include "session.h"
#include "thread.h"
#include "lib/stdlib.h" #include "lib/stdlib.h"
@ -24,17 +24,18 @@ DriverUnload(_In_ PDRIVER_OBJECT DriverObject);
_Function_class_(DRIVER_INITIALIZE) _IRQL_requires_same_ _Function_class_(DRIVER_INITIALIZE) _IRQL_requires_same_
NTSTATUS NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, DriverEntry(
_In_ PUNICODE_STRING RegistryPath); _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath);
STATIC STATIC
NTSTATUS NTSTATUS
RegistryPathQueryCallbackRoutine(IN PWSTR ValueName, RegistryPathQueryCallbackRoutine(
IN ULONG ValueType, IN PWSTR ValueName,
IN PVOID ValueData, IN ULONG ValueType,
IN ULONG ValueLength, IN PVOID ValueData,
IN PVOID Context, IN ULONG ValueLength,
IN PVOID EntryContext); IN PVOID Context,
IN PVOID EntryContext);
STATIC STATIC
VOID VOID
@ -58,8 +59,8 @@ DrvLoadEnableNotifyRoutines();
STATIC STATIC
NTSTATUS NTSTATUS
DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject, DrvLoadInitialiseDriverConfig(
_In_ PUNICODE_STRING RegistryPath); _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath);
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
# pragma alloc_text(INIT, DriverEntry) # pragma alloc_text(INIT, DriverEntry)
@ -79,33 +80,33 @@ DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject,
#endif #endif
typedef struct _DRIVER_CONFIG { typedef struct _DRIVER_CONFIG {
volatile UINT32 nmi_status; volatile UINT32 nmi_status;
UNICODE_STRING unicode_driver_name; UNICODE_STRING unicode_driver_name;
ANSI_STRING ansi_driver_name; ANSI_STRING ansi_driver_name;
PUNICODE_STRING device_name; PUNICODE_STRING device_name;
PUNICODE_STRING device_symbolic_link; PUNICODE_STRING device_symbolic_link;
UNICODE_STRING driver_path; UNICODE_STRING driver_path;
UNICODE_STRING registry_path; UNICODE_STRING registry_path;
SYSTEM_INFORMATION system_information; SYSTEM_INFORMATION system_information;
PVOID apc_contexts[MAXIMUM_APC_CONTEXTS]; PVOID apc_contexts[MAXIMUM_APC_CONTEXTS];
PDRIVER_OBJECT driver_object; PDRIVER_OBJECT driver_object;
PDEVICE_OBJECT device_object; PDEVICE_OBJECT device_object;
volatile BOOLEAN unload_in_progress; volatile BOOLEAN unload_in_progress;
KGUARDED_MUTEX lock; KGUARDED_MUTEX lock;
SYS_MODULE_VAL_CONTEXT sys_val_context; SYS_MODULE_VAL_CONTEXT sys_val_context;
IRP_QUEUE_HEAD irp_queue; IRP_QUEUE_HEAD irp_queue;
TIMER_OBJECT integrity_check_timer; TIMER_OBJECT integrity_check_timer;
ACTIVE_SESSION session_information; ACTIVE_SESSION session_information;
RB_TREE thread_tree; RB_TREE thread_tree;
DRIVER_LIST_HEAD driver_list; DRIVER_LIST_HEAD driver_list;
RTL_HASHMAP process_hashmap; RTL_HASHMAP process_hashmap;
SHARED_MAPPING mapping; SHARED_MAPPING mapping;
BOOLEAN has_driver_loaded; BOOLEAN has_driver_loaded;
BCRYPT_ALG_HANDLE aes_hash; BCRYPT_ALG_HANDLE aes_hash;
BCRYPT_ALG_HANDLE sha256_hash; BCRYPT_ALG_HANDLE sha256_hash;
} DRIVER_CONFIG, *PDRIVER_CONFIG; } DRIVER_CONFIG, *PDRIVER_CONFIG;
UNICODE_STRING g_DeviceName = RTL_CONSTANT_STRING(L"\\Device\\DonnaAC"); UNICODE_STRING g_DeviceName = RTL_CONSTANT_STRING(L"\\Device\\DonnaAC");
UNICODE_STRING g_DeviceSymbolicLink = RTL_CONSTANT_STRING(L"\\??\\DonnaAC"); UNICODE_STRING g_DeviceSymbolicLink = RTL_CONSTANT_STRING(L"\\??\\DonnaAC");
/* xor key generated on driver entry used to encrypt the imports array. Kept in /* xor key generated on driver entry used to encrypt the imports array. Kept in
@ -218,9 +219,10 @@ BOOLEAN
IsNmiInProgress() IsNmiInProgress()
{ {
PAGED_CODE(); PAGED_CODE();
return InterlockedCompareExchange(&GetDecryptedDriverConfig()->nmi_status, return InterlockedCompareExchange(
TRUE, &GetDecryptedDriverConfig()->nmi_status,
FALSE) != 0; TRUE,
FALSE) != 0;
} }
PSHARED_MAPPING PSHARED_MAPPING
@ -255,8 +257,9 @@ BOOLEAN
IsDriverUnloading() IsDriverUnloading()
{ {
PAGED_CODE(); PAGED_CODE();
return InterlockedExchange(&GetDecryptedDriverConfig()->unload_in_progress, return InterlockedExchange(
GetDecryptedDriverConfig()->unload_in_progress); &GetDecryptedDriverConfig()->unload_in_progress,
GetDecryptedDriverConfig()->unload_in_progress);
} }
PACTIVE_SESSION PACTIVE_SESSION
@ -492,16 +495,18 @@ DrvLoadEnableNotifyRoutines()
status = PsSetLoadImageNotifyRoutine(ImageLoadNotifyRoutineCallback); status = PsSetLoadImageNotifyRoutine(ImageLoadNotifyRoutineCallback);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsSetLoadImageNotifyRoutine failed with status %x", DEBUG_ERROR(
status); "PsSetLoadImageNotifyRoutine failed with status %x",
status);
return status; return status;
} }
status = ImpPsSetCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine); status = ImpPsSetCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsSetCreateThreadNotifyRoutine failed with status %x", DEBUG_ERROR(
status); "PsSetCreateThreadNotifyRoutine failed with status %x",
status);
PsRemoveLoadImageNotifyRoutine(ImageLoadNotifyRoutineCallback); PsRemoveLoadImageNotifyRoutine(ImageLoadNotifyRoutineCallback);
return status; return status;
} }
@ -510,8 +515,9 @@ DrvLoadEnableNotifyRoutines()
ImpPsSetCreateProcessNotifyRoutine(ProcessCreateNotifyRoutine, FALSE); ImpPsSetCreateProcessNotifyRoutine(ProcessCreateNotifyRoutine, FALSE);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsSetCreateProcessNotifyRoutine failed with status %x", DEBUG_ERROR(
status); "PsSetCreateProcessNotifyRoutine failed with status %x",
status);
ImpPsRemoveCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine); ImpPsRemoveCreateThreadNotifyRoutine(ThreadCreateNotifyRoutine);
PsRemoveLoadImageNotifyRoutine(ImageLoadNotifyRoutineCallback); PsRemoveLoadImageNotifyRoutine(ImageLoadNotifyRoutineCallback);
return status; return status;
@ -571,20 +577,21 @@ DrvLoadSetupDriverLists()
STATIC STATIC
NTSTATUS NTSTATUS
RegistryPathQueryCallbackRoutine(IN PWSTR ValueName, RegistryPathQueryCallbackRoutine(
IN ULONG ValueType, IN PWSTR ValueName,
IN PVOID ValueData, IN ULONG ValueType,
IN ULONG ValueLength, IN PVOID ValueData,
IN PVOID Context, IN ULONG ValueLength,
IN PVOID EntryContext) IN PVOID Context,
IN PVOID EntryContext)
{ {
PAGED_CODE(); PAGED_CODE();
UNICODE_STRING value_name = {0}; UNICODE_STRING value_name = {0};
UNICODE_STRING image_path = RTL_CONSTANT_STRING(L"ImagePath"); UNICODE_STRING image_path = RTL_CONSTANT_STRING(L"ImagePath");
UNICODE_STRING display_name = RTL_CONSTANT_STRING(L"DisplayName"); UNICODE_STRING display_name = RTL_CONSTANT_STRING(L"DisplayName");
UNICODE_STRING value = {0}; UNICODE_STRING value = {0};
PVOID temp_buffer = NULL; PVOID temp_buffer = NULL;
ImpRtlInitUnicodeString(&value_name, ValueName); ImpRtlInitUnicodeString(&value_name, ValueName);
@ -599,26 +606,28 @@ RegistryPathQueryCallbackRoutine(IN PWSTR ValueName,
IntCopyMemory(temp_buffer, ValueData, ValueLength); IntCopyMemory(temp_buffer, ValueData, ValueLength);
cfg->driver_path.Buffer = (PWCH)temp_buffer; cfg->driver_path.Buffer = (PWCH)temp_buffer;
cfg->driver_path.Length = ValueLength; cfg->driver_path.Length = ValueLength;
cfg->driver_path.MaximumLength = ValueLength; cfg->driver_path.MaximumLength = ValueLength;
} }
if (ImpRtlCompareUnicodeString(&value_name, &display_name, FALSE) == if (ImpRtlCompareUnicodeString(&value_name, &display_name, FALSE) ==
FALSE) { FALSE) {
temp_buffer = ImpExAllocatePool2(POOL_FLAG_PAGED, temp_buffer = ImpExAllocatePool2(
ValueLength + 20, POOL_FLAG_PAGED,
POOL_TAG_STRINGS); ValueLength + 20,
POOL_TAG_STRINGS);
if (!temp_buffer) if (!temp_buffer)
return STATUS_MEMORY_NOT_ALLOCATED; return STATUS_MEMORY_NOT_ALLOCATED;
IntCopyMemory(temp_buffer, ValueData, ValueLength); IntCopyMemory(temp_buffer, ValueData, ValueLength);
IntWideStringCopy((PWCH)((UINT64)temp_buffer + ValueLength - 2), IntWideStringCopy(
L".sys"); (PWCH)((UINT64)temp_buffer + ValueLength - 2),
L".sys");
cfg->unicode_driver_name.Buffer = (PWCH)temp_buffer; cfg->unicode_driver_name.Buffer = (PWCH)temp_buffer;
cfg->unicode_driver_name.Length = ValueLength + 20; cfg->unicode_driver_name.Length = ValueLength + 20;
cfg->unicode_driver_name.MaximumLength = ValueLength + 20; cfg->unicode_driver_name.MaximumLength = ValueLength + 20;
} }
@ -644,15 +653,16 @@ STATIC
NTSTATUS NTSTATUS
GetSystemProcessorType() GetSystemProcessorType()
{ {
UINT32 cpuid[4] = {0}; UINT32 cpuid[4] = {0};
PDRIVER_CONFIG cfg = GetDecryptedDriverConfig(); PDRIVER_CONFIG cfg = GetDecryptedDriverConfig();
__cpuid(cpuid, 0); __cpuid(cpuid, 0);
DEBUG_VERBOSE("Cpuid: EBX: %lx, ECX: %lx, EDX: %lx", DEBUG_VERBOSE(
cpuid[1], "Cpuid: EBX: %lx, ECX: %lx, EDX: %lx",
cpuid[2], cpuid[1],
cpuid[3]); cpuid[2],
cpuid[3]);
if (cpuid[EBX_REGISTER] == CPUID_AUTHENTIC_AMD_EBX && if (cpuid[EBX_REGISTER] == CPUID_AUTHENTIC_AMD_EBX &&
cpuid[ECX_REGISTER] == CPUID_AUTHENTIC_AMD_ECX && cpuid[ECX_REGISTER] == CPUID_AUTHENTIC_AMD_ECX &&
@ -660,9 +670,10 @@ GetSystemProcessorType()
cfg->system_information.processor = AuthenticAmd; cfg->system_information.processor = AuthenticAmd;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
else if (cpuid[EBX_REGISTER] == CPUID_GENUINE_INTEL_EBX && else if (
cpuid[ECX_REGISTER] == CPUID_GENUINE_INTEL_ECX && cpuid[EBX_REGISTER] == CPUID_GENUINE_INTEL_EBX &&
cpuid[EDX_REGISTER] == CPUID_GENUINE_INTEL_EDX) { cpuid[ECX_REGISTER] == CPUID_GENUINE_INTEL_ECX &&
cpuid[EDX_REGISTER] == CPUID_GENUINE_INTEL_EDX) {
cfg->system_information.processor = GenuineIntel; cfg->system_information.processor = GenuineIntel;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -681,13 +692,14 @@ STATIC
NTSTATUS NTSTATUS
ParseSmbiosForGivenSystemEnvironment() ParseSmbiosForGivenSystemEnvironment()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PDRIVER_CONFIG cfg = GetDecryptedDriverConfig(); PDRIVER_CONFIG cfg = GetDecryptedDriverConfig();
status = ParseSMBIOSTable(&cfg->system_information.vendor, status = ParseSMBIOSTable(
VENDOR_STRING_MAX_LENGTH, &cfg->system_information.vendor,
SmbiosInformation, VENDOR_STRING_MAX_LENGTH,
SMBIOS_VENDOR_STRING_SUB_INDEX); SmbiosInformation,
SMBIOS_VENDOR_STRING_SUB_INDEX);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ParseSMBIOSTable failed with status %x", status); DEBUG_ERROR("ParseSMBIOSTable failed with status %x", status);
@ -703,17 +715,19 @@ ParseSmbiosForGivenSystemEnvironment()
switch (cfg->system_information.environment) { switch (cfg->system_information.environment) {
case NativeWindows: { case NativeWindows: {
status = ParseSMBIOSTable(&cfg->system_information.motherboard_serial, status = ParseSMBIOSTable(
MOTHERBOARD_SERIAL_CODE_LENGTH, &cfg->system_information.motherboard_serial,
VendorSpecificInformation, MOTHERBOARD_SERIAL_CODE_LENGTH,
SMBIOS_NATIVE_SERIAL_NUMBER_SUB_INDEX); VendorSpecificInformation,
SMBIOS_NATIVE_SERIAL_NUMBER_SUB_INDEX);
break; break;
} }
case Vmware: { case Vmware: {
status = ParseSMBIOSTable(&cfg->system_information.motherboard_serial, status = ParseSMBIOSTable(
MOTHERBOARD_SERIAL_CODE_LENGTH, &cfg->system_information.motherboard_serial,
SystemInformation, MOTHERBOARD_SERIAL_CODE_LENGTH,
SMBIOS_VMWARE_SERIAL_NUMBER_SUB_INDEX); SystemInformation,
SMBIOS_VMWARE_SERIAL_NUMBER_SUB_INDEX);
break; break;
} }
case VirtualBox: case VirtualBox:
@ -734,8 +748,8 @@ STATIC
NTSTATUS NTSTATUS
DrvLoadGatherSystemEnvironmentSettings() DrvLoadGatherSystemEnvironmentSettings()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PDRIVER_CONFIG cfg = GetDecryptedDriverConfig(); PDRIVER_CONFIG cfg = GetDecryptedDriverConfig();
if (APERFMsrTimingCheck()) if (APERFMsrTimingCheck())
cfg->system_information.virtualised_environment = TRUE; cfg->system_information.virtualised_environment = TRUE;
@ -768,8 +782,9 @@ DrvLoadGatherSystemEnvironmentSettings()
sizeof(cfg->system_information.drive_0_serial)); sizeof(cfg->system_information.drive_0_serial));
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("GetHardDiskDriverSerialNumber failed with status %x", DEBUG_ERROR(
status); "GetHardDiskDriverSerialNumber failed with status %x",
status);
return status; return status;
} }
@ -780,8 +795,9 @@ DrvLoadGatherSystemEnvironmentSettings()
cfg->system_information.os_information.dwBuildNumber); cfg->system_information.os_information.dwBuildNumber);
DEBUG_VERBOSE("Environment type: %lx", cfg->system_information.environment); DEBUG_VERBOSE("Environment type: %lx", cfg->system_information.environment);
DEBUG_VERBOSE("Processor type: %lx", cfg->system_information.processor); DEBUG_VERBOSE("Processor type: %lx", cfg->system_information.processor);
DEBUG_VERBOSE("Motherboard serial: %s", DEBUG_VERBOSE(
cfg->system_information.motherboard_serial); "Motherboard serial: %s",
cfg->system_information.motherboard_serial);
DEBUG_VERBOSE("Drive 0 serial: %s", cfg->system_information.drive_0_serial); DEBUG_VERBOSE("Drive 0 serial: %s", cfg->system_information.drive_0_serial);
return status; return status;
@ -791,31 +807,32 @@ STATIC
NTSTATUS NTSTATUS
DrvLoadRetrieveDriverNameFromRegistry(_In_ PUNICODE_STRING RegistryPath) DrvLoadRetrieveDriverNameFromRegistry(_In_ PUNICODE_STRING RegistryPath)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PDRIVER_CONFIG cfg = GetDecryptedDriverConfig(); PDRIVER_CONFIG cfg = GetDecryptedDriverConfig();
RTL_QUERY_REGISTRY_TABLE query[3] = {0}; RTL_QUERY_REGISTRY_TABLE query[3] = {0};
query[0].Flags = RTL_QUERY_REGISTRY_NOEXPAND; query[0].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
query[0].Name = L"ImagePath"; query[0].Name = L"ImagePath";
query[0].DefaultType = REG_MULTI_SZ; query[0].DefaultType = REG_MULTI_SZ;
query[0].DefaultLength = 0; query[0].DefaultLength = 0;
query[0].DefaultData = NULL; query[0].DefaultData = NULL;
query[0].EntryContext = NULL; query[0].EntryContext = NULL;
query[0].QueryRoutine = RegistryPathQueryCallbackRoutine; query[0].QueryRoutine = RegistryPathQueryCallbackRoutine;
query[1].Flags = RTL_QUERY_REGISTRY_NOEXPAND; query[1].Flags = RTL_QUERY_REGISTRY_NOEXPAND;
query[1].Name = L"DisplayName"; query[1].Name = L"DisplayName";
query[1].DefaultType = REG_SZ; query[1].DefaultType = REG_SZ;
query[1].DefaultLength = 0; query[1].DefaultLength = 0;
query[1].DefaultData = NULL; query[1].DefaultData = NULL;
query[1].EntryContext = NULL; query[1].EntryContext = NULL;
query[1].QueryRoutine = RegistryPathQueryCallbackRoutine; query[1].QueryRoutine = RegistryPathQueryCallbackRoutine;
status = RtlxQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, status = RtlxQueryRegistryValues(
RegistryPath->Buffer, RTL_REGISTRY_ABSOLUTE,
&query, RegistryPath->Buffer,
NULL, &query,
NULL); NULL,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("RtlxQueryRegistryValues failed with status %x", status); DEBUG_ERROR("RtlxQueryRegistryValues failed with status %x", status);
@ -828,13 +845,15 @@ DrvLoadRetrieveDriverNameFromRegistry(_In_ PUNICODE_STRING RegistryPath)
* name since we need the .sys extension when querying the system * name since we need the .sys extension when querying the system
* modules for our driver. * modules for our driver.
*/ */
status = ImpRtlUnicodeStringToAnsiString(&cfg->ansi_driver_name, status = ImpRtlUnicodeStringToAnsiString(
&cfg->unicode_driver_name, &cfg->ansi_driver_name,
TRUE); &cfg->unicode_driver_name,
TRUE);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("RtlUnicodeStringToAnsiString failed with status %x", DEBUG_ERROR(
status); "RtlUnicodeStringToAnsiString failed with status %x",
status);
} }
return status; return status;
@ -842,23 +861,23 @@ DrvLoadRetrieveDriverNameFromRegistry(_In_ PUNICODE_STRING RegistryPath)
STATIC STATIC
NTSTATUS NTSTATUS
DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject, DrvLoadInitialiseDriverConfig(
_In_ PUNICODE_STRING RegistryPath) _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{ {
PAGED_CODE(); PAGED_CODE();
DEBUG_VERBOSE("Initialising driver configuration"); DEBUG_VERBOSE("Initialising driver configuration");
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PDRIVER_CONFIG cfg = GetDecryptedDriverConfig(); PDRIVER_CONFIG cfg = GetDecryptedDriverConfig();
ImpKeInitializeGuardedMutex(&cfg->lock); ImpKeInitializeGuardedMutex(&cfg->lock);
IrpQueueInitialise(); IrpQueueInitialise();
SessionInitialiseCallbackConfiguration(); SessionInitialiseCallbackConfiguration();
cfg->unload_in_progress = FALSE; cfg->unload_in_progress = FALSE;
cfg->system_information.virtualised_environment = FALSE; cfg->system_information.virtualised_environment = FALSE;
cfg->sys_val_context.active = FALSE; cfg->sys_val_context.active = FALSE;
status = DrvLoadRetrieveDriverNameFromRegistry(RegistryPath); status = DrvLoadRetrieveDriverNameFromRegistry(RegistryPath);
@ -873,8 +892,9 @@ DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject,
status = DrvLoadGatherSystemEnvironmentSettings(); status = DrvLoadGatherSystemEnvironmentSettings();
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("GatherSystemEnvironmentSettings failed with status %x", DEBUG_ERROR(
status); "GatherSystemEnvironmentSettings failed with status %x",
status);
return status; return status;
} }
@ -900,13 +920,14 @@ STATIC
NTSTATUS NTSTATUS
InitialiseHashingAlgorithmProvider() InitialiseHashingAlgorithmProvider()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
BCRYPT_ALG_HANDLE* handle = GetCryptHandle_Sha256(); BCRYPT_ALG_HANDLE* handle = GetCryptHandle_Sha256();
status = BCryptOpenAlgorithmProvider(handle, status = BCryptOpenAlgorithmProvider(
BCRYPT_SHA256_ALGORITHM, handle,
NULL, BCRYPT_SHA256_ALGORITHM,
BCRYPT_PROV_DISPATCH); NULL,
BCRYPT_PROV_DISPATCH);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("BCryptOpenAlgorithmProvider: %x", status); DEBUG_ERROR("BCryptOpenAlgorithmProvider: %x", status);
@ -917,13 +938,13 @@ InitialiseHashingAlgorithmProvider()
NTSTATUS NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{ {
BOOLEAN flag = FALSE; BOOLEAN flag = FALSE;
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreate; DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
DriverObject->DriverUnload = DriverUnload; DriverObject->DriverUnload = DriverUnload;
g_DeviceExtensionKey = CryptXorKeyGenerate_uint64(); g_DeviceExtensionKey = CryptXorKeyGenerate_uint64();
@ -934,23 +955,24 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
DEBUG_VERBOSE("Beginning driver entry routine..."); DEBUG_VERBOSE("Beginning driver entry routine...");
status = ImpIoCreateDevice(DriverObject, status = ImpIoCreateDevice(
sizeof(DRIVER_CONFIG), DriverObject,
&g_DeviceName, sizeof(DRIVER_CONFIG),
FILE_DEVICE_UNKNOWN, &g_DeviceName,
FILE_DEVICE_SECURE_OPEN, FILE_DEVICE_UNKNOWN,
FALSE, FILE_DEVICE_SECURE_OPEN,
&DriverObject->DeviceObject); FALSE,
&DriverObject->DeviceObject);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("IoCreateDevice failed with status %x", status); DEBUG_ERROR("IoCreateDevice failed with status %x", status);
return status; return status;
} }
g_DriverConfig = DriverObject->DeviceObject->DeviceExtension; g_DriverConfig = DriverObject->DeviceObject->DeviceExtension;
g_DriverConfig->device_object = DriverObject->DeviceObject; g_DriverConfig->device_object = DriverObject->DeviceObject;
g_DriverConfig->driver_object = DriverObject; g_DriverConfig->driver_object = DriverObject;
g_DriverConfig->device_name = &g_DeviceName; g_DriverConfig->device_name = &g_DeviceName;
g_DriverConfig->device_symbolic_link = &g_DeviceSymbolicLink; g_DriverConfig->device_symbolic_link = &g_DeviceSymbolicLink;
EncryptDeviceExtensionPointers(DriverObject->DeviceObject); EncryptDeviceExtensionPointers(DriverObject->DeviceObject);
@ -958,8 +980,9 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
status = DrvLoadInitialiseDriverConfig(DriverObject, RegistryPath); status = DrvLoadInitialiseDriverConfig(DriverObject, RegistryPath);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("InitialiseDriverConfigOnDriverEntry failed with status %x", DEBUG_ERROR(
status); "InitialiseDriverConfigOnDriverEntry failed with status %x",
status);
DrvUnloadFreeConfigStrings(); DrvUnloadFreeConfigStrings();
ImpIoDeleteDevice(GetDecryptedDriverConfig()->device_object); ImpIoDeleteDevice(GetDecryptedDriverConfig()->device_object);
return status; return status;
@ -975,9 +998,9 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
return status; return status;
} }
status = status = IoCreateSymbolicLink(
IoCreateSymbolicLink(GetDecryptedDriverConfig()->device_symbolic_link, GetDecryptedDriverConfig()->device_symbolic_link,
GetDecryptedDriverConfig()->device_name); GetDecryptedDriverConfig()->device_name);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("IoCreateSymbolicLink failed with status %x", status); DEBUG_ERROR("IoCreateSymbolicLink failed with status %x", status);
@ -1001,8 +1024,9 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
status = InitialiseHashingAlgorithmProvider(); status = InitialiseHashingAlgorithmProvider();
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("InitialiseHashingAlgorithmProvider failed with status %x", DEBUG_ERROR(
status); "InitialiseHashingAlgorithmProvider failed with status %x",
status);
DrvUnloadFreeConfigStrings(); DrvUnloadFreeConfigStrings();
DrvUnloadFreeTimerObject(); DrvUnloadFreeTimerObject();
DrvUnloadDeleteSymbolicLink(); DrvUnloadDeleteSymbolicLink();

View file

@ -1,9 +1,9 @@
#include "hv.h" #include "hv.h"
#include <intrin.h>
#include "imports.h"
#include "common.h" #include "common.h"
#include "imports.h"
#include "io.h" #include "io.h"
#include <intrin.h>
#include "lib/stdlib.h" #include "lib/stdlib.h"
@ -29,8 +29,8 @@ APERFMsrTimingCheck()
{ {
KAFFINITY new_affinity = {0}; KAFFINITY new_affinity = {0};
KAFFINITY old_affinity = {0}; KAFFINITY old_affinity = {0};
UINT64 old_irql = 0; UINT64 old_irql = 0;
INT cpuid_result[4]; INT cpuid_result[4];
/* /*
* First thing we do is we lock the current thread to the logical * First thing we do is we lock the current thread to the logical
@ -98,14 +98,15 @@ PerformVirtualizationDetection(_Inout_ PIRP Irp)
} }
HYPERVISOR_DETECTION_REPORT report = {0}; HYPERVISOR_DETECTION_REPORT report = {0};
report.aperf_msr_timing_check = APERFMsrTimingCheck(); report.aperf_msr_timing_check = APERFMsrTimingCheck();
report.invd_emulation_check = TestINVDEmulation(); report.invd_emulation_check = TestINVDEmulation();
Irp->IoStatus.Information = sizeof(HYPERVISOR_DETECTION_REPORT); Irp->IoStatus.Information = sizeof(HYPERVISOR_DETECTION_REPORT);
IntCopyMemory(Irp->AssociatedIrp.SystemBuffer, IntCopyMemory(
&report, Irp->AssociatedIrp.SystemBuffer,
sizeof(HYPERVISOR_DETECTION_REPORT)); &report,
sizeof(HYPERVISOR_DETECTION_REPORT));
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -1,8 +1,8 @@
#include "hw.h" #include "hw.h"
#include "modules.h"
#include "crypt.h" #include "crypt.h"
#include "imports.h" #include "imports.h"
#include "modules.h"
#include "lib/stdlib.h" #include "lib/stdlib.h"
@ -15,8 +15,8 @@ USHORT FLAGGED_DEVICE_IDS[FLAGGED_DEVICE_ID_COUNT] = {
0x0666, // default PCIe Squirrel DeviceID (used by PCI Leech) 0x0666, // default PCIe Squirrel DeviceID (used by PCI Leech)
0xffff}; 0xffff};
typedef NTSTATUS (*PCI_DEVICE_CALLBACK)(_In_ PDEVICE_OBJECT DeviceObject, typedef NTSTATUS (*PCI_DEVICE_CALLBACK)(
_In_opt_ PVOID Context); _In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context);
/* /*
* Every PCI device has a set of registers commonly referred to as the PCI * Every PCI device has a set of registers commonly referred to as the PCI
@ -66,15 +66,16 @@ typedef NTSTATUS (*PCI_DEVICE_CALLBACK)(_In_ PDEVICE_OBJECT DeviceObject,
*/ */
STATIC STATIC
NTSTATUS NTSTATUS
QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject, QueryPciDeviceConfigurationSpace(
_In_ UINT32 Offset, _In_ PDEVICE_OBJECT DeviceObject,
_Out_opt_ PVOID Buffer, _In_ UINT32 Offset,
_In_ UINT32 BufferLength) _Out_opt_ PVOID Buffer,
_In_ UINT32 BufferLength)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
KEVENT event = {0}; KEVENT event = {0};
IO_STATUS_BLOCK io = {0}; IO_STATUS_BLOCK io = {0};
PIRP irp = NULL; PIRP irp = NULL;
PIO_STACK_LOCATION packet = NULL; PIO_STACK_LOCATION packet = NULL;
if (BufferLength == 0) if (BufferLength == 0)
@ -87,19 +88,25 @@ QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
* request is completed * request is completed
*/ */
irp = IoBuildSynchronousFsdRequest( irp = IoBuildSynchronousFsdRequest(
IRP_MJ_PNP, DeviceObject, NULL, 0, NULL, &event, &io); IRP_MJ_PNP,
DeviceObject,
NULL,
0,
NULL,
&event,
&io);
if (!irp) { if (!irp) {
DEBUG_ERROR("IoBuildSynchronousFsdRequest failed with no status."); DEBUG_ERROR("IoBuildSynchronousFsdRequest failed with no status.");
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
packet = IoGetNextIrpStackLocation(irp); packet = IoGetNextIrpStackLocation(irp);
packet->MinorFunction = IRP_MN_READ_CONFIG; packet->MinorFunction = IRP_MN_READ_CONFIG;
packet->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG; packet->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG;
packet->Parameters.ReadWriteConfig.Offset = Offset; packet->Parameters.ReadWriteConfig.Offset = Offset;
packet->Parameters.ReadWriteConfig.Buffer = Buffer; packet->Parameters.ReadWriteConfig.Buffer = Buffer;
packet->Parameters.ReadWriteConfig.Length = BufferLength; packet->Parameters.ReadWriteConfig.Length = BufferLength;
status = IoCallDriver(DeviceObject, irp); status = IoCallDriver(DeviceObject, irp);
@ -109,8 +116,9 @@ QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
} }
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("Failed to read configuration space with status %x", DEBUG_ERROR(
status); "Failed to read configuration space with status %x",
status);
return status; return status;
} }
@ -120,23 +128,25 @@ QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
*/ */
STATIC STATIC
NTSTATUS NTSTATUS
EnumerateDriverObjectDeviceObjects(_In_ PDRIVER_OBJECT DriverObject, EnumerateDriverObjectDeviceObjects(
_Out_ PDEVICE_OBJECT** DeviceObjectArray, _In_ PDRIVER_OBJECT DriverObject,
_Out_ PUINT32 ArrayEntries) _Out_ PDEVICE_OBJECT** DeviceObjectArray,
_Out_ PUINT32 ArrayEntries)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 object_count = 0; UINT32 object_count = 0;
PDEVICE_OBJECT* buffer = NULL; PDEVICE_OBJECT* buffer = NULL;
UINT32 buffer_size = 0; UINT32 buffer_size = 0;
*DeviceObjectArray = NULL; *DeviceObjectArray = NULL;
*ArrayEntries = 0; *ArrayEntries = 0;
status = IoEnumerateDeviceObjectList(DriverObject, NULL, 0, &object_count); status = IoEnumerateDeviceObjectList(DriverObject, NULL, 0, &object_count);
if (status != STATUS_BUFFER_TOO_SMALL) { if (status != STATUS_BUFFER_TOO_SMALL) {
DEBUG_ERROR("IoEnumerateDeviceObjectList failed with status %x", DEBUG_ERROR(
status); "IoEnumerateDeviceObjectList failed with status %x",
status);
return status; return status;
} }
@ -147,20 +157,25 @@ EnumerateDriverObjectDeviceObjects(_In_ PDRIVER_OBJECT DriverObject,
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
status = IoEnumerateDeviceObjectList( status = IoEnumerateDeviceObjectList(
DriverObject, buffer, buffer_size, &object_count); DriverObject,
buffer,
buffer_size,
&object_count);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("IoEnumerateDeviceObjectList failed with status %x", DEBUG_ERROR(
status); "IoEnumerateDeviceObjectList failed with status %x",
status);
ExFreePoolWithTag(buffer, POOL_TAG_HW); ExFreePoolWithTag(buffer, POOL_TAG_HW);
return status; return status;
} }
DEBUG_VERBOSE("EnumerateDriverObjectDeviceObjects: Object Count: %lx", DEBUG_VERBOSE(
object_count); "EnumerateDriverObjectDeviceObjects: Object Count: %lx",
object_count);
*DeviceObjectArray = buffer; *DeviceObjectArray = buffer;
*ArrayEntries = object_count; *ArrayEntries = object_count;
return status; return status;
} }
@ -195,30 +210,34 @@ IsDeviceObjectValidPdo(_In_ PDEVICE_OBJECT DeviceObject)
* given the PCI FDO which is called pci.sys. * given the PCI FDO which is called pci.sys.
*/ */
NTSTATUS NTSTATUS
EnumeratePciDeviceObjects(_In_ PCI_DEVICE_CALLBACK CallbackRoutine, EnumeratePciDeviceObjects(
_In_opt_ PVOID Context) _In_ PCI_DEVICE_CALLBACK CallbackRoutine, _In_opt_ PVOID Context)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING pci = RTL_CONSTANT_STRING(L"\\Driver\\pci"); UNICODE_STRING pci = RTL_CONSTANT_STRING(L"\\Driver\\pci");
PDRIVER_OBJECT pci_driver_object = NULL; PDRIVER_OBJECT pci_driver_object = NULL;
PDEVICE_OBJECT* pci_device_objects = NULL; PDEVICE_OBJECT* pci_device_objects = NULL;
PDEVICE_OBJECT current_device = NULL; PDEVICE_OBJECT current_device = NULL;
UINT32 pci_device_objects_count = 0; UINT32 pci_device_objects_count = 0;
status = GetDriverObjectByDriverName(&pci, &pci_driver_object); status = GetDriverObjectByDriverName(&pci, &pci_driver_object);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("GetDriverObjectByDriverName failed with status %x", DEBUG_ERROR(
status); "GetDriverObjectByDriverName failed with status %x",
status);
return status; return status;
} }
status = EnumerateDriverObjectDeviceObjects( status = EnumerateDriverObjectDeviceObjects(
pci_driver_object, &pci_device_objects, &pci_device_objects_count); pci_driver_object,
&pci_device_objects,
&pci_device_objects_count);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("EnumerateDriverObjectDeviceObjects failed with status %x", DEBUG_ERROR(
status); "EnumerateDriverObjectDeviceObjects failed with status %x",
status);
return status; return status;
} }
@ -260,11 +279,11 @@ IsPciConfigurationSpaceFlagged(_In_ PPCI_COMMON_HEADER Configuration)
STATIC STATIC
VOID VOID
ReportBlacklistedPcieDevice(_In_ PDEVICE_OBJECT DeviceObject, ReportBlacklistedPcieDevice(
_In_ PPCI_COMMON_HEADER Header) _In_ PDEVICE_OBJECT DeviceObject, _In_ PPCI_COMMON_HEADER Header)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size = CryptRequestRequiredBufferLength( UINT32 packet_size = CryptRequestRequiredBufferLength(
sizeof(BLACKLISTED_PCIE_DEVICE_REPORT)); sizeof(BLACKLISTED_PCIE_DEVICE_REPORT));
PBLACKLISTED_PCIE_DEVICE_REPORT report = PBLACKLISTED_PCIE_DEVICE_REPORT report =
@ -276,8 +295,8 @@ ReportBlacklistedPcieDevice(_In_ PDEVICE_OBJECT DeviceObject,
INIT_REPORT_PACKET(report, REPORT_BLACKLISTED_PCIE_DEVICE, 0); INIT_REPORT_PACKET(report, REPORT_BLACKLISTED_PCIE_DEVICE, 0);
report->device_object = (UINT64)DeviceObject; report->device_object = (UINT64)DeviceObject;
report->device_id = Header->DeviceID; report->device_id = Header->DeviceID;
report->vendor_id = Header->VendorID; report->vendor_id = Header->VendorID;
status = CryptEncryptBuffer(report, packet_size); status = CryptEncryptBuffer(report, packet_size);
@ -296,29 +315,35 @@ PciDeviceQueryCallback(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
{ {
UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(Context);
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PCI_COMMON_HEADER header = {0}; PCI_COMMON_HEADER header = {0};
status = QueryPciDeviceConfigurationSpace( status = QueryPciDeviceConfigurationSpace(
DeviceObject, PCI_VENDOR_ID_OFFSET, &header, sizeof(PCI_COMMON_HEADER)); DeviceObject,
PCI_VENDOR_ID_OFFSET,
&header,
sizeof(PCI_COMMON_HEADER));
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("QueryPciDeviceConfigurationSpace failed with status %x", DEBUG_ERROR(
status); "QueryPciDeviceConfigurationSpace failed with status %x",
status);
return status; return status;
} }
if (IsPciConfigurationSpaceFlagged(&header)) { if (IsPciConfigurationSpaceFlagged(&header)) {
DEBUG_VERBOSE("Flagged DeviceID found. Device: %llx, DeviceId: %lx", DEBUG_VERBOSE(
(UINT64)DeviceObject, "Flagged DeviceID found. Device: %llx, DeviceId: %lx",
header.DeviceID); (UINT64)DeviceObject,
header.DeviceID);
ReportBlacklistedPcieDevice(DeviceObject, &header); ReportBlacklistedPcieDevice(DeviceObject, &header);
} }
else { else {
DEBUG_VERBOSE("Device: %llx, DeviceID: %lx, VendorID: %lx", DEBUG_VERBOSE(
DeviceObject, "Device: %llx, DeviceID: %lx, VendorID: %lx",
header.DeviceID, DeviceObject,
header.VendorID); header.DeviceID,
header.VendorID);
} }
return status; return status;

File diff suppressed because it is too large Load diff

View file

@ -1,18 +1,18 @@
#include "io.h" #include "io.h"
#include "modules.h"
#include "driver.h"
#include "callbacks.h" #include "callbacks.h"
#include "pool.h" #include "driver.h"
#include "integrity.h" #include "integrity.h"
#include "modules.h"
#include "pool.h"
#include "thread.h" #include "thread.h"
#include "hv.h" #include "hv.h"
#include "imports.h" #include "imports.h"
#include "session.h"
#include "hw.h"
#include "containers/map.h" #include "containers/map.h"
#include "hw.h"
#include "session.h"
#include "lib/stdlib.h" #include "lib/stdlib.h"
@ -171,9 +171,9 @@ STATIC
NTSTATUS NTSTATUS
IrpQueueCompleteDeferredPacket(_In_ PDEFERRED_REPORT Report, _In_ PIRP Irp) IrpQueueCompleteDeferredPacket(_In_ PDEFERRED_REPORT Report, _In_ PIRP Irp)
{ {
NTSTATUS status = ValidateIrpOutputBuffer(Irp, Report->buffer_size); NTSTATUS status = ValidateIrpOutputBuffer(Irp, Report->buffer_size);
PIRP_QUEUE_HEAD queue = GetIrpQueueHead(); PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
UINT16 type = GetPacketType(Report->buffer); UINT16 type = GetPacketType(Report->buffer);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
return status; return status;
@ -181,9 +181,11 @@ IrpQueueCompleteDeferredPacket(_In_ PDEFERRED_REPORT Report, _In_ PIRP Irp)
IncrementPacketMetics(queue, type); IncrementPacketMetics(queue, type);
IntCopyMemory( IntCopyMemory(
Irp->AssociatedIrp.SystemBuffer, Report->buffer, Report->buffer_size); Irp->AssociatedIrp.SystemBuffer,
Report->buffer,
Report->buffer_size);
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Report->buffer_size; Irp->IoStatus.Information = Report->buffer_size;
IofCompleteRequest(Irp, IO_NO_INCREMENT); IofCompleteRequest(Irp, IO_NO_INCREMENT);
IrpQueueFreeDeferredPacket(Report); IrpQueueFreeDeferredPacket(Report);
@ -194,10 +196,10 @@ STATIC
NTSTATUS NTSTATUS
IrpQueueQueryPendingPackets(_In_ PIRP Irp) IrpQueueQueryPendingPackets(_In_ PIRP Irp)
{ {
PIRP_QUEUE_HEAD queue = GetIrpQueueHead(); PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
PDEFERRED_REPORT report = NULL; PDEFERRED_REPORT report = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
KIRQL irql = 0; KIRQL irql = 0;
/* /*
* Important we hold the lock before we call IsThereDeferredReport to * Important we hold the lock before we call IsThereDeferredReport to
@ -242,7 +244,7 @@ VOID
IrpQueueCompleteCancelledIrp(_In_ PIO_CSQ Csq, _In_ PIRP Irp) IrpQueueCompleteCancelledIrp(_In_ PIO_CSQ Csq, _In_ PIRP Irp)
{ {
UNREFERENCED_PARAMETER(Csq); UNREFERENCED_PARAMETER(Csq);
Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
ImpIofCompleteRequest(Irp, IO_NO_INCREMENT); ImpIofCompleteRequest(Irp, IO_NO_INCREMENT);
} }
@ -252,12 +254,14 @@ PDEFERRED_REPORT
IrpQueueAllocateDeferredPacket(_In_ PVOID Buffer, _In_ UINT32 BufferSize) IrpQueueAllocateDeferredPacket(_In_ PVOID Buffer, _In_ UINT32 BufferSize)
{ {
PDEFERRED_REPORT report = ImpExAllocatePool2( PDEFERRED_REPORT report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, sizeof(DEFERRED_REPORT), REPORT_POOL_TAG); POOL_FLAG_NON_PAGED,
sizeof(DEFERRED_REPORT),
REPORT_POOL_TAG);
if (!report) if (!report)
return NULL; return NULL;
report->buffer = Buffer; report->buffer = Buffer;
report->buffer_size = BufferSize; report->buffer_size = BufferSize;
return report; return report;
} }
@ -266,9 +270,8 @@ IrpQueueAllocateDeferredPacket(_In_ PVOID Buffer, _In_ UINT32 BufferSize)
STATIC STATIC
VOID VOID
IrpQueueDeferPacket(_In_ PIRP_QUEUE_HEAD Queue, IrpQueueDeferPacket(
_In_ PVOID Buffer, _In_ PIRP_QUEUE_HEAD Queue, _In_ PVOID Buffer, _In_ UINT32 BufferSize)
_In_ UINT32 BufferSize)
{ {
PDEFERRED_REPORT report = NULL; PDEFERRED_REPORT report = NULL;
/* /*
@ -300,10 +303,10 @@ STATIC
NTSTATUS NTSTATUS
IrpQueueCompletePacket(_In_ PVOID Buffer, _In_ ULONG BufferSize) IrpQueueCompletePacket(_In_ PVOID Buffer, _In_ ULONG BufferSize)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PIRP_QUEUE_HEAD queue = GetIrpQueueHead(); PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
PIRP irp = IoCsqRemoveNextIrp(&queue->csq, NULL); PIRP irp = IoCsqRemoveNextIrp(&queue->csq, NULL);
UINT16 type = GetPacketType(Buffer); UINT16 type = GetPacketType(Buffer);
/* /*
* If no irps are available in our queue, lets store it in a deferred * If no irps are available in our queue, lets store it in a deferred
@ -323,7 +326,7 @@ IrpQueueCompletePacket(_In_ PVOID Buffer, _In_ ULONG BufferSize)
*/ */
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG); ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG);
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
irp->IoStatus.Information = 0; irp->IoStatus.Information = 0;
ImpIofCompleteRequest(irp, IO_NO_INCREMENT); ImpIofCompleteRequest(irp, IO_NO_INCREMENT);
return status; return status;
@ -331,7 +334,7 @@ IrpQueueCompletePacket(_In_ PVOID Buffer, _In_ ULONG BufferSize)
IncrementPacketMetics(queue, type); IncrementPacketMetics(queue, type);
irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = BufferSize; irp->IoStatus.Information = BufferSize;
IntCopyMemory(irp->AssociatedIrp.SystemBuffer, Buffer, BufferSize); IntCopyMemory(irp->AssociatedIrp.SystemBuffer, Buffer, BufferSize);
ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG); ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG);
@ -357,9 +360,9 @@ STATIC
VOID VOID
IrpQueueFreeDeferredPackets() IrpQueueFreeDeferredPackets()
{ {
PIRP_QUEUE_HEAD queue = GetIrpQueueHead(); PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
PDEFERRED_REPORT report = NULL; PDEFERRED_REPORT report = NULL;
KIRQL irql = 0; KIRQL irql = 0;
/* just in case... */ /* just in case... */
KeAcquireGuardedMutex(&queue->deferred_reports.lock); KeAcquireGuardedMutex(&queue->deferred_reports.lock);
@ -375,21 +378,22 @@ IrpQueueFreeDeferredPackets()
NTSTATUS NTSTATUS
IrpQueueInitialise() IrpQueueInitialise()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PIRP_QUEUE_HEAD queue = GetIrpQueueHead(); PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
KeInitializeGuardedMutex(&queue->lock); KeInitializeGuardedMutex(&queue->lock);
KeInitializeGuardedMutex(&queue->deferred_reports.lock); KeInitializeGuardedMutex(&queue->deferred_reports.lock);
InitializeListHead(&queue->queue); InitializeListHead(&queue->queue);
InitializeListHead(&queue->deferred_reports.head); InitializeListHead(&queue->deferred_reports.head);
status = IoCsqInitialize(&queue->csq, status = IoCsqInitialize(
IrpQueueInsert, &queue->csq,
IrpQueueRemove, IrpQueueInsert,
IrpQueuePeekNextEntry, IrpQueueRemove,
IrpQueueAcquireLock, IrpQueuePeekNextEntry,
IrpQueueReleaseLock, IrpQueueAcquireLock,
IrpQueueCompleteCancelledIrp); IrpQueueReleaseLock,
IrpQueueCompleteCancelledIrp);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("IoCsqInitialize failed with status %x", status); DEBUG_ERROR("IoCsqInitialize failed with status %x", status);
@ -398,17 +402,18 @@ IrpQueueInitialise()
} }
VOID VOID
SharedMappingWorkRoutine(_In_ PDEVICE_OBJECT DeviceObject, SharedMappingWorkRoutine(
_In_opt_ PVOID Context) _In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
HANDLE handle = NULL; HANDLE handle = NULL;
PSHARED_MAPPING state = (PSHARED_MAPPING)Context; PSHARED_MAPPING state = (PSHARED_MAPPING)Context;
InterlockedIncrement(&state->work_item_status); InterlockedIncrement(&state->work_item_status);
DEBUG_VERBOSE("SharedMapping work routine called. OperationId: %lx", DEBUG_VERBOSE(
state->kernel_buffer->operation_id); "SharedMapping work routine called. OperationId: %lx",
state->kernel_buffer->operation_id);
switch (state->kernel_buffer->operation_id) { switch (state->kernel_buffer->operation_id) {
case ssRunNmiCallbacks: case ssRunNmiCallbacks:
@ -427,13 +432,14 @@ SharedMappingWorkRoutine(_In_ PDEVICE_OBJECT DeviceObject,
DEBUG_INFO( DEBUG_INFO(
"SHARED_STATE_OPERATION_ID: ValidateDriverObjects Received."); "SHARED_STATE_OPERATION_ID: ValidateDriverObjects Received.");
status = ImpPsCreateSystemThread(&handle, status = ImpPsCreateSystemThread(
PROCESS_ALL_ACCESS, &handle,
NULL, PROCESS_ALL_ACCESS,
NULL, NULL,
NULL, NULL,
HandleValidateDriversIOCTL, NULL,
NULL); HandleValidateDriversIOCTL,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status); DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
@ -473,8 +479,9 @@ SharedMappingWorkRoutine(_In_ PDEVICE_OBJECT DeviceObject,
status = ValidateOurDriverImage(); status = ValidateOurDriverImage();
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("VerifyInMemoryImageVsDiskImage failed with status %x", DEBUG_ERROR(
status); "VerifyInMemoryImageVsDiskImage failed with status %x",
status);
break; break;
@ -494,8 +501,9 @@ SharedMappingWorkRoutine(_In_ PDEVICE_OBJECT DeviceObject,
status = DetectEptHooksInKeyFunctions(); status = DetectEptHooksInKeyFunctions();
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("DetectEpthooksInKeyFunctions failed with status %x", DEBUG_ERROR(
status); "DetectEpthooksInKeyFunctions failed with status %x",
status);
break; break;
@ -531,8 +539,9 @@ SharedMappingWorkRoutine(_In_ PDEVICE_OBJECT DeviceObject,
status = ValidateWin32kDispatchTables(); status = ValidateWin32kDispatchTables();
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("ValidateWin32kDispatchTables failed with status %x", DEBUG_ERROR(
status); "ValidateWin32kDispatchTables failed with status %x",
status);
break; break;
@ -545,10 +554,11 @@ end:
/* again, we want to run our routine at apc level not dispatch level */ /* again, we want to run our routine at apc level not dispatch level */
VOID VOID
SharedMappingDpcRoutine(_In_ PKDPC Dpc, SharedMappingDpcRoutine(
_In_opt_ PVOID DeferredContext, _In_ PKDPC Dpc,
_In_opt_ PVOID SystemArgument1, _In_opt_ PVOID DeferredContext,
_In_opt_ PVOID SystemArgument2) _In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2)
{ {
PSHARED_MAPPING mapping = (PSHARED_MAPPING)DeferredContext; PSHARED_MAPPING mapping = (PSHARED_MAPPING)DeferredContext;
@ -556,7 +566,10 @@ SharedMappingDpcRoutine(_In_ PKDPC Dpc,
return; return;
IoQueueWorkItem( IoQueueWorkItem(
mapping->work_item, SharedMappingWorkRoutine, NormalWorkQueue, mapping); mapping->work_item,
SharedMappingWorkRoutine,
NormalWorkQueue,
mapping);
} }
#define REPEAT_TIME_15_SEC 30000 #define REPEAT_TIME_15_SEC 30000
@ -572,9 +585,9 @@ SharedMappingTerminate()
while (mapping->work_item_status) while (mapping->work_item_status)
YieldProcessor(); YieldProcessor();
mapping->active = FALSE; mapping->active = FALSE;
mapping->user_buffer = NULL; mapping->user_buffer = NULL;
mapping->size = 0; mapping->size = 0;
KeCancelTimer(&mapping->timer); KeCancelTimer(&mapping->timer);
IoFreeWorkItem(mapping->work_item); IoFreeWorkItem(mapping->work_item);
@ -589,7 +602,7 @@ NTSTATUS
SharedMappingInitialiseTimer(_In_ PSHARED_MAPPING Mapping) SharedMappingInitialiseTimer(_In_ PSHARED_MAPPING Mapping)
{ {
LARGE_INTEGER due_time = {0}; LARGE_INTEGER due_time = {0};
LONG period = 0; LONG period = 0;
due_time.QuadPart = -ABSOLUTE(SECONDS(30)); due_time.QuadPart = -ABSOLUTE(SECONDS(30));
@ -603,7 +616,10 @@ SharedMappingInitialiseTimer(_In_ PSHARED_MAPPING Mapping)
KeInitializeDpc(&Mapping->timer_dpc, SharedMappingDpcRoutine, Mapping); KeInitializeDpc(&Mapping->timer_dpc, SharedMappingDpcRoutine, Mapping);
KeInitializeTimer(&Mapping->timer); KeInitializeTimer(&Mapping->timer);
KeSetTimerEx( KeSetTimerEx(
&Mapping->timer, due_time, REPEAT_TIME_15_SEC, &Mapping->timer_dpc); &Mapping->timer,
due_time,
REPEAT_TIME_15_SEC,
&Mapping->timer_dpc);
DEBUG_VERBOSE("Initialised shared mapping event timer."); DEBUG_VERBOSE("Initialised shared mapping event timer.");
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -611,16 +627,17 @@ SharedMappingInitialiseTimer(_In_ PSHARED_MAPPING Mapping)
STATIC STATIC
VOID VOID
InitSharedMappingStructure(_Out_ PSHARED_MAPPING Mapping, InitSharedMappingStructure(
_In_ PVOID KernelBuffer, _Out_ PSHARED_MAPPING Mapping,
_In_ PVOID UserBuffer, _In_ PVOID KernelBuffer,
_In_ PMDL Mdl) _In_ PVOID UserBuffer,
_In_ PMDL Mdl)
{ {
Mapping->kernel_buffer = (PSHARED_STATE)KernelBuffer; Mapping->kernel_buffer = (PSHARED_STATE)KernelBuffer;
Mapping->user_buffer = UserBuffer; Mapping->user_buffer = UserBuffer;
Mapping->mdl = Mdl; Mapping->mdl = Mdl;
Mapping->size = PAGE_SIZE; Mapping->size = PAGE_SIZE;
Mapping->active = TRUE; Mapping->active = TRUE;
Mapping->work_item_status = FALSE; Mapping->work_item_status = FALSE;
} }
@ -628,13 +645,13 @@ STATIC
NTSTATUS NTSTATUS
SharedMappingInitialise(_In_ PIRP Irp) SharedMappingInitialise(_In_ PIRP Irp)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PMDL mdl = NULL; PMDL mdl = NULL;
PSHARED_MAPPING mapping = NULL; PSHARED_MAPPING mapping = NULL;
PSHARED_MAPPING_INIT mapping_init = NULL; PSHARED_MAPPING_INIT mapping_init = NULL;
PEPROCESS process = NULL; PEPROCESS process = NULL;
PVOID buffer = NULL; PVOID buffer = NULL;
PVOID user_buffer = NULL; PVOID user_buffer = NULL;
mapping = GetSharedMappingConfig(); mapping = GetSharedMappingConfig();
@ -667,18 +684,19 @@ SharedMappingInitialise(_In_ PIRP Irp)
MmBuildMdlForNonPagedPool(mdl); MmBuildMdlForNonPagedPool(mdl);
__try { __try {
user_buffer = MmMapLockedPagesSpecifyCache(mdl, user_buffer = MmMapLockedPagesSpecifyCache(
UserMode, mdl,
MmCached, UserMode,
NULL, MmCached,
FALSE, NULL,
NormalPagePriority | FALSE,
MdlMappingNoExecute); NormalPagePriority | MdlMappingNoExecute);
} }
__except (EXCEPTION_EXECUTE_HANDLER) { __except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode(); status = GetExceptionCode();
DEBUG_ERROR("MmMapLockedPagesSpecifyCache failed with status %x", DEBUG_ERROR(
status); "MmMapLockedPagesSpecifyCache failed with status %x",
status);
IoFreeMdl(mdl); IoFreeMdl(mdl);
ExFreePoolWithTag(buffer, POOL_TAG_INTEGRITY); ExFreePoolWithTag(buffer, POOL_TAG_INTEGRITY);
return status; return status;
@ -689,7 +707,7 @@ SharedMappingInitialise(_In_ PIRP Irp)
mapping_init = (PSHARED_MAPPING_INIT)Irp->AssociatedIrp.SystemBuffer; mapping_init = (PSHARED_MAPPING_INIT)Irp->AssociatedIrp.SystemBuffer;
mapping_init->buffer = user_buffer; mapping_init->buffer = user_buffer;
mapping_init->size = PAGE_SIZE; mapping_init->size = PAGE_SIZE;
return status; return status;
} }
@ -707,14 +725,16 @@ DispatchApcOperation(_In_ PAPC_OPERATION_ID Operation)
switch (Operation->operation_id) { switch (Operation->operation_id) {
case APC_OPERATION_STACKWALK: case APC_OPERATION_STACKWALK:
DEBUG_INFO("Initiating APC stackwalk operation with operation id %i", DEBUG_INFO(
Operation->operation_id); "Initiating APC stackwalk operation with operation id %i",
Operation->operation_id);
status = ValidateThreadsViaKernelApc(); status = ValidateThreadsViaKernelApc();
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("ValidateThreadsViaKernelApc failed with status %x", DEBUG_ERROR(
status); "ValidateThreadsViaKernelApc failed with status %x",
status);
return status; return status;
@ -792,11 +812,11 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
{ {
PAGED_CODE(); PAGED_CODE();
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stack_location = IoGetCurrentIrpStackLocation(Irp); PIO_STACK_LOCATION stack_location = IoGetCurrentIrpStackLocation(Irp);
HANDLE handle = NULL; HANDLE handle = NULL;
PKTHREAD thread = NULL; PKTHREAD thread = NULL;
BOOLEAN security_flag = FALSE; BOOLEAN security_flag = FALSE;
/* /*
* LMAO * LMAO
@ -835,13 +855,14 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
* bug check under windows driver verifier. * bug check under windows driver verifier.
*/ */
status = ImpPsCreateSystemThread(&handle, status = ImpPsCreateSystemThread(
PROCESS_ALL_ACCESS, &handle,
NULL, PROCESS_ALL_ACCESS,
NULL, NULL,
NULL, NULL,
HandleValidateDriversIOCTL, NULL,
NULL); HandleValidateDriversIOCTL,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status); DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
@ -889,8 +910,9 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
status = PerformVirtualizationDetection(Irp); status = PerformVirtualizationDetection(Irp);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("PerformVirtualizationDetection failed with status %x", DEBUG_ERROR(
status); "PerformVirtualizationDetection failed with status %x",
status);
break; break;
@ -908,30 +930,32 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
DEBUG_VERBOSE("IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS Received"); DEBUG_VERBOSE("IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS Received");
status = status = ImpPsCreateSystemThread(
ImpPsCreateSystemThread(&handle, &handle,
PROCESS_ALL_ACCESS, PROCESS_ALL_ACCESS,
NULL, NULL,
NULL, NULL,
NULL, NULL,
RetrieveInMemoryModuleExecutableSections, RetrieveInMemoryModuleExecutableSections,
Irp); Irp);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status); DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
goto end; goto end;
} }
status = ImpObReferenceObjectByHandle(handle, status = ImpObReferenceObjectByHandle(
THREAD_ALL_ACCESS, handle,
*PsThreadType, THREAD_ALL_ACCESS,
KernelMode, *PsThreadType,
&thread, KernelMode,
NULL); &thread,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ObReferenceObjectbyhandle failed with status %lx", DEBUG_ERROR(
status); "ObReferenceObjectbyhandle failed with status %lx",
status);
ImpZwClose(handle); ImpZwClose(handle);
goto end; goto end;
} }
@ -982,8 +1006,9 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
status = ValidateOurDriverImage(); status = ValidateOurDriverImage();
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("VerifyInMemoryImageVsDiskImage failed with status %x", DEBUG_ERROR(
status); "VerifyInMemoryImageVsDiskImage failed with status %x",
status);
break; break;
@ -1002,8 +1027,9 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
status = ValidateProcessLoadedModule(Irp); status = ValidateProcessLoadedModule(Irp);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("ValidateProcessLoadedModule failed with status %x", DEBUG_ERROR(
status); "ValidateProcessLoadedModule failed with status %x",
status);
break; break;
@ -1017,16 +1043,18 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
status = ValidateIrpOutputBuffer(Irp, sizeof(SYSTEM_INFORMATION)); status = ValidateIrpOutputBuffer(Irp, sizeof(SYSTEM_INFORMATION));
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ValidateIrpOutputBuffer failed with status %x", DEBUG_ERROR(
status); "ValidateIrpOutputBuffer failed with status %x",
status);
goto end; goto end;
} }
Irp->IoStatus.Information = sizeof(SYSTEM_INFORMATION); Irp->IoStatus.Information = sizeof(SYSTEM_INFORMATION);
IntCopyMemory(Irp->AssociatedIrp.SystemBuffer, IntCopyMemory(
system_information, Irp->AssociatedIrp.SystemBuffer,
sizeof(SYSTEM_INFORMATION)); system_information,
sizeof(SYSTEM_INFORMATION));
break; break;
@ -1051,8 +1079,9 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
status = DetectEptHooksInKeyFunctions(); status = DetectEptHooksInKeyFunctions();
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("DetectEpthooksInKeyFunctions failed with status %x", DEBUG_ERROR(
status); "DetectEpthooksInKeyFunctions failed with status %x",
status);
break; break;
@ -1120,8 +1149,9 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
status = SharedMappingInitialise(Irp); status = SharedMappingInitialise(Irp);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("SharedMappingInitialise failed with status %x", DEBUG_ERROR(
status); "SharedMappingInitialise failed with status %x",
status);
break; break;
@ -1129,13 +1159,14 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
DEBUG_INFO("IOCTL_VALIDATE_PCI_DEVICES Received"); DEBUG_INFO("IOCTL_VALIDATE_PCI_DEVICES Received");
status = ImpPsCreateSystemThread(&handle, status = ImpPsCreateSystemThread(
PROCESS_ALL_ACCESS, &handle,
NULL, PROCESS_ALL_ACCESS,
NULL, NULL,
NULL, NULL,
ValidatePciDevices, NULL,
NULL); ValidatePciDevices,
NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status); DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
@ -1152,14 +1183,16 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
status = ValidateWin32kDispatchTables(); status = ValidateWin32kDispatchTables();
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
DEBUG_ERROR("ValidateWin32kDispatchTables failed with status %x", DEBUG_ERROR(
status); "ValidateWin32kDispatchTables failed with status %x",
status);
break; break;
default: default:
DEBUG_WARNING("Invalid IOCTL passed to driver: %lx", DEBUG_WARNING(
stack_location->Parameters.DeviceIoControl.IoControlCode); "Invalid IOCTL passed to driver: %lx",
stack_location->Parameters.DeviceIoControl.IoControlCode);
status = STATUS_INVALID_PARAMETER; status = STATUS_INVALID_PARAMETER;
break; break;

View file

@ -4,7 +4,7 @@ VOID
IntCopyMemory(_In_ PVOID Destination, _In_ PVOID Source, _In_ SIZE_T Length) IntCopyMemory(_In_ PVOID Destination, _In_ PVOID Source, _In_ SIZE_T Length)
{ {
PUCHAR dest = (PUCHAR)Destination; PUCHAR dest = (PUCHAR)Destination;
PUCHAR src = (PUCHAR)Source; PUCHAR src = (PUCHAR)Source;
for (SIZE_T index = 0; index < Length; index++) for (SIZE_T index = 0; index < Length; index++)
dest[index] = src[index]; dest[index] = src[index];

File diff suppressed because it is too large Load diff

View file

@ -55,19 +55,21 @@ PeGetExportDataDirectorySafe(_In_ PVOID Image)
} }
PIMAGE_EXPORT_DIRECTORY PIMAGE_EXPORT_DIRECTORY
PeGetExportDirectory(_In_ PVOID Image, PeGetExportDirectory(
_In_ PIMAGE_DATA_DIRECTORY ExportDataDirectory) _In_ PVOID Image, _In_ PIMAGE_DATA_DIRECTORY ExportDataDirectory)
{ {
if (!ExportDataDirectory->VirtualAddress || !ExportDataDirectory->Size) if (!ExportDataDirectory->VirtualAddress || !ExportDataDirectory->Size)
return NULL; return NULL;
return RVA( return RVA(
PIMAGE_EXPORT_DIRECTORY, Image, ExportDataDirectory->VirtualAddress); PIMAGE_EXPORT_DIRECTORY,
Image,
ExportDataDirectory->VirtualAddress);
} }
PIMAGE_EXPORT_DIRECTORY PIMAGE_EXPORT_DIRECTORY
PeGetExportDirectorySafe(_In_ PVOID Image, PeGetExportDirectorySafe(
_In_ PIMAGE_DATA_DIRECTORY ExportDataDirectory) _In_ PVOID Image, _In_ PIMAGE_DATA_DIRECTORY ExportDataDirectory)
{ {
if (!MmIsAddressValid(Image)) if (!MmIsAddressValid(Image))
return NULL; return NULL;
@ -76,7 +78,9 @@ PeGetExportDirectorySafe(_In_ PVOID Image,
return NULL; return NULL;
return RVA( return RVA(
PIMAGE_EXPORT_DIRECTORY, Image, ExportDataDirectory->VirtualAddress); PIMAGE_EXPORT_DIRECTORY,
Image,
ExportDataDirectory->VirtualAddress);
} }
UINT32 UINT32
@ -97,9 +101,9 @@ GetSectionCountSafe(_In_ PNT_HEADER_64 Header)
PVOID PVOID
PeFindExportByName(_In_ PVOID Image, _In_ PCHAR Name) PeFindExportByName(_In_ PVOID Image, _In_ PCHAR Name)
{ {
ANSI_STRING target = {0}; ANSI_STRING target = {0};
PNT_HEADER_64 nt = NULL; PNT_HEADER_64 nt = NULL;
PIMAGE_DATA_DIRECTORY data = NULL; PIMAGE_DATA_DIRECTORY data = NULL;
PIMAGE_EXPORT_DIRECTORY export = NULL; PIMAGE_EXPORT_DIRECTORY export = NULL;
RtlInitAnsiString(&target, Name); RtlInitAnsiString(&target, Name);
@ -119,18 +123,14 @@ PeFindExportByName(_In_ PVOID Image, _In_ PCHAR Name)
if (!export) if (!export)
return NULL; return NULL;
PUINT32 functions = PUINT32 functions = RVA(PUINT32, Image, export->AddressOfFunctions);
RVA(PUINT32, Image, export->AddressOfFunctions); PUINT32 names = RVA(PUINT32, Image, export->AddressOfNames);
PUINT32 names = PUINT16 ordinals = RVA(PUINT16, Image, export->AddressOfNameOrdinals);
RVA(PUINT32, Image, export->AddressOfNames);
PUINT16 ordinals =
RVA(PUINT16, Image, export->AddressOfNameOrdinals);
for (UINT32 index = 0; index < export->NumberOfNames; index++) { for (UINT32 index = 0; index < export->NumberOfNames; index++) {
PCHAR export = RVA(PCHAR, Image, names[index]); PCHAR export = RVA(PCHAR, Image, names[index]);
if (!IntCompareString(Name, export)) if (!IntCompareString(Name, export))
return RVA( return RVA(PVOID, Image, functions[ordinals[index]]);
PVOID, Image, functions[ordinals[index]]);
} }
return NULL; return NULL;

View file

@ -4,9 +4,9 @@
#include "callbacks.h" #include "callbacks.h"
#include "crypt.h"
#include "ia32.h" #include "ia32.h"
#include "imports.h" #include "imports.h"
#include "crypt.h"
#include "lib/stdlib.h" #include "lib/stdlib.h"
@ -56,28 +56,30 @@ typedef struct _PROCESS_SCAN_CONTEXT {
STATIC STATIC
BOOLEAN BOOLEAN
ValidateIfAddressIsProcessStructure(_In_ PVOID Address, ValidateIfAddressIsProcessStructure(
_In_ PPOOL_HEADER PoolHeader); _In_ PVOID Address, _In_ PPOOL_HEADER PoolHeader);
STATIC STATIC
VOID VOID
ScanPageForKernelObjectAllocation(_In_ UINT64 PageBase, ScanPageForKernelObjectAllocation(
_In_ ULONG PageSize, _In_ UINT64 PageBase,
_In_ ULONG ObjectIndex, _In_ ULONG PageSize,
_Inout_ PPROCESS_SCAN_CONTEXT Context); _In_ ULONG ObjectIndex,
_Inout_ PPROCESS_SCAN_CONTEXT Context);
STATIC STATIC
BOOLEAN BOOLEAN
IsPhysicalAddressInPhysicalMemoryRange(_In_ UINT64 PhysicalAddress, IsPhysicalAddressInPhysicalMemoryRange(
_In_ PPHYSICAL_MEMORY_RANGE _In_ UINT64 PhysicalAddress,
PhysicalMemoryRanges); _In_ PPHYSICAL_MEMORY_RANGE PhysicalMemoryRanges);
STATIC STATIC
VOID VOID
EnumerateKernelLargePages(_In_ UINT64 PageBase, EnumerateKernelLargePages(
_In_ ULONG PageSize, _In_ UINT64 PageBase,
_In_ PPROCESS_SCAN_CONTEXT Context, _In_ ULONG PageSize,
_In_ ULONG ObjectIndex); _In_ PPROCESS_SCAN_CONTEXT Context,
_In_ ULONG ObjectIndex);
STATIC STATIC
VOID VOID
@ -89,8 +91,8 @@ IncrementProcessCounter(_In_ PPROCESS_LIST_ENTRY Node, _In_opt_ PVOID Context);
STATIC STATIC
VOID VOID
CheckIfProcessAllocationIsInProcessList(_In_ PPROCESS_LIST_ENTRY Node, CheckIfProcessAllocationIsInProcessList(
_In_opt_ PVOID Context); _In_ PPROCESS_LIST_ENTRY Node, _In_opt_ PVOID Context);
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
# pragma alloc_text(PAGE, GetGlobalDebuggerData) # pragma alloc_text(PAGE, GetGlobalDebuggerData)
@ -105,9 +107,9 @@ GetGlobalDebuggerData()
{ {
PAGED_CODE(); PAGED_CODE();
CONTEXT context = {0}; CONTEXT context = {0};
PDUMP_HEADER dump_header = {0}; PDUMP_HEADER dump_header = {0};
UINT64 thread_state = 0; UINT64 thread_state = 0;
PKDDEBUGGER_DATA64 debugger_data = NULL; PKDDEBUGGER_DATA64 debugger_data = NULL;
context.ContextFlags = CONTEXT_FULL; context.ContextFlags = CONTEXT_FULL;
@ -115,23 +117,35 @@ GetGlobalDebuggerData()
RtlCaptureContext(&context); RtlCaptureContext(&context);
dump_header = ImpExAllocatePool2( dump_header = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, DUMP_BLOCK_SIZE, POOL_DUMP_BLOCK_TAG); POOL_FLAG_NON_PAGED,
DUMP_BLOCK_SIZE,
POOL_DUMP_BLOCK_TAG);
if (!dump_header) if (!dump_header)
goto end; goto end;
KeCapturePersistentThreadState( KeCapturePersistentThreadState(
&context, NULL, NULL, NULL, NULL, NULL, NULL, dump_header); &context,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
dump_header);
debugger_data = (PKDDEBUGGER_DATA64)ExAllocatePool2( debugger_data = (PKDDEBUGGER_DATA64)ExAllocatePool2(
POOL_FLAG_NON_PAGED, sizeof(KDDEBUGGER_DATA64), POOL_DEBUGGER_DATA_TAG); POOL_FLAG_NON_PAGED,
sizeof(KDDEBUGGER_DATA64),
POOL_DEBUGGER_DATA_TAG);
if (!debugger_data) if (!debugger_data)
goto end; goto end;
IntCopyMemory(debugger_data, IntCopyMemory(
dump_header->KdDebuggerDataBlock, debugger_data,
sizeof(KDDEBUGGER_DATA64)); dump_header->KdDebuggerDataBlock,
sizeof(KDDEBUGGER_DATA64));
end: end:
@ -200,25 +214,25 @@ GetPsActiveProcessHead(_Out_ PUINT64 Address)
*/ */
STATIC STATIC
BOOLEAN BOOLEAN
ValidateIfAddressIsProcessStructure(_In_ PVOID Address, ValidateIfAddressIsProcessStructure(
_In_ PPOOL_HEADER PoolHeader) _In_ PVOID Address, _In_ PPOOL_HEADER PoolHeader)
{ {
UINT64 peak_virtual_size = 0; UINT64 peak_virtual_size = 0;
UINT64 dir_table_base = 0; UINT64 dir_table_base = 0;
UINT64 allocation_size = 0; UINT64 allocation_size = 0;
UINT64 peb = 0; UINT64 peb = 0;
UINT64 object_table = 0; UINT64 object_table = 0;
BOOLEAN peb_test = FALSE; BOOLEAN peb_test = FALSE;
BOOLEAN object_table_test = FALSE; BOOLEAN object_table_test = FALSE;
UINT64 allocation_size_test = 0; UINT64 allocation_size_test = 0;
if (ImpMmIsAddressValid((UINT64)Address + if (ImpMmIsAddressValid(
KPROCESS_DIRECTORY_TABLE_BASE_OFFSET)) (UINT64)Address + KPROCESS_DIRECTORY_TABLE_BASE_OFFSET))
dir_table_base = dir_table_base =
*(UINT64*)((UINT64)Address + KPROCESS_DIRECTORY_TABLE_BASE_OFFSET); *(UINT64*)((UINT64)Address + KPROCESS_DIRECTORY_TABLE_BASE_OFFSET);
if (ImpMmIsAddressValid((UINT64)Address + if (ImpMmIsAddressValid(
EPROCESS_PEAK_VIRTUAL_SIZE_OFFSET)) (UINT64)Address + EPROCESS_PEAK_VIRTUAL_SIZE_OFFSET))
peak_virtual_size = peak_virtual_size =
*(UINT64*)((UINT64)Address + EPROCESS_PEAK_VIRTUAL_SIZE_OFFSET); *(UINT64*)((UINT64)Address + EPROCESS_PEAK_VIRTUAL_SIZE_OFFSET);
@ -278,23 +292,24 @@ ValidateIfAddressIsProcessStructure(_In_ PVOID Address,
*/ */
STATIC STATIC
VOID VOID
ScanPageForKernelObjectAllocation(_In_ UINT64 PageBase, ScanPageForKernelObjectAllocation(
_In_ ULONG PageSize, _In_ UINT64 PageBase,
_In_ ULONG ObjectIndex, _In_ ULONG PageSize,
_Inout_ PPROCESS_SCAN_CONTEXT Context) _In_ ULONG ObjectIndex,
_Inout_ PPROCESS_SCAN_CONTEXT Context)
{ {
INT length = 0; INT length = 0;
CHAR current_char = 0; CHAR current_char = 0;
CHAR current_sig_byte = 0; CHAR current_sig_byte = 0;
PPOOL_HEADER pool_header = NULL; PPOOL_HEADER pool_header = NULL;
PEPROCESS process = NULL; PEPROCESS process = NULL;
PEPROCESS process_size_one = NULL; PEPROCESS process_size_one = NULL;
PEPROCESS process_size_two = NULL; PEPROCESS process_size_two = NULL;
PEPROCESS test_process = NULL; PEPROCESS test_process = NULL;
LPCSTR process_name = NULL; LPCSTR process_name = NULL;
PUINT64 address_list = NULL; PUINT64 address_list = NULL;
ULONG allocation_size = 0; ULONG allocation_size = 0;
ULONG minimum_process_allocation_size = ULONG minimum_process_allocation_size =
EPROCESS_SIZE - sizeof(POOL_HEADER) - OBJECT_HEADER_SIZE; EPROCESS_SIZE - sizeof(POOL_HEADER) - OBJECT_HEADER_SIZE;
if (!PageBase || !PageSize) if (!PageBase || !PageSize)
@ -335,8 +350,9 @@ ScanPageForKernelObjectAllocation(_In_ UINT64 PageBase,
(PEPROCESS)((UINT64)pool_header + sizeof(POOL_HEADER) + (PEPROCESS)((UINT64)pool_header + sizeof(POOL_HEADER) +
header_size); header_size);
if (ValidateIfAddressIsProcessStructure(test_process, if (ValidateIfAddressIsProcessStructure(
pool_header)) { test_process,
pool_header)) {
process = test_process; process = test_process;
break; break;
} }
@ -345,8 +361,9 @@ ScanPageForKernelObjectAllocation(_In_ UINT64 PageBase,
if (!process) if (!process)
break; break;
DEBUG_VERBOSE("Found process via pt walk: %llx", DEBUG_VERBOSE(
(UINT64)process); "Found process via pt walk: %llx",
(UINT64)process);
address_list = (PUINT64)Context->process_buffer; address_list = (PUINT64)Context->process_buffer;
@ -374,17 +391,17 @@ ScanPageForKernelObjectAllocation(_In_ UINT64 PageBase,
*/ */
STATIC STATIC
BOOLEAN BOOLEAN
IsPhysicalAddressInPhysicalMemoryRange(_In_ UINT64 PhysicalAddress, IsPhysicalAddressInPhysicalMemoryRange(
_In_ PPHYSICAL_MEMORY_RANGE _In_ UINT64 PhysicalAddress,
PhysicalMemoryRanges) _In_ PPHYSICAL_MEMORY_RANGE PhysicalMemoryRanges)
{ {
ULONG page_index = 0; ULONG page_index = 0;
UINT64 start_address = 0; UINT64 start_address = 0;
UINT64 end_address = 0; UINT64 end_address = 0;
while (PhysicalMemoryRanges[page_index].NumberOfBytes.QuadPart != NULL) { while (PhysicalMemoryRanges[page_index].NumberOfBytes.QuadPart != NULL) {
start_address = PhysicalMemoryRanges[page_index].BaseAddress.QuadPart; start_address = PhysicalMemoryRanges[page_index].BaseAddress.QuadPart;
end_address = start_address + end_address = start_address +
PhysicalMemoryRanges[page_index].NumberOfBytes.QuadPart; PhysicalMemoryRanges[page_index].NumberOfBytes.QuadPart;
if (PhysicalAddress >= start_address && PhysicalAddress <= end_address) if (PhysicalAddress >= start_address && PhysicalAddress <= end_address)
@ -398,10 +415,11 @@ IsPhysicalAddressInPhysicalMemoryRange(_In_ UINT64 PhysicalAddress,
STATIC STATIC
VOID VOID
EnumerateKernelLargePages(_In_ UINT64 PageBase, EnumerateKernelLargePages(
_In_ ULONG PageSize, _In_ UINT64 PageBase,
_In_ PPROCESS_SCAN_CONTEXT Context, _In_ ULONG PageSize,
_In_ ULONG ObjectIndex) _In_ PPROCESS_SCAN_CONTEXT Context,
_In_ ULONG ObjectIndex)
{ {
/* /*
* Split the large pages up into blocks of 0x1000 and scan each block * Split the large pages up into blocks of 0x1000 and scan each block
@ -409,7 +427,10 @@ EnumerateKernelLargePages(_In_ UINT64 PageBase,
for (UINT64 page_index = 0; page_index < PageSize; page_index++) { for (UINT64 page_index = 0; page_index < PageSize; page_index++) {
UINT64 page_base = PageBase + (page_index * PAGE_SIZE); UINT64 page_base = PageBase + (page_index * PAGE_SIZE);
ScanPageForKernelObjectAllocation( ScanPageForKernelObjectAllocation(
page_base, PAGE_SIZE, ObjectIndex, Context); page_base,
PAGE_SIZE,
ObjectIndex,
Context);
} }
} }
@ -445,24 +466,24 @@ STATIC
VOID VOID
WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context) WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
{ {
CR3 cr3 = {0}; CR3 cr3 = {0};
PML4E pml4_base = {0}; PML4E pml4_base = {0};
PML4E pml4_entry = {0}; PML4E pml4_entry = {0};
UINT64 pdpt_base = 0; UINT64 pdpt_base = 0;
UINT64 pd_base = 0; UINT64 pd_base = 0;
UINT64 pt_base = 0; UINT64 pt_base = 0;
PDPTE pdpt_entry = {0}; PDPTE pdpt_entry = {0};
PDPTE_LARGE pdpt_large_entry = {0}; PDPTE_LARGE pdpt_large_entry = {0};
PDE pd_entry = {0}; PDE pd_entry = {0};
PDE_LARGE pd_large_entry = {0}; PDE_LARGE pd_large_entry = {0};
PTE pt_entry = {0}; PTE pt_entry = {0};
UINT64 base_physical_page = 0; UINT64 base_physical_page = 0;
UINT64 base_virtual_page = 0; UINT64 base_virtual_page = 0;
UINT64 base_2mb_virtual_page = 0; UINT64 base_2mb_virtual_page = 0;
UINT64 base_1gb_virtual_page = 0; UINT64 base_1gb_virtual_page = 0;
PHYSICAL_ADDRESS physical = {0}; PHYSICAL_ADDRESS physical = {0};
PPHYSICAL_MEMORY_RANGE physical_memory_ranges = NULL; PPHYSICAL_MEMORY_RANGE physical_memory_ranges = NULL;
KIRQL irql = {0}; KIRQL irql = {0};
physical_memory_ranges = ImpMmGetPhysicalMemoryRangesEx2(NULL, NULL); physical_memory_ranges = ImpMmGetPhysicalMemoryRangesEx2(NULL, NULL);
@ -481,8 +502,8 @@ WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
return; return;
for (INT pml4_index = 0; pml4_index < PML4_ENTRY_COUNT; pml4_index++) { for (INT pml4_index = 0; pml4_index < PML4_ENTRY_COUNT; pml4_index++) {
if (!ImpMmIsAddressValid(pml4_base.BitAddress + if (!ImpMmIsAddressValid(
pml4_index * sizeof(UINT64))) pml4_base.BitAddress + pml4_index * sizeof(UINT64)))
continue; continue;
pml4_entry.BitAddress = pml4_entry.BitAddress =
@ -516,7 +537,8 @@ WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
<< PAGE_1GB_SHIFT; << PAGE_1GB_SHIFT;
if (IsPhysicalAddressInPhysicalMemoryRange( if (IsPhysicalAddressInPhysicalMemoryRange(
physical.QuadPart, physical_memory_ranges) == FALSE) physical.QuadPart,
physical_memory_ranges) == FALSE)
continue; continue;
base_1gb_virtual_page = ImpMmGetVirtualForPhysical(physical); base_1gb_virtual_page = ImpMmGetVirtualForPhysical(physical);
@ -525,10 +547,11 @@ WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
!ImpMmIsAddressValid(base_1gb_virtual_page)) !ImpMmIsAddressValid(base_1gb_virtual_page))
continue; continue;
EnumerateKernelLargePages(base_1gb_virtual_page, EnumerateKernelLargePages(
LARGE_PAGE_1GB_ENTRIES, base_1gb_virtual_page,
Context, LARGE_PAGE_1GB_ENTRIES,
INDEX_PROCESS_POOL_TAG); Context,
INDEX_PROCESS_POOL_TAG);
continue; continue;
} }
@ -559,7 +582,8 @@ WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
<< PAGE_2MB_SHIFT; << PAGE_2MB_SHIFT;
if (IsPhysicalAddressInPhysicalMemoryRange( if (IsPhysicalAddressInPhysicalMemoryRange(
physical.QuadPart, physical_memory_ranges) == FALSE) physical.QuadPart,
physical_memory_ranges) == FALSE)
continue; continue;
base_2mb_virtual_page = base_2mb_virtual_page =
@ -569,10 +593,11 @@ WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
!ImpMmIsAddressValid(base_2mb_virtual_page)) !ImpMmIsAddressValid(base_2mb_virtual_page))
continue; continue;
EnumerateKernelLargePages(base_2mb_virtual_page, EnumerateKernelLargePages(
LARGE_PAGE_2MB_ENTRIES, base_2mb_virtual_page,
Context, LARGE_PAGE_2MB_ENTRIES,
INDEX_PROCESS_POOL_TAG); Context,
INDEX_PROCESS_POOL_TAG);
continue; continue;
} }
@ -589,8 +614,8 @@ WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
continue; continue;
for (INT pt_index = 0; pt_index < PT_ENTRY_COUNT; pt_index++) { for (INT pt_index = 0; pt_index < PT_ENTRY_COUNT; pt_index++) {
if (!ImpMmIsAddressValid(pt_base + if (!ImpMmIsAddressValid(
pt_index * sizeof(UINT64))) pt_base + pt_index * sizeof(UINT64)))
continue; continue;
pt_entry.BitAddress = pt_entry.BitAddress =
@ -605,7 +630,8 @@ WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
/* if the page base isnt in a legit /* if the page base isnt in a legit
* region, go next */ * region, go next */
if (IsPhysicalAddressInPhysicalMemoryRange( if (IsPhysicalAddressInPhysicalMemoryRange(
physical.QuadPart, physical_memory_ranges) == FALSE) physical.QuadPart,
physical_memory_ranges) == FALSE)
continue; continue;
base_virtual_page = ImpMmGetVirtualForPhysical(physical); base_virtual_page = ImpMmGetVirtualForPhysical(physical);
@ -616,10 +642,11 @@ WalkKernelPageTables(_In_ PPROCESS_SCAN_CONTEXT Context)
!ImpMmIsAddressValid(base_virtual_page)) !ImpMmIsAddressValid(base_virtual_page))
continue; continue;
ScanPageForKernelObjectAllocation(base_virtual_page, ScanPageForKernelObjectAllocation(
PAGE_BASE_SIZE, base_virtual_page,
INDEX_PROCESS_POOL_TAG, PAGE_BASE_SIZE,
Context); INDEX_PROCESS_POOL_TAG,
Context);
} }
} }
} }
@ -646,13 +673,13 @@ IncrementProcessCounter(_In_ PPROCESS_LIST_ENTRY Node, _In_opt_ PVOID Context)
STATIC STATIC
VOID VOID
CheckIfProcessAllocationIsInProcessList(_In_ PPROCESS_LIST_ENTRY Node, CheckIfProcessAllocationIsInProcessList(
_In_opt_ PVOID Context) _In_ PPROCESS_LIST_ENTRY Node, _In_opt_ PVOID Context)
{ {
PAGED_CODE(); PAGED_CODE();
PUINT64 allocation_address = NULL; PUINT64 allocation_address = NULL;
PPROCESS_SCAN_CONTEXT context = (PPROCESS_SCAN_CONTEXT)Context; PPROCESS_SCAN_CONTEXT context = (PPROCESS_SCAN_CONTEXT)Context;
if (!context) if (!context)
return; return;
@ -664,8 +691,9 @@ CheckIfProcessAllocationIsInProcessList(_In_ PPROCESS_LIST_ENTRY Node,
allocation_address[i] - PROCESS_OBJECT_ALLOCATION_MARGIN && allocation_address[i] - PROCESS_OBJECT_ALLOCATION_MARGIN &&
(UINT64)Node->process <= (UINT64)Node->process <=
allocation_address[i] + PROCESS_OBJECT_ALLOCATION_MARGIN) { allocation_address[i] + PROCESS_OBJECT_ALLOCATION_MARGIN) {
RtlZeroMemory((UINT64)context->process_buffer + i * sizeof(UINT64), RtlZeroMemory(
sizeof(UINT64)); (UINT64)context->process_buffer + i * sizeof(UINT64),
sizeof(UINT64));
} }
} }
} }
@ -679,10 +707,10 @@ FindUnlinkedProcesses()
{ {
PAGED_CODE(); PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PUINT64 allocation_address = NULL; PUINT64 allocation_address = NULL;
PROCESS_SCAN_CONTEXT context = {0}; PROCESS_SCAN_CONTEXT context = {0};
PINVALID_PROCESS_ALLOCATION_REPORT report = NULL; PINVALID_PROCESS_ALLOCATION_REPORT report = NULL;
UINT32 packet_size = CryptRequestRequiredBufferLength( UINT32 packet_size = CryptRequestRequiredBufferLength(
sizeof(INVALID_PROCESS_ALLOCATION_REPORT)); sizeof(INVALID_PROCESS_ALLOCATION_REPORT));
@ -693,10 +721,10 @@ FindUnlinkedProcesses()
return STATUS_ABANDONED; return STATUS_ABANDONED;
} }
context.process_buffer = context.process_buffer = ExAllocatePool2(
ExAllocatePool2(POOL_FLAG_NON_PAGED, POOL_FLAG_NON_PAGED,
context.process_count * 2 * sizeof(UINT64), context.process_count * 2 * sizeof(UINT64),
PROCESS_ADDRESS_LIST_TAG); PROCESS_ADDRESS_LIST_TAG);
if (!context.process_buffer) if (!context.process_buffer)
return STATUS_MEMORY_NOT_ALLOCATED; return STATUS_MEMORY_NOT_ALLOCATED;
@ -704,7 +732,9 @@ FindUnlinkedProcesses()
WalkKernelPageTables(&context); WalkKernelPageTables(&context);
RtlHashmapEnumerate( RtlHashmapEnumerate(
GetProcessHashmap(), CheckIfProcessAllocationIsInProcessList, &context); GetProcessHashmap(),
CheckIfProcessAllocationIsInProcessList,
&context);
allocation_address = (PUINT64)context.process_buffer; allocation_address = (PUINT64)context.process_buffer;
@ -727,7 +757,9 @@ FindUnlinkedProcesses()
allocation); allocation);
report = ImpExAllocatePool2( report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG); POOL_FLAG_NON_PAGED,
packet_size,
REPORT_POOL_TAG);
if (!report) if (!report)
continue; continue;
@ -735,7 +767,9 @@ FindUnlinkedProcesses()
INIT_REPORT_PACKET(report, REPORT_INVALID_PROCESS_ALLOCATION, 0); INIT_REPORT_PACKET(report, REPORT_INVALID_PROCESS_ALLOCATION, 0);
IntCopyMemory( IntCopyMemory(
report->process, allocation, REPORT_INVALID_PROCESS_BUFFER_SIZE); report->process,
allocation,
REPORT_INVALID_PROCESS_BUFFER_SIZE);
status = CryptEncryptBuffer(report, packet_size); status = CryptEncryptBuffer(report, packet_size);
@ -764,11 +798,11 @@ end:
NTSTATUS NTSTATUS
EnumerateBigPoolAllocations() EnumerateBigPoolAllocations()
{ {
ULONG return_length = 0; ULONG return_length = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PSYSTEM_BIGPOOL_ENTRY entry = NULL; PSYSTEM_BIGPOOL_ENTRY entry = NULL;
SYSTEM_BIGPOOL_INFORMATION pool_information = {0}; SYSTEM_BIGPOOL_INFORMATION pool_information = {0};
PSYSTEM_BIGPOOL_INFORMATION pool_entries = NULL; PSYSTEM_BIGPOOL_INFORMATION pool_entries = NULL;
UNICODE_STRING routine = RTL_CONSTANT_STRING(L"ZwQuerySystemInformation"); UNICODE_STRING routine = RTL_CONSTANT_STRING(L"ZwQuerySystemInformation");
ZwQuerySystemInformation pZwQuerySystemInformation = ZwQuerySystemInformation pZwQuerySystemInformation =
ImpMmGetSystemRoutineAddress(&routine); ImpMmGetSystemRoutineAddress(&routine);
@ -778,10 +812,11 @@ EnumerateBigPoolAllocations()
return status; return status;
} }
status = pZwQuerySystemInformation(SYSTEM_BIGPOOL_INFORMATION_ID, status = pZwQuerySystemInformation(
&pool_information, SYSTEM_BIGPOOL_INFORMATION_ID,
sizeof(pool_information), &pool_information,
&return_length); sizeof(pool_information),
&return_length);
if (status != STATUS_INFO_LENGTH_MISMATCH) { if (status != STATUS_INFO_LENGTH_MISMATCH) {
DEBUG_ERROR("ZwQuerySystemInformation failed with status %x", status); DEBUG_ERROR("ZwQuerySystemInformation failed with status %x", status);
@ -791,15 +826,18 @@ EnumerateBigPoolAllocations()
return_length += sizeof(SYSTEM_BIGPOOL_INFORMATION); return_length += sizeof(SYSTEM_BIGPOOL_INFORMATION);
pool_entries = ImpExAllocatePool2( pool_entries = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, return_length, POOL_TAG_INTEGRITY); POOL_FLAG_NON_PAGED,
return_length,
POOL_TAG_INTEGRITY);
if (!pool_entries) if (!pool_entries)
return STATUS_MEMORY_NOT_ALLOCATED; return STATUS_MEMORY_NOT_ALLOCATED;
status = pZwQuerySystemInformation(SYSTEM_BIGPOOL_INFORMATION_ID, status = pZwQuerySystemInformation(
pool_entries, SYSTEM_BIGPOOL_INFORMATION_ID,
return_length, pool_entries,
&return_length); return_length,
&return_length);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ZwQuerySystemInformation 2 failed with status %x", status); DEBUG_ERROR("ZwQuerySystemInformation 2 failed with status %x", status);

View file

@ -1,7 +1,7 @@
#include "session.h" #include "session.h"
#include "imports.h"
#include "crypt.h" #include "crypt.h"
#include "imports.h"
#include "util.h" #include "util.h"
#include "lib/stdlib.h" #include "lib/stdlib.h"
@ -9,7 +9,7 @@
NTSTATUS NTSTATUS
SessionInitialiseStructure() SessionInitialiseStructure()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION session = GetActiveSession(); PACTIVE_SESSION session = GetActiveSession();
KeInitializeGuardedMutex(&session->lock); KeInitializeGuardedMutex(&session->lock);
@ -74,12 +74,12 @@ SessionTerminate()
DEBUG_INFO("Termination active session."); DEBUG_INFO("Termination active session.");
PACTIVE_SESSION session = GetActiveSession(); PACTIVE_SESSION session = GetActiveSession();
KIRQL irql = {0}; KIRQL irql = {0};
KeAcquireGuardedMutex(&session->lock); KeAcquireGuardedMutex(&session->lock);
session->km_handle = NULL; session->km_handle = NULL;
session->um_handle = NULL; session->um_handle = NULL;
session->process = NULL; session->process = NULL;
session->is_session_active = FALSE; session->is_session_active = FALSE;
RtlZeroMemory(&session->module, sizeof(MODULE_INFORMATION)); RtlZeroMemory(&session->module, sizeof(MODULE_INFORMATION));
@ -92,18 +92,19 @@ SessionTerminate()
/* Return type for this doesnt matter */ /* Return type for this doesnt matter */
STATIC STATIC
BOOLEAN BOOLEAN
HashOurUserModuleOnEntryCallback(_In_ PPROCESS_MAP_MODULE_ENTRY Entry, HashOurUserModuleOnEntryCallback(
_In_opt_ PVOID Context) _In_ PPROCESS_MAP_MODULE_ENTRY Entry, _In_opt_ PVOID Context)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION session = (PACTIVE_SESSION)Context; PACTIVE_SESSION session = (PACTIVE_SESSION)Context;
if (!ARGUMENT_PRESENT(Context)) if (!ARGUMENT_PRESENT(Context))
return FALSE; return FALSE;
status = HashUserModule(Entry, status = HashUserModule(
session->module.module_hash, Entry,
sizeof(session->module.module_hash)); session->module.module_hash,
sizeof(session->module.module_hash));
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("HashUserModule: %lx", status); DEBUG_ERROR("HashUserModule: %lx", status);
@ -111,8 +112,9 @@ HashOurUserModuleOnEntryCallback(_In_ PPROCESS_MAP_MODULE_ENTRY Entry,
} }
DEBUG_VERBOSE("User module hashed!"); DEBUG_VERBOSE("User module hashed!");
DumpBufferToKernelDebugger(session->module.module_hash, DumpBufferToKernelDebugger(
sizeof(session->module.module_hash)); session->module.module_hash,
sizeof(session->module.module_hash));
return TRUE; return TRUE;
} }
@ -120,16 +122,17 @@ HashOurUserModuleOnEntryCallback(_In_ PPROCESS_MAP_MODULE_ENTRY Entry,
NTSTATUS NTSTATUS
SessionInitialise(_In_ PIRP Irp) SessionInitialise(_In_ PIRP Irp)
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS process = NULL; PEPROCESS process = NULL;
PSESSION_INITIATION_PACKET initiation = NULL; PSESSION_INITIATION_PACKET initiation = NULL;
PACTIVE_SESSION session = GetActiveSession(); PACTIVE_SESSION session = GetActiveSession();
KIRQL irql = {0}; KIRQL irql = {0};
DEBUG_VERBOSE("Initialising new session."); DEBUG_VERBOSE("Initialising new session.");
status = ValidateIrpInputBuffer( status = ValidateIrpInputBuffer(
Irp, sizeof(SESSION_INITIATION_PACKET) - SHA_256_HASH_LENGTH); Irp,
sizeof(SESSION_INITIATION_PACKET) - SHA_256_HASH_LENGTH);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ValidateIrpInputBuffer failed with status %x", status); DEBUG_ERROR("ValidateIrpInputBuffer failed with status %x", status);
@ -151,17 +154,19 @@ SessionInitialise(_In_ PIRP Irp)
} }
session->km_handle = ImpPsGetProcessId(process); session->km_handle = ImpPsGetProcessId(process);
session->process = process; session->process = process;
session->cookie = initiation->cookie; session->cookie = initiation->cookie;
IntCopyMemory(session->aes_key, initiation->aes_key, AES_256_KEY_SIZE); IntCopyMemory(session->aes_key, initiation->aes_key, AES_256_KEY_SIZE);
IntCopyMemory(session->iv, initiation->aes_iv, AES_256_IV_SIZE); IntCopyMemory(session->iv, initiation->aes_iv, AES_256_IV_SIZE);
session->module.base_address = initiation->module_info.base_address; session->module.base_address = initiation->module_info.base_address;
session->module.size = initiation->module_info.size; session->module.size = initiation->module_info.size;
IntCopyMemory( IntCopyMemory(
session->module.path, initiation->module_info.path, MAX_MODULE_PATH); session->module.path,
initiation->module_info.path,
MAX_MODULE_PATH);
DEBUG_VERBOSE("Module base: %llx", session->module.base_address); DEBUG_VERBOSE("Module base: %llx", session->module.base_address);
DEBUG_VERBOSE("Module size: %lx ", session->module.size); DEBUG_VERBOSE("Module size: %lx ", session->module.size);
@ -193,8 +198,8 @@ end:
VOID VOID
SessionTerminateProcess() SessionTerminateProcess()
{ {
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG process_id = 0; ULONG process_id = 0;
SessionGetProcessId(&process_id); SessionGetProcessId(&process_id);
@ -205,8 +210,9 @@ SessionTerminateProcess()
/* Make sure we pass a km handle to ZwTerminateProcess and NOT a /* Make sure we pass a km handle to ZwTerminateProcess and NOT a
* usermode handle. */ * usermode handle. */
status = ZwTerminateProcess(process_id, status = ZwTerminateProcess(
STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION); process_id,
STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
/* /*

View file

@ -2,14 +2,14 @@
#include <intrin.h> #include <intrin.h>
#include "pool.h"
#include "callbacks.h" #include "callbacks.h"
#include "driver.h" #include "driver.h"
#include "pool.h"
#include "session.h"
#include "imports.h"
#include "containers/tree.h" #include "containers/tree.h"
#include "crypt.h" #include "crypt.h"
#include "imports.h"
#include "session.h"
#include "lib/stdlib.h" #include "lib/stdlib.h"
@ -23,9 +23,9 @@ DoesThreadHaveValidCidEntry(_In_ PETHREAD Thread)
{ {
PAGED_CODE(); PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
HANDLE thread_id = NULL; HANDLE thread_id = NULL;
PETHREAD thread = NULL; PETHREAD thread = NULL;
/* /*
* PsGetThreadId simply returns ETHREAD->Cid.UniqueThread * PsGetThreadId simply returns ETHREAD->Cid.UniqueThread
@ -80,15 +80,15 @@ DoesThreadHaveValidCidEntry(_In_ PETHREAD Thread)
* any APC's queued. * any APC's queued.
*/ */
STATIC VOID STATIC VOID
DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry, DetectAttachedThreadsProcessCallback(
_Inout_opt_ PVOID Context) _In_ PTHREAD_LIST_ENTRY ThreadListEntry, _Inout_opt_ PVOID Context)
{ {
UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(Context);
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
PKAPC_STATE apc_state = NULL; PKAPC_STATE apc_state = NULL;
PEPROCESS protected_process = NULL; PEPROCESS protected_process = NULL;
UINT32 packet_size = UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(ATTACH_PROCESS_REPORT)); CryptRequestRequiredBufferLength(sizeof(ATTACH_PROCESS_REPORT));
SessionGetProcess(&protected_process); SessionGetProcess(&protected_process);
@ -110,8 +110,9 @@ DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
return; return;
} }
DEBUG_WARNING("Thread is attached to our protected process: %llx", DEBUG_WARNING(
(UINT64)ThreadListEntry->thread); "Thread is attached to our protected process: %llx",
(UINT64)ThreadListEntry->thread);
PATTACH_PROCESS_REPORT report = PATTACH_PROCESS_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG); ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
@ -121,7 +122,7 @@ DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
INIT_REPORT_PACKET(report, REPORT_ILLEGAL_ATTACH_PROCESS, 0); INIT_REPORT_PACKET(report, REPORT_ILLEGAL_ATTACH_PROCESS, 0);
report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread); report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread);
report->thread_address = ThreadListEntry->thread; report->thread_address = ThreadListEntry->thread;
status = CryptEncryptBuffer(report, packet_size); status = CryptEncryptBuffer(report, packet_size);
@ -141,5 +142,7 @@ DetectThreadsAttachedToProtectedProcess()
PAGED_CODE(); PAGED_CODE();
DEBUG_VERBOSE("Detecting threads attached to our process..."); DEBUG_VERBOSE("Detecting threads attached to our process...");
RtlRbTreeEnumerate( RtlRbTreeEnumerate(
GetThreadTree(), DetectAttachedThreadsProcessCallback, NULL); GetThreadTree(),
DetectAttachedThreadsProcessCallback,
NULL);
} }

View file

@ -6,8 +6,8 @@ LARGE_INTEGER
GenerateRandSeed() GenerateRandSeed()
{ {
LARGE_INTEGER system_time = {0}; LARGE_INTEGER system_time = {0};
LARGE_INTEGER up_time = {0}; LARGE_INTEGER up_time = {0};
LARGE_INTEGER seed = {0}; LARGE_INTEGER seed = {0};
KeQuerySystemTime(&system_time); KeQuerySystemTime(&system_time);
KeQueryTickCount(&up_time); KeQueryTickCount(&up_time);
@ -17,12 +17,13 @@ GenerateRandSeed()
} }
NTSTATUS NTSTATUS
MapAndReadPhysical(_In_ UINT64 PhysicalAddress, MapAndReadPhysical(
_In_ UINT32 ReadLength, _In_ UINT64 PhysicalAddress,
_Out_ PVOID OutputBuffer, _In_ UINT32 ReadLength,
_In_ UINT32 OutputBufferLength) _Out_ PVOID OutputBuffer,
_In_ UINT32 OutputBufferLength)
{ {
PVOID va = NULL; PVOID va = NULL;
PHYSICAL_ADDRESS pa = {.QuadPart = PhysicalAddress}; PHYSICAL_ADDRESS pa = {.QuadPart = PhysicalAddress};
if (ReadLength > OutputBufferLength) if (ReadLength > OutputBufferLength)
@ -45,12 +46,13 @@ MapAndReadPhysical(_In_ UINT64 PhysicalAddress,
} }
NTSTATUS NTSTATUS
UnicodeToCharBufString(_In_ PUNICODE_STRING UnicodeString, UnicodeToCharBufString(
_Out_ PVOID OutBuffer, _In_ PUNICODE_STRING UnicodeString,
_In_ UINT32 OutBufferSize) _Out_ PVOID OutBuffer,
_In_ UINT32 OutBufferSize)
{ {
ANSI_STRING string = {0}; ANSI_STRING string = {0};
NTSTATUS status = STATUS_UNSUCCESSFUL; NTSTATUS status = STATUS_UNSUCCESSFUL;
status = RtlUnicodeStringToAnsiString(&string, UnicodeString, TRUE); status = RtlUnicodeStringToAnsiString(&string, UnicodeString, TRUE);