mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
format
This commit is contained in:
parent
18109448bc
commit
197796d004
18 changed files with 2130 additions and 1836 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 <><><><><><");
|
||||||
|
|
313
driver/crypt.c
313
driver/crypt.c
|
@ -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(¤t_block,
|
IntCopyMemory(
|
||||||
&Array[block_index * block_size],
|
¤t_block,
|
||||||
sizeof(__m256i));
|
&Array[block_index * block_size],
|
||||||
|
sizeof(__m256i));
|
||||||
|
|
||||||
load_block = _mm256_loadu_si256(¤t_block);
|
load_block = _mm256_loadu_si256(¤t_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:
|
||||||
|
|
344
driver/driver.c
344
driver/driver.c
|
@ -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();
|
||||||
|
|
19
driver/hv.c
19
driver/hv.c
|
@ -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;
|
||||||
}
|
}
|
151
driver/hw.c
151
driver/hw.c
|
@ -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
327
driver/io.c
327
driver/io.c
|
@ -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;
|
||||||
|
|
|
@ -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];
|
||||||
|
|
606
driver/modules.c
606
driver/modules.c
File diff suppressed because it is too large
Load diff
34
driver/pe.c
34
driver/pe.c
|
@ -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;
|
||||||
|
|
312
driver/pool.c
312
driver/pool.c
|
@ -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);
|
||||||
|
|
|
@ -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)) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue