diff --git a/2.x/trunk/KProcessHacker/handle.c b/2.x/trunk/KProcessHacker/handle.c deleted file mode 100644 index 43b94fd9a..000000000 --- a/2.x/trunk/KProcessHacker/handle.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Process Hacker Driver - - * handle table - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#include "include/handle.h" -#include "include/handlep.h" - -NTSTATUS KphpAllocateHandleEntry( - __in PKPH_HANDLE_TABLE HandleTable, - __out PKPH_HANDLE_TABLE_ENTRY *Entry - ); - -NTSTATUS KphpFreeHandleEntry( - __in PKPH_HANDLE_TABLE HandleTable, - __in PKPH_HANDLE_TABLE_ENTRY Entry - ); - -/* KphCreateHandleTable - * - * Creates a handle table. - * - * HandleTable: A variable which receives a pointer to the handle table. - * MaximumHandles: The maximum number of handles that can be created. - * SizeOfEntry: The size of each handle table entry. This value must be - * divisible by 4. - * Tag: The tag to use when allocating handle table resources. - */ -NTSTATUS KphCreateHandleTable( - __out PKPH_HANDLE_TABLE *HandleTable, - __in ULONG MaximumHandles, - __in ULONG SizeOfEntry, - __in ULONG Tag - ) -{ - PKPH_HANDLE_TABLE handleTable; - - /* Each handle entry must be at least the size of our - * handle table entry definition. - */ - if (SizeOfEntry < sizeof(KPH_HANDLE_TABLE_ENTRY)) - return STATUS_INVALID_PARAMETER_3; - /* Handle entries must be 4-byte aligned. */ - if (SizeOfEntry % 4 != 0) - return STATUS_INVALID_PARAMETER_3; - - /* Allocate storage for the handle table structure. */ - handleTable = ExAllocatePoolWithTag( - PagedPool, - sizeof(KPH_HANDLE_TABLE), - Tag - ); - - if (!handleTable) - return STATUS_INSUFFICIENT_RESOURCES; - - /* Allocate storage for the handle table itself. */ - handleTable->Table = ExAllocatePoolWithTag( - PagedPool, - MaximumHandles * SizeOfEntry, - Tag - ); - - if (!handleTable->Table) - { - ExFreePoolWithTag(handleTable, Tag); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Initialize the rest of the table descriptor. */ - handleTable->Tag = Tag; - handleTable->SizeOfEntry = SizeOfEntry; - handleTable->NextHandle = (HANDLE)0; - handleTable->FreeHandle = NULL; - ExInitializeFastMutex(&handleTable->Mutex); - handleTable->TableSize = MaximumHandles * SizeOfEntry; - - /* Zero the handle table. */ - memset(handleTable->Table, 0, handleTable->TableSize); - - /* Pass the pointer to the handle table back. */ - *HandleTable = handleTable; - - return STATUS_SUCCESS; -} - -/* KphFreeHandleTable - * - * Frees all handle table resources. - */ -VOID KphFreeHandleTable( - __in PKPH_HANDLE_TABLE HandleTable - ) -{ - ULONG i; - ULONG tag; - - /* Free all handle values. */ - for (i = 0; i < HandleTable->TableSize / HandleTable->SizeOfEntry; i++) - { - KphCloseHandle(HandleTable, KphHandleFromIndex(i)); - } - - /* Save the handle table tag first. */ - tag = HandleTable->Tag; - /* Free the table. */ - ExFreePoolWithTag(HandleTable->Table, tag); - /* Free the descriptor. */ - ExFreePoolWithTag(HandleTable, tag); -} - -/* KphCloseHandle - * - * Closes a handle, dereferencing the referenced object. - */ -NTSTATUS KphCloseHandle( - __in PKPH_HANDLE_TABLE HandleTable, - __in HANDLE Handle - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPH_HANDLE_TABLE_ENTRY entry; - PVOID object; - - if (!KphValidHandle(HandleTable, Handle, &entry)) - return STATUS_INVALID_HANDLE; - - /* Save a pointer to the object referenced by the handle. */ - object = entry->Object; - /* Free the handle. */ - status = KphpFreeHandleEntry(HandleTable, entry); - - if (!NT_SUCCESS(status)) - return status; - - /* Dereference the object. */ - KphDereferenceObject(object); - - return status; -} - -/* KphCreateHandle - * - * Creates a handle and references an object. - */ -NTSTATUS KphCreateHandle( - __in PKPH_HANDLE_TABLE HandleTable, - __in PVOID Object, - __out PHANDLE Handle - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPH_HANDLE_TABLE_ENTRY entry; - - /* Allocate a handle. */ - status = KphpAllocateHandleEntry(HandleTable, &entry); - - if (!NT_SUCCESS(status)) - return status; - - /* Reference and set the object in the entry. */ - KphReferenceObject(Object); - entry->Object = Object; - - /* Pass the handle back. */ - *Handle = KphGetHandleEntry(entry); - - return status; -} - -/* KphReferenceObjectByHandle - * - * References an object from a handle. - */ -NTSTATUS KphReferenceObjectByHandle( - __in PKPH_HANDLE_TABLE HandleTable, - __in HANDLE Handle, - __in_opt PKPH_OBJECT_TYPE ObjectType, - __out PVOID *Object - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPH_HANDLE_TABLE_ENTRY entry; - - if (!KphValidHandle(HandleTable, Handle, &entry)) - return STATUS_INVALID_HANDLE; - - /* Lock the entry. */ - if (!KphLockAllocatedHandleEntry(entry)) - return STATUS_INVALID_HANDLE; - - /* Check the type of object if the caller requested us - * to do that. - */ - if (ObjectType) - { - if (KphGetObjectType(entry->Object) != ObjectType) - { - /* Bad type. */ - KphUnlockHandleEntry(entry); - - return STATUS_OBJECT_TYPE_MISMATCH; - } - } - - /* Reference and pass the object back. */ - KphReferenceObject(entry->Object); - *Object = entry->Object; - - KphUnlockHandleEntry(entry); - - return status; -} - -/* KphValidHandle - * - * Checks if a handle is valid. - */ -BOOLEAN KphValidHandle( - __in PKPH_HANDLE_TABLE HandleTable, - __in HANDLE Handle, - __out_opt PKPH_HANDLE_TABLE_ENTRY *Entry - ) -{ - PKPH_HANDLE_TABLE_ENTRY entry; - BOOLEAN valid; - - entry = KphEntryFromHandle(HandleTable, Handle); - valid = - ((ULONG_PTR)entry >= (ULONG_PTR)HandleTable->Table) && - ((ULONG_PTR)entry + HandleTable->SizeOfEntry <= - (ULONG_PTR)HandleTable->Table + HandleTable->TableSize); - - if (valid) - *Entry = entry; - - return valid; -} - -/* KphpAllocateHandleEntry - * - * Allocates a handle table entry. - */ -NTSTATUS KphpAllocateHandleEntry( - __in PKPH_HANDLE_TABLE HandleTable, - __out PKPH_HANDLE_TABLE_ENTRY *Entry - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPH_HANDLE_TABLE_ENTRY entry = NULL; - - /* Prevent others from modifying the handle table. */ - ExAcquireFastMutex(&HandleTable->Mutex); - - /* Check the free list first. If we have a free entry, - * claim it and update the free list. Otherwise, create - * a new entry from the NextHandle value. - */ - if (HandleTable->FreeHandle) - { - /* We have a free entry. Update the free list. */ - entry = HandleTable->FreeHandle; - /* The next free entry goes into FreeHandle. */ - HandleTable->FreeHandle = KphGetNextFreeEntry(entry); - } - else - { - /* No free handles. We have to initialize a new one - * based on the NextHandle value. - */ - /* Make sure we don't go past the end of the table. */ - if ( - KphIndexFromHandle(HandleTable->NextHandle) * - HandleTable->SizeOfEntry <= - HandleTable->TableSize - ) - { - /* Get a pointer to the entry from the handle. */ - entry = KphEntryFromHandle(HandleTable, HandleTable->NextHandle); - /* Increment the next handle value. */ - HandleTable->NextHandle = KphIncrementHandle(HandleTable->NextHandle); - } - else - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - /* Set the entry's handle value. */ - entry->Handle = KphHandleFromEntry(HandleTable, entry); - KphSetAllocatedEntry(entry); - - *Entry = entry; - } - - ExReleaseFastMutex(&HandleTable->Mutex); - - return status; -} - -/* KphpFreeHandleEntry - * - * Frees a handle table entry. - */ -NTSTATUS KphpFreeHandleEntry( - __in PKPH_HANDLE_TABLE HandleTable, - __in PKPH_HANDLE_TABLE_ENTRY Entry - ) -{ - ExAcquireFastMutex(&HandleTable->Mutex); - - /* Lock the entry. */ - if (!KphLockAllocatedHandleEntry(Entry)) - { - /* Someone else has already freed the entry (or it was never allocated). */ - ExReleaseFastMutex(&HandleTable->Mutex); - return STATUS_INVALID_HANDLE; - } - - /* Mark the entry as unallocated. */ - KphClearAllocatedEntry(Entry); - - /* Add the entry to the free list. */ - KphSetNextFreeEntry(Entry, HandleTable->FreeHandle); - HandleTable->FreeHandle = Entry; - - /* Zero the entry (except for the Value). */ - memset(&Entry->Object, 0, HandleTable->SizeOfEntry - sizeof(ULONG_PTR)); - - /* Unlock the entry. */ - KphUnlockHandleEntry(Entry); - - ExReleaseFastMutex(&HandleTable->Mutex); - - return STATUS_SUCCESS; -} diff --git a/2.x/trunk/KProcessHacker/hook.c b/2.x/trunk/KProcessHacker/hook.c deleted file mode 100644 index 3f775db5d..000000000 --- a/2.x/trunk/KProcessHacker/hook.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Process Hacker Driver - - * hooks - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#include "include/hook.h" -#include "include/sync.h" - -static KPH_PROCESSOR_LOCK HookProcessorLock; - -/* KphHookInit - * - * Initializes the hooking module. - */ -NTSTATUS KphHookInit() -{ - KphInitializeProcessorLock(&HookProcessorLock); - - return STATUS_SUCCESS; -} - -/* KphInitializeHook - * - * Initializes a hook structure. - */ -VOID KphInitializeHook( - __out PKPH_HOOK Hook, - __in PVOID Function, - __in PVOID Target - ) -{ - memset(Hook, 0, sizeof(KPH_HOOK)); - Hook->Function = Function; - Hook->Target = Target; -} - -/* KphHook - * - * Hooks a kernel-mode function. - * WARNING: DO NOT HOOK A FUNCTION THAT IS CALLABLE ABOVE APC_LEVEL. - * - * Thread safety: Full - * IRQL: <= APC_LEVEL - */ -NTSTATUS KphHook( - __inout PKPH_HOOK Hook - ) -{ - NTSTATUS status = STATUS_SUCCESS; - MAPPED_MDL mappedMdl; - PUCHAR function; - - status = KphpCreateMappedMdl( - Hook->Function, - 5, - &mappedMdl - ); - - if (!NT_SUCCESS(status)) - return status; - - function = (PUCHAR)mappedMdl.Address; - - /* Acquire a lock on all other processors. */ - if (KphAcquireProcessorLock(&HookProcessorLock)) - { - /* Note that this is completely safe even though we are at - * DISPATCH_LEVEL because we are using the mapped MDL. - */ - /* Copy the original five bytes (for unhooking). */ - memcpy(Hook->Bytes, function, 10); - /* Hook the function by writing a jump instruction. */ - Hook->Hooked = TRUE; - /* jmp Target */ - *function = 0xe9; - *(PULONG_PTR)(function + 1) = (ULONG_PTR)Hook->Target - (ULONG_PTR)Hook->Function - 5; - - /* Release the processor lock. */ - KphReleaseProcessorLock(&HookProcessorLock); - } - else - { - dprintf("KphHook: Could not acquire processor lock!\n"); - status = STATUS_INSUFFICIENT_RESOURCES; - } - - KphpFreeMappedMdl(&mappedMdl); - - return status; -} - -/* KphUnhook - * - * Unhooks a kernel-mode function. - * WARNING: DO NOT UNHOOK A FUNCTION THAT IS CALLABLE ABOVE APC_LEVEL. - * - * Thread safety: Full - * IRQL: <= APC_LEVEL - */ -NTSTATUS KphUnhook( - __inout PKPH_HOOK Hook - ) -{ - NTSTATUS status = STATUS_SUCCESS; - MAPPED_MDL mappedMdl; - - if (!Hook->Hooked) - return STATUS_UNSUCCESSFUL; - - status = KphpCreateMappedMdl( - Hook->Function, - 5, - &mappedMdl - ); - - if (!NT_SUCCESS(status)) - return status; - - /* Acquire a lock on all other processors. */ - if (KphAcquireProcessorLock(&HookProcessorLock)) - { - /* Unpatch the function. */ - memcpy(mappedMdl.Address, Hook->Bytes, 5); - Hook->Hooked = FALSE; - /* Release the processor lock. */ - KphReleaseProcessorLock(&HookProcessorLock); - } - else - { - dprintf("KphUnhook: Could not acquire processor lock!\n"); - status = STATUS_INSUFFICIENT_RESOURCES; - } - - KphpFreeMappedMdl(&mappedMdl); - - return status; -} - -/* KphObOpenCall - * - * Calls the original open procedure for an object type. - * - * AccessMode: If this argument is unavailable, specify KernelMode. - */ -NTSTATUS NTAPI KphObOpenCall( - __in PKPH_OB_OPEN_HOOK ObOpenHook, - __in OB_OPEN_REASON OpenReason, - __in KPROCESSOR_MODE AccessMode, - __in PEPROCESS Process, - __in PVOID Object, - __in ACCESS_MASK GrantedAccess, - __in ULONG HandleCount - ) -{ - /* If there wasn't any original open procedure, exit. */ - if (!ObOpenHook->Function) - return STATUS_SUCCESS; - - if (WindowsVersion == WINDOWS_XP) - { - return ((OB_OPEN_METHOD_51)ObOpenHook->Function)( - OpenReason, - Process, - Object, - GrantedAccess, - HandleCount - ); - } - else if ( - WindowsVersion == WINDOWS_VISTA || - WindowsVersion == WINDOWS_7 - ) - { - return ((OB_OPEN_METHOD_60)ObOpenHook->Function)( - OpenReason, - AccessMode, - Process, - Object, - GrantedAccess, - HandleCount - ); - } - else - { - return STATUS_NOT_SUPPORTED; - } -} - -/* KphInitializeObOpenHook - * - * Initializes a hook structure. - */ -VOID KphInitializeObOpenHook( - __inout PKPH_OB_OPEN_HOOK ObOpenHook, - __in POBJECT_TYPE ObjectType, - __in PVOID Target51, - __in PVOID Target60 - ) -{ - memset(ObOpenHook, 0, sizeof(KPH_OB_OPEN_HOOK)); - ObOpenHook->ObjectType = ObjectType; - ObOpenHook->Target51 = Target51; - ObOpenHook->Target60 = Target60; -} - -/* KphObOpenHook - * - * Hooks the open procedure for an object type. - * - * Thread safety: Full - * IRQL: <= APC_LEVEL - */ -NTSTATUS KphObOpenHook( - __inout PKPH_OB_OPEN_HOOK ObOpenHook - ) -{ - NTSTATUS status = STATUS_SUCCESS; - MAPPED_MDL mappedMdl; - PVOID *openProcedure; - - status = KphpCreateMappedMdl( - KVOFF(ObOpenHook->ObjectType, OffOtiOpenProcedure), - sizeof(PVOID), - &mappedMdl - ); - - if (!NT_SUCCESS(status)) - return status; - - openProcedure = (PVOID *)mappedMdl.Address; - - /* Acquire a lock on all other processors. */ - if (KphAcquireProcessorLock(&HookProcessorLock)) - { - /* Save the original open procedure pointer. */ - ObOpenHook->Function = *openProcedure; - - /* Choose the correct target open procedure and hook. */ - if (WindowsVersion == WINDOWS_XP) - { - if (ObOpenHook->Target51) - *openProcedure = ObOpenHook->Target51; - else - status = STATUS_INVALID_PARAMETER; - } - else if ( - WindowsVersion == WINDOWS_VISTA || - WindowsVersion == WINDOWS_7 - ) - { - if (ObOpenHook->Target60) - *openProcedure = ObOpenHook->Target60; - else - status = STATUS_INVALID_PARAMETER; - } - else - { - status = STATUS_NOT_SUPPORTED; - } - - ObOpenHook->Hooked = TRUE; - - /* Release the processor lock. */ - KphReleaseProcessorLock(&HookProcessorLock); - } - else - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - - KphpFreeMappedMdl(&mappedMdl); - - return status; -} - -/* KphObOpenUnhook - * - * Unhooks the open procedure for an object type. - * - * Thread safety: Full - * IRQL: <= APC_LEVEL - */ -NTSTATUS KphObOpenUnhook( - __inout PKPH_OB_OPEN_HOOK ObOpenHook - ) -{ - NTSTATUS status = STATUS_SUCCESS; - MAPPED_MDL mappedMdl; - PVOID *openProcedure; - - if (!ObOpenHook->Hooked) - return STATUS_UNSUCCESSFUL; - - status = KphpCreateMappedMdl( - KVOFF(ObOpenHook->ObjectType, OffOtiOpenProcedure), - sizeof(PVOID), - &mappedMdl - ); - - if (!NT_SUCCESS(status)) - return status; - - openProcedure = (PVOID *)mappedMdl.Address; - - /* Acquire a lock on all other processors. */ - if (KphAcquireProcessorLock(&HookProcessorLock)) - { - /* Restore the original open procedure pointer. */ - *openProcedure = ObOpenHook->Function; - ObOpenHook->Hooked = FALSE; - - /* Release the processor lock. */ - KphReleaseProcessorLock(&HookProcessorLock); - } - else - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - - KphpFreeMappedMdl(&mappedMdl); - - return status; -} - -/* KphpCreateMappedMdl - * - * Creates and maps a MDL. - * - * Thread safety: Full - * IRQL: Any - */ -NTSTATUS KphpCreateMappedMdl( - __in PVOID Address, - __in ULONG Length, - __out PMAPPED_MDL MappedMdl - ) -{ - PMDL mdl; - - MappedMdl->Mdl = NULL; - MappedMdl->Address = NULL; - - mdl = IoAllocateMdl(Address, Length, FALSE, FALSE, NULL); - - if (mdl == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - - MmBuildMdlForNonPagedPool(mdl); - mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; - MappedMdl->Address = MmMapLockedPagesSpecifyCache( - mdl, - KernelMode, - MmNonCached, - NULL, - FALSE, - HighPagePriority - ); - MappedMdl->Mdl = mdl; - - if (!MappedMdl->Address) - { - KphpFreeMappedMdl(MappedMdl); - return STATUS_INSUFFICIENT_RESOURCES; - } - - return STATUS_SUCCESS; -} - -/* KphpFreeMappedMdl - * - * Unmaps and frees a MDL. - * - * Thread safety: Full - * IRQL: Any - */ -VOID KphpFreeMappedMdl( - __in PMAPPED_MDL MappedMdl - ) -{ - if (MappedMdl->Mdl != NULL) - { - if (MappedMdl->Address != NULL) - { - MmUnmapLockedPages(MappedMdl->Address, MappedMdl->Mdl); - MappedMdl->Address = NULL; - } - - IoFreeMdl(MappedMdl->Mdl); - MappedMdl->Mdl = NULL; - } -} diff --git a/2.x/trunk/KProcessHacker/i386/kprocesshacker.sys b/2.x/trunk/KProcessHacker/i386/kprocesshacker.sys index 4788d67ea..7ee2c6349 100644 Binary files a/2.x/trunk/KProcessHacker/i386/kprocesshacker.sys and b/2.x/trunk/KProcessHacker/i386/kprocesshacker.sys differ diff --git a/2.x/trunk/KProcessHacker/include/ex.h b/2.x/trunk/KProcessHacker/include/ex.h index bfd06ccbe..0303ced48 100644 --- a/2.x/trunk/KProcessHacker/include/ex.h +++ b/2.x/trunk/KProcessHacker/include/ex.h @@ -23,8 +23,6 @@ #ifndef _EX_H #define _EX_H -#include "types.h" - /* HACK - version.c dependency */ #define WINDOWS_XP 51 #define WINDOWS_SERVER_2003 52 diff --git a/2.x/trunk/KProcessHacker/include/handle.h b/2.x/trunk/KProcessHacker/include/handle.h deleted file mode 100644 index 710205b3e..000000000 --- a/2.x/trunk/KProcessHacker/include/handle.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Process Hacker Driver - - * handle table - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#ifndef _HANDLE_H -#define _HANDLE_H - -#include "kph.h" -#include "ref.h" - -struct _KPH_HANDLE_TABLE; -typedef struct _KPH_HANDLE_TABLE *PKPH_HANDLE_TABLE; - -typedef struct _KPH_HANDLE_TABLE_ENTRY -{ - union - { - HANDLE Handle; - ULONG_PTR Value; - struct _KPH_HANDLE_TABLE_ENTRY *NextFree; - }; - PVOID Object; -} KPH_HANDLE_TABLE_ENTRY, *PKPH_HANDLE_TABLE_ENTRY; - -NTSTATUS KphCreateHandleTable( - __out PKPH_HANDLE_TABLE *HandleTable, - __in ULONG MaximumHandles, - __in ULONG SizeOfEntry, - __in ULONG Tag - ); - -VOID KphFreeHandleTable( - __in PKPH_HANDLE_TABLE HandleTable - ); - -NTSTATUS KphCloseHandle( - __in PKPH_HANDLE_TABLE HandleTable, - __in HANDLE Handle - ); - -NTSTATUS KphCreateHandle( - __in PKPH_HANDLE_TABLE HandleTable, - __in PVOID Object, - __out PHANDLE Handle - ); - -NTSTATUS KphReferenceObjectByHandle( - __in PKPH_HANDLE_TABLE HandleTable, - __in HANDLE Handle, - __in_opt PKPH_OBJECT_TYPE ObjectType, - __out PVOID *Object - ); - -BOOLEAN KphValidHandle( - __in PKPH_HANDLE_TABLE HandleTable, - __in HANDLE Handle, - __out_opt PKPH_HANDLE_TABLE_ENTRY *Entry - ); - -#endif diff --git a/2.x/trunk/KProcessHacker/include/handlep.h b/2.x/trunk/KProcessHacker/include/handlep.h deleted file mode 100644 index a6cd445ee..000000000 --- a/2.x/trunk/KProcessHacker/include/handlep.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Process Hacker Driver - - * handle table - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#ifndef _HANDLEP_H -#define _HANDLEP_H - -#define _HANDLE_PRIVATE -#include "handle.h" -#include "sync.h" - -#define KPH_HANDLE_INCREMENT 4 -#define KPH_HANDLE_LOCKED 0x1 -#define KPH_HANDLE_LOCKED_SHIFT 0 -#define KPH_HANDLE_ALLOCATED 0x2 -#define KPH_HANDLE_FLAGS 0x3 - -#define KphGetFlagsEntry(Entry) ((Entry)->Value & KPH_HANDLE_FLAGS) -#define KphGetHandleEntry(Entry) ((HANDLE)((Entry)->Value & ~KPH_HANDLE_FLAGS)) -#define KphIncrementHandle(Handle) ((HANDLE)((ULONG_PTR)(Handle) + KPH_HANDLE_INCREMENT)) - -#define KphIsAllocatedEntry(Entry) ((Entry)->Value & KPH_HANDLE_ALLOCATED) -#define KphClearAllocatedEntry(Entry) ((Entry)->Value &= ~KPH_HANDLE_ALLOCATED) -#define KphSetAllocatedEntry(Entry) ((Entry)->Value |= KPH_HANDLE_ALLOCATED) - -#define KphGetNextFreeEntry(Entry) ((PKPH_HANDLE_TABLE_ENTRY)((Entry)->Value & ~KPH_HANDLE_FLAGS)) -#define KphSetNextFreeEntry(Entry, NextFree) ((Entry)->Value = ((ULONG_PTR)(NextFree) | KphGetFlagsEntry(Entry))) - -#define KphHandleFromIndex(Index) ((HANDLE)((ULONG_PTR)(Index) * KPH_HANDLE_INCREMENT)) -#define KphHandleFromIndexEx(Index, Flags) ((HANDLE)(((Index) * KPH_HANDLE_INCREMENT) | (Flags))) -#define KphIndexFromHandle(Handle) (((ULONG_PTR)(Handle) & ~KPH_HANDLE_FLAGS) / KPH_HANDLE_INCREMENT) - -#define KphEntryFromHandle(HandleTable, Handle) KphEntryFromIndex((HandleTable), KphIndexFromHandle(Handle)) -#define KphEntryFromIndex(HandleTable, Index) \ - ((PKPH_HANDLE_TABLE_ENTRY)((ULONG_PTR)(HandleTable)->Table + (Index) * (HandleTable)->SizeOfEntry)) -#define KphHandleFromEntry(HandleTable, Entry) KphHandleFromIndex(KphIndexFromEntry((HandleTable), (Entry))) -#define KphHandleFromEntryEx(HandleTable, Entry, Flags) \ - KphHandleFromIndexEx(KphIndexFromEntry((HandleTable), (Entry)), (Flags)) -#define KphIndexFromEntry(HandleTable, Entry) \ - (((ULONG_PTR)(Entry) - (ULONG_PTR)(HandleTable)->Table) / (HandleTable)->SizeOfEntry) - -typedef struct _KPH_HANDLE_TABLE -{ - /* The pool tag used for this descriptor and the table itself. */ - ULONG Tag; - /* The size of each handle table entry. */ - ULONG SizeOfEntry; - /* The next handle value to use. */ - HANDLE NextHandle; - /* The free list of handle table entries. */ - struct _KPH_HANDLE_TABLE_ENTRY *FreeHandle; - - /* A fast mutex guarding writes to the handle table. */ - FAST_MUTEX Mutex; - /* The size of the table, in bytes. */ - ULONG TableSize; - /* The actual handle table. */ - PVOID Table; -} KPH_HANDLE_TABLE, *PKPH_HANDLE_TABLE; - -FORCEINLINE BOOLEAN KphLockHandleEntry( - __inout PKPH_HANDLE_TABLE_ENTRY Entry - ); - -FORCEINLINE BOOLEAN KphLockAllocatedHandleEntry( - __inout PKPH_HANDLE_TABLE_ENTRY Entry - ); - -FORCEINLINE VOID KphUnlockHandleEntry( - __inout PKPH_HANDLE_TABLE_ENTRY Entry - ); - -/* KphLockHandle - * - * Locks a handle table entry for exclusive access. Do not - * modify the lowest bit of the entry's value while you - * hold the lock. - * - * Return value: TRUE if the entry is allocated, otherwise FALSE. - */ -FORCEINLINE BOOLEAN KphLockHandleEntry( - __inout PKPH_HANDLE_TABLE_ENTRY Entry - ) -{ - /* Acquire the spinlock. */ - KphAcquireBitSpinLock((PLONG)&Entry->Value, KPH_HANDLE_LOCKED_SHIFT); - - /* Return whether the entry is allocated. */ - return !!(Entry->Value & KPH_HANDLE_ALLOCATED); -} - -/* KphLockAllocatedHandle - * - * Locks a handle table entry for exclusive access. Do not - * modify the lowest bit of the entry's value while you - * hold the lock. - * The function will not lock the handle if it is unallocated. - * - * Return value: TRUE if the entry was locked, otherwise FALSE. - */ -FORCEINLINE BOOLEAN KphLockAllocatedHandleEntry( - __inout PKPH_HANDLE_TABLE_ENTRY Entry - ) -{ - if (!KphLockHandleEntry(Entry)) - { - KphUnlockHandleEntry(Entry); - return FALSE; - } - - return TRUE; -} - -/* KphUnlockHandle - * - * Unlocks a handle table entry. - */ -FORCEINLINE VOID KphUnlockHandleEntry( - __inout PKPH_HANDLE_TABLE_ENTRY Entry - ) -{ - /* Unlock the spinlock. */ - KphReleaseBitSpinLock((PLONG)&Entry->Value, KPH_HANDLE_LOCKED_SHIFT); -} - -#endif diff --git a/2.x/trunk/KProcessHacker/include/hook.h b/2.x/trunk/KProcessHacker/include/hook.h deleted file mode 100644 index 12ec3d3f9..000000000 --- a/2.x/trunk/KProcessHacker/include/hook.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Process Hacker Driver - - * hooks - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#ifndef _HOOK_H -#define _HOOK_H - -#include "kph.h" -#include "ob.h" - -#define KPH_DEFINE_HOOK_CALL(Name, Arguments, Hook) \ - __declspec(naked) Name(Arguments) \ - { \ - __asm lea eax, Hook \ - __asm mov eax, [eax+KPH_HOOK.Function] \ - __asm add eax, 5 \ - __asm push ebp \ - __asm mov ebp, esp \ - __asm jmp eax \ - } \ - -typedef struct _KPH_HOOK -{ - /* The address of the hooked function. - Should NOT be a function that is callable above PASSIVE_LEVEL. */ - PVOID Function; - /* The address of the new function. */ - PVOID Target; - /* Whether the function is hooked. */ - BOOLEAN Hooked; - /* The original first 10 bytes. */ - CHAR Bytes[10]; -} KPH_HOOK, *PKPH_HOOK; - -typedef struct _KPH_OB_OPEN_HOOK -{ - /* The object type that is being hooked. */ - POBJECT_TYPE ObjectType; - /* The original open procedure. */ - PVOID Function; - /* The new open procedure for NT 5.1 (XP). */ - OB_OPEN_METHOD_51 Target51; - /* The new open procedure for NT 6.1 and above (Vista, 7 or higher). */ - OB_OPEN_METHOD_60 Target60; - /* Whether the open procedure is hooked. */ - BOOLEAN Hooked; -} KPH_OB_OPEN_HOOK, *PKPH_OB_OPEN_HOOK; - -NTSTATUS KphHookInit(); - -VOID KphInitializeHook( - __out PKPH_HOOK Hook, - __in PVOID Function, - __in PVOID Target - ); - -NTSTATUS KphHook( - __inout PKPH_HOOK Hook - ); - -NTSTATUS KphUnhook( - __inout PKPH_HOOK Hook - ); - -NTSTATUS NTAPI KphObOpenCall( - __in PKPH_OB_OPEN_HOOK ObOpenHook, - __in OB_OPEN_REASON OpenReason, - __in KPROCESSOR_MODE AccessMode, - __in PEPROCESS Process, - __in PVOID Object, - __in ACCESS_MASK GrantedAccess, - __in ULONG HandleCount - ); - -VOID KphInitializeObOpenHook( - __inout PKPH_OB_OPEN_HOOK ObOpenHook, - __in POBJECT_TYPE ObjectType, - __in PVOID Target51, - __in PVOID Target60 - ); - -NTSTATUS KphObOpenHook( - __inout PKPH_OB_OPEN_HOOK ObOpenHook - ); - -NTSTATUS KphObOpenUnhook( - __inout PKPH_OB_OPEN_HOOK ObOpenHook - ); - -#endif diff --git a/2.x/trunk/KProcessHacker/include/io.h b/2.x/trunk/KProcessHacker/include/io.h index bc98fb151..624c27dda 100644 --- a/2.x/trunk/KProcessHacker/include/io.h +++ b/2.x/trunk/KProcessHacker/include/io.h @@ -23,8 +23,6 @@ #ifndef _IO_H #define _IO_H -#include "types.h" - extern POBJECT_TYPE *IoAdapterObjectType; extern POBJECT_TYPE *IoControllerObjectType; extern POBJECT_TYPE *IoDeviceHandlerObjectType; /* not used anymore */ diff --git a/2.x/trunk/KProcessHacker/include/ke.h b/2.x/trunk/KProcessHacker/include/ke.h index 741c1b00b..998a27b96 100644 --- a/2.x/trunk/KProcessHacker/include/ke.h +++ b/2.x/trunk/KProcessHacker/include/ke.h @@ -23,8 +23,6 @@ #ifndef _KE_H #define _KE_H -#include "types.h" - /* APCs */ typedef enum _KAPC_ENVIRONMENT diff --git a/2.x/trunk/KProcessHacker/include/kph.h b/2.x/trunk/KProcessHacker/include/kph.h index 99c7a8e8d..dfb8cc7c9 100644 --- a/2.x/trunk/KProcessHacker/include/kph.h +++ b/2.x/trunk/KProcessHacker/include/kph.h @@ -23,16 +23,23 @@ #ifndef _KPH_H #define _KPH_H -#include "types.h" +#include + #include "debug.h" #include "ref.h" +#include "util.h" #include "version.h" +#include "ex.h" +#include "io.h" #include "ke.h" #include "mm.h" +#include "ob.h" #include "ps.h" -#include "trace.h" +#include "se.h" #include "zw.h" + +#include "trace.h" #define MAX_UINTEGER(Bits) ((1 << (Bits)) - 1) #define BITS_UCHAR 8 @@ -74,7 +81,6 @@ EXT POBJECT_TYPE *ObDirectoryObjectType EQNULL; EXT POBJECT_TYPE *ObTypeObjectType EQNULL; EXT PKSERVICE_TABLE_DESCRIPTOR __KeServiceDescriptorTable EQNULL; -EXT PVOID __KiFastCallEntry EQNULL; EXT _NtClose __NtClose EQNULL; EXT _ObGetObjectType ObGetObjectType EQNULL; EXT _PsGetProcessJob PsGetProcessJob EQNULL; @@ -180,8 +186,8 @@ NTSTATUS OpenProcess( ); NTSTATUS SetProcessToken( - __in HANDLE sourcePid, - __in HANDLE targetPid + __in HANDLE SourcePid, + __in HANDLE TargetPid ); /* KProcessHacker */ diff --git a/2.x/trunk/KProcessHacker/include/kprocesshacker.h b/2.x/trunk/KProcessHacker/include/kprocesshacker.h index 0df5a7326..703b074e9 100644 --- a/2.x/trunk/KProcessHacker/include/kprocesshacker.h +++ b/2.x/trunk/KProcessHacker/include/kprocesshacker.h @@ -23,11 +23,6 @@ #ifndef KPROCESSHACKER_H #define KPROCESSHACKER_H -#include "include/kph.h" -#include "include/handle.h" -#include "include/ref.h" -#include "include/sync.h" - /* KPH Configuration */ //#define KPH_REQUIRE_DEBUG_PRIVILEGE @@ -35,8 +30,8 @@ /* Device */ #define KPH_DEVICE_TYPE (0x9999) -#define KPH_DEVICE_NAME (L"\\Device\\KProcessHacker") -#define KPH_DEVICE_DOS_NAME (L"\\DosDevices\\KProcessHacker") +#define KPH_DEVICE_NAME (L"\\Device\\KProcessHacker2") +#define KPH_DEVICE_DOS_NAME (L"\\DosDevices\\KProcessHacker2") /* Features */ @@ -46,63 +41,56 @@ /* Control Codes */ #define KPH_CTL_CODE(x) CTL_CODE(KPH_DEVICE_TYPE, 0x800 + x, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define KPH_CLOSEHANDLE KPH_CTL_CODE(0) -#define KPH_SSQUERYCLIENTENTRY KPH_CTL_CODE(1) -#define KPH_RESERVED1 KPH_CTL_CODE(2) -#define KPH_OPENPROCESS KPH_CTL_CODE(3) -#define KPH_OPENTHREAD KPH_CTL_CODE(4) -#define KPH_OPENPROCESSTOKEN KPH_CTL_CODE(5) -#define KPH_GETPROCESSPROTECTED KPH_CTL_CODE(6) -#define KPH_SETPROCESSPROTECTED KPH_CTL_CODE(7) -#define KPH_TERMINATEPROCESS KPH_CTL_CODE(8) -#define KPH_SUSPENDPROCESS KPH_CTL_CODE(9) -#define KPH_RESUMEPROCESS KPH_CTL_CODE(10) -#define KPH_READVIRTUALMEMORY KPH_CTL_CODE(11) -#define KPH_WRITEVIRTUALMEMORY KPH_CTL_CODE(12) -#define KPH_SETPROCESSTOKEN KPH_CTL_CODE(13) -#define KPH_GETTHREADSTARTADDRESS KPH_CTL_CODE(14) -#define KPH_SETHANDLEATTRIBUTES KPH_CTL_CODE(15) -#define KPH_GETHANDLEOBJECTNAME KPH_CTL_CODE(16) -#define KPH_OPENPROCESSJOB KPH_CTL_CODE(17) -#define KPH_GETCONTEXTTHREAD KPH_CTL_CODE(18) -#define KPH_SETCONTEXTTHREAD KPH_CTL_CODE(19) -#define KPH_GETTHREADWIN32THREAD KPH_CTL_CODE(20) -#define KPH_DUPLICATEOBJECT KPH_CTL_CODE(21) -#define KPH_ZWQUERYOBJECT KPH_CTL_CODE(22) -#define KPH_GETPROCESSID KPH_CTL_CODE(23) -#define KPH_GETTHREADID KPH_CTL_CODE(24) -#define KPH_TERMINATETHREAD KPH_CTL_CODE(25) -#define KPH_GETFEATURES KPH_CTL_CODE(26) -#define KPH_SETHANDLEGRANTEDACCESS KPH_CTL_CODE(27) -#define KPH_ASSIGNIMPERSONATIONTOKEN KPH_CTL_CODE(28) -#define KPH_PROTECTADD KPH_CTL_CODE(29) -#define KPH_PROTECTREMOVE KPH_CTL_CODE(30) -#define KPH_PROTECTQUERY KPH_CTL_CODE(31) -#define KPH_UNSAFEREADVIRTUALMEMORY KPH_CTL_CODE(32) -#define KPH_SETEXECUTEOPTIONS KPH_CTL_CODE(33) -#define KPH_QUERYPROCESSHANDLES KPH_CTL_CODE(34) -#define KPH_OPENTHREADPROCESS KPH_CTL_CODE(35) -#define KPH_CAPTURESTACKBACKTRACETHREAD KPH_CTL_CODE(36) -#define KPH_DANGEROUSTERMINATETHREAD KPH_CTL_CODE(37) -#define KPH_OPENTYPE KPH_CTL_CODE(38) -#define KPH_OPENDRIVER KPH_CTL_CODE(39) -#define KPH_QUERYINFORMATIONDRIVER KPH_CTL_CODE(40) -#define KPH_OPENDIRECTORYOBJECT KPH_CTL_CODE(41) -#define KPH_SSREF KPH_CTL_CODE(42) -#define KPH_SSUNREF KPH_CTL_CODE(43) -#define KPH_SSCREATECLIENTENTRY KPH_CTL_CODE(44) -#define KPH_SSCREATERULESETENTRY KPH_CTL_CODE(45) -#define KPH_SSREMOVERULE KPH_CTL_CODE(46) -#define KPH_SSADDPROCESSIDRULE KPH_CTL_CODE(47) -#define KPH_SSADDTHREADIDRULE KPH_CTL_CODE(48) -#define KPH_SSADDPREVIOUSMODERULE KPH_CTL_CODE(49) -#define KPH_SSADDNUMBERRULE KPH_CTL_CODE(50) -#define KPH_SSENABLECLIENTENTRY KPH_CTL_CODE(51) -#define KPH_OPENNAMEDOBJECT KPH_CTL_CODE(52) -#define KPH_QUERYINFORMATIONPROCESS KPH_CTL_CODE(53) -#define KPH_QUERYINFORMATIONTHREAD KPH_CTL_CODE(54) -#define KPH_SETINFORMATIONPROCESS KPH_CTL_CODE(55) -#define KPH_SETINFORMATIONTHREAD KPH_CTL_CODE(56) + +/* General */ +#define KPH_GETFEATURES KPH_CTL_CODE(0) + +/* Processes */ +#define KPH_OPENPROCESS KPH_CTL_CODE(50) +#define KPH_OPENPROCESSTOKEN KPH_CTL_CODE(51) +#define KPH_OPENPROCESSJOB KPH_CTL_CODE(52) +#define KPH_SUSPENDPROCESS KPH_CTL_CODE(53) +#define KPH_RESUMEPROCESS KPH_CTL_CODE(54) +#define KPH_TERMINATEPROCESS KPH_CTL_CODE(55) +#define KPH_READVIRTUALMEMORY KPH_CTL_CODE(56) +#define KPH_WRITEVIRTUALMEMORY KPH_CTL_CODE(57) +#define KPH_UNSAFEREADVIRTUALMEMORY KPH_CTL_CODE(58) +#define KPH_GETPROCESSPROTECTED KPH_CTL_CODE(59) +#define KPH_SETPROCESSPROTECTED KPH_CTL_CODE(60) +#define KPH_SETEXECUTEOPTIONS KPH_CTL_CODE(61) +#define KPH_SETPROCESSTOKEN KPH_CTL_CODE(62) +#define KPH_QUERYINFORMATIONPROCESS KPH_CTL_CODE(63) +#define KPH_QUERYINFORMATIONTHREAD KPH_CTL_CODE(64) +#define KPH_SETINFORMATIONPROCESS KPH_CTL_CODE(65) +#define KPH_SETINFORMATIONTHREAD KPH_CTL_CODE(66) + +/* Threads */ +#define KPH_OPENTHREAD KPH_CTL_CODE(100) +#define KPH_OPENTHREADPROCESS KPH_CTL_CODE(101) +#define KPH_TERMINATETHREAD KPH_CTL_CODE(102) +#define KPH_DANGEROUSTERMINATETHREAD KPH_CTL_CODE(103) +#define KPH_GETCONTEXTTHREAD KPH_CTL_CODE(104) +#define KPH_SETCONTEXTTHREAD KPH_CTL_CODE(105) +#define KPH_CAPTURESTACKBACKTRACETHREAD KPH_CTL_CODE(106) +#define KPH_GETTHREADWIN32THREAD KPH_CTL_CODE(107) +#define KPH_ASSIGNIMPERSONATIONTOKEN KPH_CTL_CODE(108) + +/* Handles */ +#define KPH_QUERYPROCESSHANDLES KPH_CTL_CODE(150) +#define KPH_GETHANDLEOBJECTNAME KPH_CTL_CODE(151) +#define KPH_ZWQUERYOBJECT KPH_CTL_CODE(152) +#define KPH_DUPLICATEOBJECT KPH_CTL_CODE(153) +#define KPH_SETHANDLEATTRIBUTES KPH_CTL_CODE(154) +#define KPH_SETHANDLEGRANTEDACCESS KPH_CTL_CODE(155) +#define KPH_GETPROCESSID KPH_CTL_CODE(156) +#define KPH_GETTHREADID KPH_CTL_CODE(157) + +/* Objects */ +#define KPH_OPENNAMEDOBJECT KPH_CTL_CODE(200) +#define KPH_OPENDIRECTORYOBJECT KPH_CTL_CODE(201) +#define KPH_OPENDRIVER KPH_CTL_CODE(202) +#define KPH_QUERYINFORMATIONDRIVER KPH_CTL_CODE(203) +#define KPH_OPENTYPE KPH_CTL_CODE(204) /* Standard Driver Routines */ @@ -114,57 +102,4 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); NTSTATUS KphDispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp); NTSTATUS KphUnsupported(PDEVICE_OBJECT DeviceObject, PIRP Irp); -/* Clients */ - -#define TAG_CLIENT_HANDLETABLE ('HChP') -#define KPH_CLIENT_SSMAXCOUNT 1000 -#define KPH_CLIENT_MAXHANDLES 100 - -typedef struct _KPH_CLIENT_ENTRY -{ - LIST_ENTRY ClientListEntry; - HANDLE ProcessId; - PKPH_HANDLE_TABLE HandleTable; - - KPH_GUARDED_LOCK SsLock; - /* The number of times the client has "started" the system service logger. */ - LONG SsStartCount; -} KPH_CLIENT_ENTRY, *PKPH_CLIENT_ENTRY; - -/* Functions */ - -VOID SsRef(LONG count); -VOID SsUnref(LONG count); - -VOID NTAPI ClientEntryDeleteProcedure( - __in PVOID Object, - __in ULONG Flags - ); - -PKPH_CLIENT_ENTRY CreateClientEntry( - __in HANDLE ProcessId - ); - -PKPH_CLIENT_ENTRY ReferenceClientEntry( - __in_opt HANDLE ProcessId - ); - -NTSTATUS CloseClientHandle( - __in_opt HANDLE ProcessId, - __in HANDLE Handle - ); - -NTSTATUS CreateClientHandle( - __in_opt HANDLE ProcessId, - __in PVOID Object, - __out PHANDLE Handle - ); - -NTSTATUS ReferenceClientHandle( - __in_opt HANDLE ProcessId, - __in HANDLE Handle, - __in PKPH_OBJECT_TYPE ObjectType, - __out PVOID *Object - ); - #endif \ No newline at end of file diff --git a/2.x/trunk/KProcessHacker/include/ob.h b/2.x/trunk/KProcessHacker/include/ob.h index 783629c12..6b1c3f4c7 100644 --- a/2.x/trunk/KProcessHacker/include/ob.h +++ b/2.x/trunk/KProcessHacker/include/ob.h @@ -23,9 +23,6 @@ #ifndef _OB_H #define _OB_H -#include "types.h" -#include "ex.h" - #define OBJECT_TO_OBJECT_HEADER(o) \ CONTAINING_RECORD((o), OBJECT_HEADER, Body) diff --git a/2.x/trunk/KProcessHacker/include/protect.h b/2.x/trunk/KProcessHacker/include/protect.h deleted file mode 100644 index b714ab1b0..000000000 --- a/2.x/trunk/KProcessHacker/include/protect.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Process Hacker Driver - - * process protection - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#ifndef _PROTECT_H -#define _PROTECT_H - -#include "hook.h" - -#define TAG_PROTECTION_ENTRY ('rPhP') - -#define OBOPENOBJECTBYPOINTER_ARGS \ - PVOID Object, \ - ULONG HandleAttributes, \ - PACCESS_STATE PassedAccessState, \ - ACCESS_MASK DesiredAccess, \ - POBJECT_TYPE ObjectType, \ - KPROCESSOR_MODE AccessMode, \ - PHANDLE Handle - -typedef struct _KPH_PROCESS_ENTRY -{ - LIST_ENTRY ListEntry; - PEPROCESS Process; - PEPROCESS CreatorProcess; - HANDLE Tag; - LOGICAL AllowKernelMode; - ACCESS_MASK ProcessAllowMask; - ACCESS_MASK ThreadAllowMask; -} KPH_PROCESS_ENTRY, *PKPH_PROCESS_ENTRY; - -NTSTATUS NTAPI KphNewObOpenObjectByPointer(OBOPENOBJECTBYPOINTER_ARGS); -NTSTATUS NTAPI KphOldObOpenObjectByPointer(OBOPENOBJECTBYPOINTER_ARGS); - -NTSTATUS NTAPI KphNewOpenProcedure51( - __in OB_OPEN_REASON OpenReason, - __in PEPROCESS Process, - __in PVOID Object, - __in ACCESS_MASK GrantedAccess, - __in ULONG HandleCount - ); - -NTSTATUS NTAPI KphNewOpenProcedure60( - __in OB_OPEN_REASON OpenReason, - __in KPROCESSOR_MODE AccessMode, - __in PEPROCESS Process, - __in PVOID Object, - __in ACCESS_MASK GrantedAccess, - __in ULONG HandleCount - ); - -NTSTATUS KphProtectInit(); -NTSTATUS KphProtectDeinit(); - -PKPH_PROCESS_ENTRY KphProtectAddEntry( - __in PEPROCESS Process, - __in HANDLE Tag, - __in LOGICAL AllowKernelMode, - __in ACCESS_MASK ProcessAllowMask, - __in ACCESS_MASK ThreadAllowMask - ); - -PKPH_PROCESS_ENTRY KphProtectFindEntry( - __in PEPROCESS Process, - __in HANDLE Tag, - __out_opt PKPH_PROCESS_ENTRY ProcessEntryCopy - ); - -BOOLEAN KphProtectRemoveByProcess( - __in PEPROCESS Process - ); - -ULONG KphProtectRemoveByTag( - __in HANDLE Tag - ); - -#endif diff --git a/2.x/trunk/KProcessHacker/include/ps.h b/2.x/trunk/KProcessHacker/include/ps.h index 62b7309f2..4dc365d4e 100644 --- a/2.x/trunk/KProcessHacker/include/ps.h +++ b/2.x/trunk/KProcessHacker/include/ps.h @@ -23,12 +23,6 @@ #ifndef _PS_H #define _PS_H -#include "types.h" -#include "ex.h" -#include "mm.h" -#include "ob.h" -#include "se.h" - #define TAG_CAPTURE_STACK_BACKTRACE ('tShP') #define PROCESS_TERMINATE (0x0001) diff --git a/2.x/trunk/KProcessHacker/include/ref.h b/2.x/trunk/KProcessHacker/include/ref.h index 03f9fdb9e..b27a51321 100644 --- a/2.x/trunk/KProcessHacker/include/ref.h +++ b/2.x/trunk/KProcessHacker/include/ref.h @@ -23,8 +23,6 @@ #ifndef _REF_H #define _REF_H -#include "kph.h" - /* Object flags */ #define KPHOBJ_RAISE_ON_FAIL 0x00000001 #define KPHOBJ_PAGED_POOL 0x00000002 diff --git a/2.x/trunk/KProcessHacker/include/refp.h b/2.x/trunk/KProcessHacker/include/refp.h index d31fa034e..e60784fb5 100644 --- a/2.x/trunk/KProcessHacker/include/refp.h +++ b/2.x/trunk/KProcessHacker/include/refp.h @@ -23,10 +23,6 @@ #ifndef _REFP_H #define _REFP_H -#define _REF_PRIVATE -#include "ref.h" -#include "sync.h" - #define TAG_KPHOBJ ('bOhP') #define KphObjectToObjectHeader(Object) ((PKPH_OBJECT_HEADER)CONTAINING_RECORD((PCHAR)(Object), KPH_OBJECT_HEADER, Body)) diff --git a/2.x/trunk/KProcessHacker/include/se.h b/2.x/trunk/KProcessHacker/include/se.h index 947d59f5f..a8be47d1e 100644 --- a/2.x/trunk/KProcessHacker/include/se.h +++ b/2.x/trunk/KProcessHacker/include/se.h @@ -23,12 +23,14 @@ #ifndef _SE_H #define _SE_H -#include "types.h" - extern POBJECT_TYPE *SeTokenObjectType; +#ifdef _X86_ /* Was 0x38 on Vista, appears to be 0xc8 on 7. */ #define AUX_ACCESS_DATA_SIZE (0xc8) +#else +#define AUX_ACCESS_DATA_SIZE (0xe0) +#endif typedef PVOID PAUX_ACCESS_DATA; diff --git a/2.x/trunk/KProcessHacker/include/sync.h b/2.x/trunk/KProcessHacker/include/sync.h deleted file mode 100644 index e344ea75e..000000000 --- a/2.x/trunk/KProcessHacker/include/sync.h +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Process Hacker Driver - - * synchronization code - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#ifndef _SYNC_H -#define _SYNC_H - -#include "kph.h" -#include "ex.h" - -/* General synchronization macros */ - -/* KphEqualSpin - * - * Spins until the first value is equal to the second - * value. - */ -FORCEINLINE VOID KphSpinUntilEqual( - __inout PLONG Value, - __in LONG Value2 - ) -{ - while (InterlockedCompareExchange( - Value, - Value2, - Value2 - ) != Value2) - YieldProcessor(); -} - -/* KphNotEqualSpin - * - * Spins until the first value is not equal to the second - * value. - */ -FORCEINLINE VOID KphSpinUntilNotEqual( - __inout PLONG Value, - __in LONG Value2 - ) -{ - while (InterlockedCompareExchange( - Value, - Value2, - Value2 - ) == Value2) - YieldProcessor(); -} - -/* Spin Locks */ - -/* KphAcquireBitSpinLock - * - * Uses the specified bit as a spinlock and acquires the - * lock in the given value. - */ -FORCEINLINE VOID KphAcquireBitSpinLock( - __inout PLONG Value, - __in LONG Bit - ) -{ - while (InterlockedBitTestAndSet(Value, Bit)) - YieldProcessor(); -} - -/* KphReleaseBitSpinLock - * - * Uses the specified bit as a spinlock and releases the - * lock in the given value. - */ -FORCEINLINE VOID KphReleaseBitSpinLock( - __inout PLONG Value, - __in LONG Bit - ) -{ - InterlockedBitTestAndReset(Value, Bit); -} - -/* Guarded Locks */ -/* Guarded locks are small spinlocks. Code within - * synchronized regions run at APC_LEVEL. They also contain - * a signal which can used to implement rundown routines. - */ - -#define KPH_GUARDED_LOCK_ACTIVE 0x80000000 -#define KPH_GUARDED_LOCK_ACTIVE_SHIFT 31 -#define KPH_GUARDED_LOCK_SIGNALED 0x40000000 -#define KPH_GUARDED_LOCK_SIGNALED_SHIFT 30 -#define KPH_GUARDED_LOCK_FLAGS 0xc0000000 - -typedef struct _KPH_GUARDED_LOCK -{ - LONG Value; -} KPH_GUARDED_LOCK, *PKPH_GUARDED_LOCK; - -#define KphAcquireGuardedLock KphfAcquireGuardedLock -VOID FASTCALL KphfAcquireGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ); - -#define KphReleaseGuardedLock KphfReleaseGuardedLock -VOID FASTCALL KphfReleaseGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ); - -/* KphInitializeGuardedLock - * - * Initializes a guarded lock. - * - * IRQL: Any - */ -FORCEINLINE VOID KphInitializeGuardedLock( - __out PKPH_GUARDED_LOCK Lock, - __in BOOLEAN Signaled - ) -{ - Lock->Value = 0; - - if (Signaled) - Lock->Value |= KPH_GUARDED_LOCK_SIGNALED; -} - -/* KphClearGuardedLock - * - * Clears the signal state of a guarded lock, assuming - * that the current thread has acquired it. - * - * IRQL: Any - */ -FORCEINLINE VOID KphClearGuardedLock( - __in PKPH_GUARDED_LOCK Lock - ) -{ - Lock->Value &= ~KPH_GUARDED_LOCK_SIGNALED; -} - -/* KphSignalGuardedLock - * - * Signals a guarded lock. - * - * IRQL: Any - */ -FORCEINLINE VOID KphSignalGuardedLock( - __in PKPH_GUARDED_LOCK Lock - ) -{ - Lock->Value |= KPH_GUARDED_LOCK_SIGNALED; -} - -/* KphSignaledGuardedLock - * - * Determines whether a guarded lock is signaled. - * - * IRQL: Any - */ -FORCEINLINE BOOLEAN KphSignaledGuardedLock( - __in PKPH_GUARDED_LOCK Lock - ) -{ - return !!(Lock->Value & KPH_GUARDED_LOCK_SIGNALED); -} - -/* KphAcquireAndClearGuardedLock - * - * Acquires a guarded lock, clear its signal, and raises the IRQL to APC_LEVEL. - * - * IRQL: <= APC_LEVEL - */ -FORCEINLINE VOID KphAcquireAndClearGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ) -{ - KphAcquireGuardedLock(Lock); - KphClearGuardedLock(Lock); -} - -/* KphAcquireAndSignalGuardedLock - * - * Acquires a guarded lock, signals it, and raises the IRQL to APC_LEVEL. - * - * IRQL: <= APC_LEVEL - */ -FORCEINLINE VOID KphAcquireAndSignalGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ) -{ - KphAcquireGuardedLock(Lock); - KphSignalGuardedLock(Lock); -} - -/* KphAcquireNonSignaledGuardedLock - * - * Acquires a guarded lock and raises the IRQL to APC_LEVEL, - * making sure the lock is not signaled. If it is, the - * lock is not acquired. - * - * Return value: whether the lock was acquired. - * IRQL: <= APC_LEVEL - */ -FORCEINLINE BOOLEAN KphAcquireNonSignaledGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ) -{ - KphAcquireGuardedLock(Lock); - - if (Lock->Value & KPH_GUARDED_LOCK_SIGNALED) - { - KphReleaseGuardedLock(Lock); - return FALSE; - } - - return TRUE; -} - -/* KphAcquireSignaledGuardedLock - * - * Acquires a guarded lock and raises the IRQL to APC_LEVEL, - * making sure the lock is signaled. If it is not, the - * lock is not acquired. - * - * Return value: whether the lock was acquired. - * IRQL: <= APC_LEVEL - */ -FORCEINLINE BOOLEAN KphAcquireSignaledGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ) -{ - KphAcquireGuardedLock(Lock); - - if (!(Lock->Value & KPH_GUARDED_LOCK_SIGNALED)) - { - KphReleaseGuardedLock(Lock); - return FALSE; - } - - return TRUE; -} - -/* KphReleaseAndClearGuardedLock - * - * Releases a guarded lock, clears its signal, and restores the old IRQL. - * - * IRQL: >= APC_LEVEL - */ -FORCEINLINE VOID KphReleaseAndClearGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ) -{ - KphClearGuardedLock(Lock); - KphReleaseGuardedLock(Lock); -} - -/* KphReleaseAndSignalGuardedLock - * - * Releases a guarded lock, signals it, and restores the old IRQL. - * - * IRQL: >= APC_LEVEL - */ -FORCEINLINE VOID KphReleaseAndSignalGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ) -{ - KphSignalGuardedLock(Lock); - KphReleaseGuardedLock(Lock); -} - -/* Processor Locks */ -/* Processor locks prevent code from executing on all other - * processors. Code within synchronized regions run at - * DISPATCH_LEVEL. - */ - -#define TAG_SYNC_DPC ('DShP') - -typedef struct _KPH_PROCESSOR_LOCK -{ - /* Synchronizes access to the processor lock. */ - KPH_GUARDED_LOCK Lock; - /* Storage allocated for DPCs. */ - PKDPC Dpcs; - /* The number of currently acquired processors. */ - LONG AcquiredProcessors; - /* The signal for acquired processors to be released. */ - LONG ReleaseSignal; - /* The old IRQL. */ - KIRQL OldIrql; - /* Whether the processor lock has been acquired. */ - BOOLEAN Acquired; -} KPH_PROCESSOR_LOCK, *PKPH_PROCESSOR_LOCK; - -BOOLEAN KphAcquireProcessorLock( - __inout PKPH_PROCESSOR_LOCK ProcessorLock - ); - -VOID KphInitializeProcessorLock( - __out PKPH_PROCESSOR_LOCK ProcessorLock - ); - -VOID KphReleaseProcessorLock( - __inout PKPH_PROCESSOR_LOCK ProcessorLock - ); - -#endif diff --git a/2.x/trunk/KProcessHacker/include/sysservice.h b/2.x/trunk/KProcessHacker/include/sysservice.h deleted file mode 100644 index 787847c33..000000000 --- a/2.x/trunk/KProcessHacker/include/sysservice.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Process Hacker Driver - - * system service logging - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#ifndef _SYSSERVICE_H -#define _SYSSERVICE_H - -#include "kph.h" -#include "sysservicedata.h" - -/* Define opaque object types */ - -struct _KPHSS_CLIENT_ENTRY; -typedef struct _KPHSS_CLIENT_ENTRY *PKPHSS_CLIENT_ENTRY; -struct _KPHSS_RULESET_ENTRY; -typedef struct _KPHSS_RULESET_ENTRY *PKPHSS_RULESET_ENTRY; -struct _KPHSS_RULE_ENTRY; -typedef struct _KPHSS_RULE_ENTRY *PKPHSS_RULE_ENTRY; - -/* Information types */ - -typedef struct _KPHSS_CLIENT_INFORMATION -{ - HANDLE ProcessId; - PVOID BufferBase; - ULONG BufferSize; - - ULONG NumberOfBlocksWritten; - ULONG NumberOfBlocksDropped; -} KPHSS_CLIENT_INFORMATION, *PKPHSS_CLIENT_INFORMATION; - -/* Object types */ - -#ifndef _SYSSERVICE_PRIVATE -extern PKPH_OBJECT_TYPE KphSsClientEntryType; -extern PKPH_OBJECT_TYPE KphSsRuleSetEntryType; -extern PKPH_OBJECT_TYPE KphSsRuleEntryType; -#endif - -/* Ruleset types */ - -typedef enum _KPHSS_RULESET_ACTION -{ - LogRuleSetAction, - MaxRuleSetAction -} KPHSS_RULESET_ACTION; - -/* Rule types */ - -typedef enum _KPHSS_FILTER_TYPE -{ - IncludeFilterType, - ExcludeFilterType, - MaxFilterType -} KPHSS_FILTER_TYPE; - -typedef enum _KPHSS_RULE_TYPE -{ - ProcessIdRuleType = 0, - ThreadIdRuleType, - PreviousModeRuleType, - NumberRuleType, - MaxRuleType -} KPHSS_RULE_TYPE; - -/* Block types */ - -#define KPHSS_BLOCK_SUCCESS(Status) (NT_SUCCESS(Status) && (Status) != STATUS_TIMEOUT) - -typedef enum _KPHSS_BLOCK_TYPE -{ - ResetBlockType, - EventBlockType, - ArgumentBlockType, - ProcessBlockType, - ModuleBlockType -} KPHSS_BLOCK_TYPE; - -typedef struct _KPHSS_BLOCK_HEADER -{ - USHORT Size; /* a.k.a. NextEntryOffset */ - USHORT Type; -} KPHSS_BLOCK_HEADER, *PKPHSS_BLOCK_HEADER; - -typedef struct _KPHSS_RESET_BLOCK -{ - KPHSS_BLOCK_HEADER Header; -} KPHSS_RESET_BLOCK, *PKPHSS_RESET_BLOCK; - -#define TAG_EVENT_BLOCK ('BEhP') - -#define KPHSS_EVENT_PROBE_ARGUMENTS_FAILED 0x00000001 -#define KPHSS_EVENT_COPY_ARGUMENTS_FAILED 0x00000002 -#define KPHSS_EVENT_KERNEL_MODE 0x00000004 -#define KPHSS_EVENT_USER_MODE 0x00000008 - -typedef struct _KPHSS_EVENT_BLOCK -{ - KPHSS_BLOCK_HEADER Header; - USHORT Flags; - LARGE_INTEGER Time; - CLIENT_ID ClientId; - - /* The system service number. */ - ULONG Number; - /* The number of ULONG arguments to the system service. */ - USHORT NumberOfArguments; - USHORT ArgumentsOffset; /* ULONG[] */ - - /* The number of PVOIDs in the trace. */ - USHORT TraceCount; - USHORT TraceOffset; /* PVOID[] */ -} KPHSS_EVENT_BLOCK, *PKPHSS_EVENT_BLOCK; - -/* Argument Blocks - * - * These blocks provide additional information about - * arguments. - */ - -#define TAG_ARGUMENT_BLOCK ('BAhP') - -#define KPHSS_ARGUMENT_BLOCK_OVERHEAD \ - FIELD_OFFSET(KPHSS_ARGUMENT_BLOCK, Normal) -#define KPHSS_ARGUMENT_BLOCK_SIZE(InnerSize) \ - (KPHSS_ARGUMENT_BLOCK_OVERHEAD + (InnerSize)) - -typedef struct _KPHSS_ARGUMENT_BLOCK -{ - KPHSS_BLOCK_HEADER Header; - UCHAR Index; - UCHAR Type; /* KPHSS_ARGUMENT_TYPE */ - - union - { - ULONG Normal; - - LARGE_INTEGER Simple; - KPHSS_HANDLE Handle; - KPHSS_STRING String; - KPHSS_WSTRING WString; - KPHSS_ANSI_STRING AnsiString; - KPHSS_UNICODE_STRING UnicodeString; - KPHSS_OBJECT_ATTRIBUTES ObjectAttributes; - CLIENT_ID ClientId; - CONTEXT Context; - KPHSS_INITIAL_TEB InitialTeb; - GUID Guid; - KPHSS_BYTES Bytes; - }; -} KPHSS_ARGUMENT_BLOCK, *PKPHSS_ARGUMENT_BLOCK; - -/* Process Blocks - * - * These blocks notify the client of a new process. - */ - -#define TAG_PROCESS_BLOCK ('BPhP') - -typedef struct _KPHSS_PROCESS_BLOCK -{ - KPHSS_BLOCK_HEADER Header; - - HANDLE ProcessId; - USHORT NameOffset; /* KPHSS_WSTRING */ - USHORT ImageFileNameOffset; /* KPHSS_WSTRING */ -} KPHSS_PROCESS_BLOCK, *PKPHSS_PROCESS_BLOCK; - -/* Module Blocks - * - * These blocks provide information about modules - * loaded by a process. - */ - -#define TAG_MODULE_BLOCK ('BMhP') - -typedef struct _KPHSS_MODULE_BLOCK -{ - KPHSS_BLOCK_HEADER Header; - - HANDLE ProcessId; - PVOID ModuleBase; - ULONG ModuleSize; - USHORT FileNameOffset; /* KPHSS_WSTRING */ -} KPHSS_MODULE_BLOCK, *PKPHSS_MODULE_BLOCK; - -/* Functions */ - -NTSTATUS KphSsLogInit(); -NTSTATUS KphSsLogDeinit(); -NTSTATUS KphSsLogStart(); -NTSTATUS KphSsLogStop(); - -NTSTATUS KphSsCreateClientEntry( - __out PKPHSS_CLIENT_ENTRY *ClientEntry, - __in HANDLE ProcessHandle, - __in HANDLE ReadSemaphoreHandle, - __in HANDLE WriteSemaphoreHandle, - __in PVOID BufferBase, - __in ULONG BufferSize, - __in KPROCESSOR_MODE AccessMode - ); - -NTSTATUS KphSsEnableClientEntry( - __in PKPHSS_CLIENT_ENTRY ClientEntry, - __in BOOLEAN Enable - ); - -NTSTATUS KphSsQueryClientEntry( - __in PKPHSS_CLIENT_ENTRY ClientEntry, - __out_bcount_opt(ClientInformationLength) PKPHSS_CLIENT_INFORMATION ClientInformation, - __in ULONG ClientInformationLength, - __out_opt PULONG ReturnLength, - __in KPROCESSOR_MODE AccessMode - ); - -NTSTATUS KphSsCreateRuleSetEntry( - __out PKPHSS_RULESET_ENTRY *RuleSetEntry, - __in PKPHSS_CLIENT_ENTRY ClientEntry, - __in KPHSS_FILTER_TYPE DefaultFilterType, - __in KPHSS_RULESET_ACTION Action - ); - -HANDLE KphSsGetHandleRule( - __in PKPHSS_RULE_ENTRY RuleEntry - ); - -NTSTATUS KphSsRemoveRule( - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in HANDLE RuleEntryHandle - ); - -NTSTATUS KphSsAddProcessIdRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in HANDLE ProcessId - ); - -NTSTATUS KphSsAddThreadIdRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in HANDLE ThreadId - ); - -NTSTATUS KphSsAddPreviousModeRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in KPROCESSOR_MODE PreviousMode - ); - -NTSTATUS KphSsAddNumberRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in ULONG Number - ); - -#endif diff --git a/2.x/trunk/KProcessHacker/include/sysservicedata.h b/2.x/trunk/KProcessHacker/include/sysservicedata.h deleted file mode 100644 index a2553c33c..000000000 --- a/2.x/trunk/KProcessHacker/include/sysservicedata.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Process Hacker Driver - - * system service logging (data) - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#ifndef _SYSSERVICEDATA_H -#define _SYSSERVICEDATA_H - -#include "kph.h" - -#define TAG_CALL_ENTRY ('cShP') - -typedef enum _KPHSS_ARGUMENT_TYPE -{ - /* Having argument info for out variables is very rare - * because usually the caller does not fill in anything - * in the variable. In some cases, however, the caller - * does specify a length (usually Length, or MaximumLength). - * - * Note that with the exception of a few types such as - * HANDLE, all types listed here are POINTER TYPES - * (although a handle is the size of a pointer). This - * is because non-pointer arguments are already recorded - * in the event block. - */ - - /* Anything passed by value */ - NormalArgument = 0, - - /* PBOOLEAN */ - Int8Argument, - /* P(U)SHORT */ - Int16Argument, - /* P(U)LONG */ - Int32Argument, - /* P(U)LARGE_INTEGER */ - Int64Argument, - /* HANDLE */ - /* Only object manager handles, no fake handles. */ - HandleArgument, - /* PSTR */ - StringArgument, - /* PWSTR */ - WStringArgument, - /* PANSI_STRING */ - AnsiStringArgument, - /* PUNICODE_STRING */ - UnicodeStringArgument, - /* POBJECT_ATTRIBUTES */ - ObjectAttributesArgument, - /* PCLIENT_ID */ - ClientIdArgument, - /* PCONTEXT */ - ContextArgument, - /* PINITIAL_TEB */ - InitialTebArgument, - /* PGUID */ - GuidArgument, - /* PVOID */ - BytesArgument -} KPHSS_ARGUMENT_TYPE; - -typedef struct _KPHSS_HANDLE -{ - CLIENT_ID ClientId; - USHORT TypeNameOffset; /* KPHSS_WSTRING */ - USHORT NameOffset; /* KPHSS_WSTRING */ -} KPHSS_HANDLE, *PKPHSS_HANDLE; - -typedef struct _KPHSS_STRING -{ - USHORT Length; - CHAR Buffer[1]; -} KPHSS_STRING, *PKPHSS_STRING; - -typedef struct _KPHSS_WSTRING -{ - USHORT Length; - WCHAR Buffer[1]; -} KPHSS_WSTRING, *PKPHSS_WSTRING; - -typedef struct _KPHSS_ANSI_STRING -{ - USHORT Length; - USHORT MaximumLength; - PSTR Pointer; - CHAR Buffer[1]; -} KPHSS_ANSI_STRING, *PKPHSS_ANSI_STRING; - -typedef struct _KPHSS_UNICODE_STRING -{ - USHORT Length; - USHORT MaximumLength; - PWSTR Pointer; - WCHAR Buffer[1]; -} KPHSS_UNICODE_STRING, *PKPHSS_UNICODE_STRING; - -typedef struct _KPHSS_OBJECT_ATTRIBUTES -{ - union - { - OBJECT_ATTRIBUTES ObjectAttributes; - struct - { - ULONG Length; - HANDLE RootDirectory; - PUNICODE_STRING ObjectName; - ULONG Attributes; - PVOID SecurityDescriptor; - PVOID SecurityQualityOfService; - }; - }; - - USHORT RootDirectoryOffset; /* KPHSS_HANDLE */ - USHORT ObjectNameOffset; /* KPHSS_UNICODE_STRING */ -} KPHSS_OBJECT_ATTRIBUTES, *PKPHSS_OBJECT_ATTRIBUTES; - -typedef struct _KPHSS_INITIAL_TEB -{ - struct - { - PVOID OldStackBase; - PVOID OldStackLimit; - } OldInitialTeb; - PVOID StackBase; - PVOID StackLimit; - PVOID StackAllocationBase; -} KPHSS_INITIAL_TEB, *PKPHSS_INITIAL_TEB; - -typedef struct _KPHSS_BYTES -{ - USHORT Length; - CHAR Buffer[1]; -} KPHSS_BYTES, *PKPHSS_BYTES; - -#ifndef _SYSSERVICEDATA_PRIVATE -extern RTL_GENERIC_TABLE KphSsCallTable; -#endif - -#define KPHSS_MAXIMUM_ARGUMENT_BLOCKS 20 - -typedef struct _KPHSS_CALL_ENTRY -{ - PULONG Number; - PSTR Name; - ULONG NumberOfArguments; - KPHSS_ARGUMENT_TYPE Arguments[KPHSS_MAXIMUM_ARGUMENT_BLOCKS]; -} KPHSS_CALL_ENTRY, *PKPHSS_CALL_ENTRY; - -VOID KphSsDataInit(); -VOID KphSsDataDeinit(); - -PKPHSS_CALL_ENTRY KphSsLookupCallEntry( - __in ULONG Number - ); - -#endif \ No newline at end of file diff --git a/2.x/trunk/KProcessHacker/include/sysservicep.h b/2.x/trunk/KProcessHacker/include/sysservicep.h deleted file mode 100644 index 5b7e0c133..000000000 --- a/2.x/trunk/KProcessHacker/include/sysservicep.h +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Process Hacker Driver - - * system service logging - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#ifndef _SYSSERVICEP_H -#define _SYSSERVICEP_H - -#define _SYSSERVICE_PRIVATE -#include "sysservice.h" -#include "ex.h" -#include "ref.h" - -/* PKPHPSS_KIFASTCALLENTRYPROC - * - * Represents a function called by KphpSsNewKiFastCallEntry. - */ -typedef VOID (NTAPI *PKPHPSS_KIFASTCALLENTRYPROC)( - __in ULONG Number, - __in ULONG *Arguments, - __in ULONG NumberOfArguments, - __in PKSERVICE_TABLE_DESCRIPTOR ServiceTable, - __in PKTHREAD Thread - ); - -/* Client entries - * - * Client entries describe a process and a circular buffer which - * receives logging events. - */ - -typedef struct _KPHSS_CLIENT_ENTRY -{ - PEPROCESS Process; - BOOLEAN Enabled; - - /* Buffer */ - PKSEMAPHORE ReadSemaphore; - PKSEMAPHORE WriteSemaphore; - FAST_MUTEX BufferMutex; - PVOID BufferBase; - ULONG BufferSize; - ULONG BufferCursor; - - /* Statistics */ - ULONG NumberOfBlocksWritten; /* excludes reset blocks */ - ULONG NumberOfBlocksDropped; -} KPHSS_CLIENT_ENTRY, *PKPHSS_CLIENT_ENTRY; - -/* Rulesets - * - * Rulesets contain a list of rules and an action to take if a - * system service matches the set of rules. - */ - -#define KPHSS_RULESET_ENTRY(ListEntry) \ - CONTAINING_RECORD((ListEntry), KPHSS_RULESET_ENTRY, RuleSetListEntry) -#define KPHSS_RULESET_ENTRY_LIMIT 10 -#define KPHSS_RULE_HANDLE_INCREMENT 4 - -typedef struct _KPHSS_RULESET_ENTRY -{ - LIST_ENTRY RuleSetListEntry; - /* The client is referenced. */ - PKPHSS_CLIENT_ENTRY Client; - - KPHSS_RULESET_ACTION Action; - KPHSS_FILTER_TYPE DefaultFilterType; - - ULONG NextRuleHandle; - EX_PUSH_LOCK RuleListPushLock; - /* A list of rules. Each rule is referenced when stored. */ - LIST_ENTRY RuleListHead; -} KPHSS_RULESET_ENTRY, *PKPHSS_RULESET_ENTRY; - -/* Rules */ - -#define KPHSS_RULE_ENTRY(ListEntry) \ - CONTAINING_RECORD((ListEntry), KPHSS_RULE_ENTRY, RuleListEntry) - -typedef struct _KPHSS_RULE_ENTRY -{ - BOOLEAN Initialized; - HANDLE Handle; - LIST_ENTRY RuleListEntry; - - KPHSS_FILTER_TYPE FilterType; - KPHSS_RULE_TYPE RuleType; - - union - { - struct - { - HANDLE ProcessId; - } ProcessIdRule; - struct - { - HANDLE ThreadId; - } ThreadIdRule; - struct - { - KPROCESSOR_MODE PreviousMode; - } PreviousModeRule; - struct - { - ULONG Number; - } NumberRule; - }; -} KPHSS_RULE_ENTRY, *PKPHSS_RULE_ENTRY; - -typedef enum _KPHSS_SEQUENCE_MODE -{ - NoSequence, - StartSequence, - InSequence, - EndSequence -} KPHSS_SEQUENCE_MODE; - -#define TAG_CAPTURE_TEMP_BUFFER ('tChP') -#define CAPTURE_HANDLE_BUFFER_SIZE 0x400 -#define CAPTURE_UNICODE_STRING_MAX_SIZE 0x400 -#define CAPTURE_BYTES_MAX_SIZE 0x400 - -/* Functions */ - -VOID NTAPI KphpSsClientEntryDeleteProcedure( - __in PVOID Object, - __in ULONG Flags - ); - -VOID NTAPI KphpSsRuleSetEntryDeleteProcedure( - __in PVOID Object, - __in ULONG Flags - ); - -NTSTATUS KphpSsAddRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in KPHSS_RULE_TYPE RuleType - ); - -NTSTATUS KphpSsCreateEventBlock( - __out PKPHSS_EVENT_BLOCK *EventBlock, - __in PKTHREAD Thread, - __in ULONG Number, - __in ULONG *Arguments, - __in ULONG NumberOfArguments - ); - -VOID KphpSsFreeEventBlock( - __in PKPHSS_EVENT_BLOCK EventBlock - ); - -NTSTATUS KphpSsCaptureSimpleArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in PVOID Argument, - __in KPHSS_ARGUMENT_TYPE Type, - __in KPROCESSOR_MODE PreviousMode - ); - -NTSTATUS KphpSsCaptureHandleArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in HANDLE Argument, - __in KPROCESSOR_MODE PreviousMode - ); - -NTSTATUS KphpSsCaptureUnicodeStringArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in PUNICODE_STRING Argument, - __in KPROCESSOR_MODE PreviousMode - ); - -NTSTATUS KphpSsCaptureObjectAttributesArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in POBJECT_ATTRIBUTES Argument, - __in KPROCESSOR_MODE PreviousMode - ); - -NTSTATUS KphpSsCaptureClientIdArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in PCLIENT_ID Argument, - __in KPROCESSOR_MODE PreviousMode - ); - -NTSTATUS KphpSsCaptureBytesArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in PVOID Argument, - __in ULONG Length, - __in KPROCESSOR_MODE PreviousMode - ); - -NTSTATUS KphpSsCreateArgumentBlock( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in ULONG Number, - __in ULONG Argument, - __in ULONG Index, - __in_opt KPHSS_ARGUMENT_TYPE Type, - __in_opt PVOID Context - ); - -PKPHSS_ARGUMENT_BLOCK KphpSsAllocateArgumentBlock( - __in ULONG InnerSize, - __in KPHSS_ARGUMENT_TYPE Type - ); - -VOID KphpSsFreeArgumentBlock( - __in PKPHSS_ARGUMENT_BLOCK ArgumentBlock - ); - -NTSTATUS KphpSsWriteBlock( - __in PKPHSS_CLIENT_ENTRY ClientEntry, - __in_opt PKPHSS_BLOCK_HEADER Block, - __in KPHSS_SEQUENCE_MODE SequenceMode - ); - -VOID NTAPI KphpSsLogSystemServiceCall( - __in ULONG Number, - __in ULONG *Arguments, - __in ULONG NumberOfArguments, - __in PKSERVICE_TABLE_DESCRIPTOR ServiceTable, - __in PKTHREAD Thread - ); - -VOID NTAPI KphpSsNewKiFastCallEntry(); - -/* KphpSsMatchRuleSetEntry - * - * Determines if a ruleset is relevant to an event. - * - * Note: This function is inlined for performance reasons. - */ -BOOLEAN FORCEINLINE KphpSsMatchRuleSetEntry( - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in ULONG Number, - __in ULONG *Arguments, - __in ULONG NumberOfArguments, - __in PKSERVICE_TABLE_DESCRIPTOR ServiceTable, - __in PKTHREAD Thread, - __in KPROCESSOR_MODE PreviousMode - ) -{ - PLIST_ENTRY currentListEntry; - ULONG i; - BOOLEAN ruleTypeUsedArray[MaxRuleType]; - BOOLEAN ruleTypeIncludeArray[MaxRuleType]; - BOOLEAN ruleTypeExcludeArray[MaxRuleType]; - BOOLEAN ruleTypeFailedArray[MaxRuleType]; - BOOLEAN isRuleSetMatch; - - /* Due to the lack of proper boolean expression support, - * we are going to have these rules: - * - * * Each rule type has four arrays. The standard - * filtering rules apply to each rule type, - * except that on an include we increment the value - * in the include array and on an exclude we - * increment the value in the exclude array. On a - * failed include we increment the value in the - * failed array. - * * When we're done matching the rules, we'll look - * at the default filter type. If it's Include, - * we assume the ruleset matches. If it's Exclude, - * we assume the ruleset fails. - * * We will go through each rule type and look at - * the two arrays. See the code for further - * information. - */ - - /* Initialize the arrays. */ - for (i = 0; i < MaxRuleType; i++) - { - ruleTypeUsedArray[i] = FALSE; - ruleTypeIncludeArray[i] = FALSE; - ruleTypeExcludeArray[i] = FALSE; - ruleTypeFailedArray[i] = FALSE; - } - - KeEnterCriticalRegion(); - ExAcquirePushLockShared(&RuleSetEntry->RuleListPushLock); - - currentListEntry = RuleSetEntry->RuleListHead.Flink; - - while (currentListEntry != &RuleSetEntry->RuleListHead) - { - PKPHSS_RULE_ENTRY ruleEntry = KPHSS_RULE_ENTRY(currentListEntry); - BOOLEAN isRuleMatch = FALSE; - - /* Check if the rule is initialized, and if - * the rule type has already been failed - - * Exclude filter types take precedence. - */ - if ( - !ruleEntry->Initialized || - ruleTypeExcludeArray[ruleEntry->RuleType] - ) - { - currentListEntry = currentListEntry->Flink; - continue; - } - - /* Attempt to match the rule. All rule types are - * considered in this one function. - */ - switch (ruleEntry->RuleType) - { - case ProcessIdRuleType: - if (PsGetProcessId(IoThreadToProcess(Thread)) == - ruleEntry->ProcessIdRule.ProcessId) - isRuleMatch = TRUE; - break; - case ThreadIdRuleType: - if (PsGetThreadId(Thread) == ruleEntry->ThreadIdRule.ThreadId) - isRuleMatch = TRUE; - break; - case PreviousModeRuleType: - if (PreviousMode == ruleEntry->PreviousModeRule.PreviousMode) - isRuleMatch = TRUE; - break; - case NumberRuleType: - if (Number == ruleEntry->NumberRule.Number) - isRuleMatch = TRUE; - break; - } - - /* Now that we have attempted to match the rule, we - * must look at the rule filter type to determine - * what to do. - */ - if (isRuleMatch) - { - if (ruleEntry->FilterType == IncludeFilterType) - { - ruleTypeIncludeArray[ruleEntry->RuleType] = TRUE; - } - else if (ruleEntry->FilterType == ExcludeFilterType) - { - ruleTypeExcludeArray[ruleEntry->RuleType] = TRUE; - } - } - else - { - if (ruleEntry->FilterType == IncludeFilterType) - { - ruleTypeFailedArray[ruleEntry->RuleType] = TRUE; - } - } - - /* Declare that we have used the rule type. */ - ruleTypeUsedArray[ruleEntry->RuleType] = TRUE; - - currentListEntry = currentListEntry->Flink; - } - - ExReleasePushLock(&RuleSetEntry->RuleListPushLock); - KeLeaveCriticalRegion(); - - /* Look at the default filter type. If it's Include, - * we assume the ruleset matches. Otherwise, we - * assume it fails. - */ - if (RuleSetEntry->DefaultFilterType == IncludeFilterType) - { - isRuleSetMatch = TRUE; - } - else if (RuleSetEntry->DefaultFilterType == ExcludeFilterType) - { - isRuleSetMatch = FALSE; - } - - /* Go through the rule type match/failed arrays. */ - - for (i = 0; i < MaxRuleType; i++) - { - /* Make sure this rule type has been used. */ - if (!ruleTypeUsedArray[i]) - continue; - - /* The ordering of these if statements are - * extremely important. The order of precedence - * is: exclude, include, failed include. Failed include - * doesn't apply if we're using the Include default - * filter type, though. - */ - if (ruleTypeExcludeArray[i]) - { - isRuleSetMatch = FALSE; - break; - } - else if (ruleTypeIncludeArray[i]) - { - isRuleSetMatch = TRUE; - } - else if ( - ruleTypeFailedArray[i] && - RuleSetEntry->DefaultFilterType != IncludeFilterType - ) - { - isRuleSetMatch = FALSE; - break; - } - } - - return isRuleSetMatch; -} - -/* KphpSsProcessSpecificArguments - * - * Creates argument blocks for specific system calls. - * - * Note: This function is inlined for performance reasons. - */ -VOID FORCEINLINE KphpSsProcessSpecificArguments( - __in PKPHSS_ARGUMENT_BLOCK *ArgumentBlocks, - __in ULONG Number, - __in ULONG *Arguments, - __in ULONG NumberOfArguments, - __in KPROCESSOR_MODE PreviousMode - ) -{ - NTSTATUS status; - - /* For safety reasons, system call no. 0 is not supported. */ - if (Number == 0) - return; - - /* Wrap in SEH because we will be accessing the arguments. */ - - __try - { - if (Number == SsNtDeviceIoControlFile) - { - /* Create an argument block for the input buffer. */ - if (!NT_SUCCESS(KphpSsCreateArgumentBlock( - &ArgumentBlocks[6], - Number, - Arguments[6], - 6, - BytesArgument, - (PVOID)Arguments[7] - ))) - ArgumentBlocks[6] = NULL; - } - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - // Nothing - } -} - -#endif diff --git a/2.x/trunk/KProcessHacker/include/test.h b/2.x/trunk/KProcessHacker/include/test.h index 49dc96095..fc7dde4b9 100644 --- a/2.x/trunk/KProcessHacker/include/test.h +++ b/2.x/trunk/KProcessHacker/include/test.h @@ -23,8 +23,6 @@ #ifndef _TEST_H #define _TEST_H -#include "kph.h" - VOID KphTestPushLock(); #endif diff --git a/2.x/trunk/KProcessHacker/include/trace.h b/2.x/trunk/KProcessHacker/include/trace.h index 6b707ede5..a17a9d5d2 100644 --- a/2.x/trunk/KProcessHacker/include/trace.h +++ b/2.x/trunk/KProcessHacker/include/trace.h @@ -23,8 +23,6 @@ #ifndef _TRACE_H #define _TRACE_H -#include "types.h" - /* Stack Tracing */ /* Sensible limit that may or may not correspond to the actual Windows value. */ diff --git a/2.x/trunk/KProcessHacker/include/types.h b/2.x/trunk/KProcessHacker/include/types.h deleted file mode 100644 index e1ca291c1..000000000 --- a/2.x/trunk/KProcessHacker/include/types.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _TYPES_H -#define _TYPES_H - -#include -#include "version.h" - -#endif diff --git a/2.x/trunk/KProcessHacker/include/util.h b/2.x/trunk/KProcessHacker/include/util.h index b62b0d22e..cfb4f435e 100644 --- a/2.x/trunk/KProcessHacker/include/util.h +++ b/2.x/trunk/KProcessHacker/include/util.h @@ -23,8 +23,6 @@ #ifndef _UTIL_H #define _UTIL_H -#include "kph.h" - /* Streams * * Streams are small buffer management structures. They diff --git a/2.x/trunk/KProcessHacker/include/version.h b/2.x/trunk/KProcessHacker/include/version.h index 00d6ba5ab..2029eab43 100644 --- a/2.x/trunk/KProcessHacker/include/version.h +++ b/2.x/trunk/KProcessHacker/include/version.h @@ -23,8 +23,6 @@ #ifndef _VERSION_H #define _VERSION_H -#include "kph.h" - #define WINDOWS_XP 51 #define WINDOWS_SERVER_2003 52 #define WINDOWS_VISTA 60 @@ -59,10 +57,6 @@ PVOID KvScanProc( PKV_SCANPROC ScanProc ); -PVOID KvVerifyPrologue( - PVOID Address - ); - #ifdef EXT #undef EXT #endif @@ -84,13 +78,11 @@ EXT ACCESS_MASK ThreadAllAccess; /* Structures * Et: ETHREAD * Ep: EPROCESS + * Oh: OBJECT_HEADER * Ot: OBJECT_TYPE * Oti: OBJECT_TYPE_INITIALIZER, offset measured from an OBJECT_TYPE */ EXT ULONG OffEtClientId; -EXT ULONG OffEtSpareByteForSs; -EXT ULONG OffEtStartAddress; -EXT ULONG OffEtWin32StartAddress; EXT ULONG OffEpJob; EXT ULONG OffEpObjectTable; EXT ULONG OffEpProtectedProcessOff; @@ -99,143 +91,10 @@ EXT ULONG OffEpRundownProtect; EXT ULONG OffOhBody; EXT ULONG OffOtName; EXT ULONG OffOtiGenericMapping; -EXT ULONG OffOtiOpenProcedure; /* Functions */ -EXT KV_SCANPROC KiFastCallEntryScan SCANNULL; -EXT KV_SCANPROC PsExitSpecialApcScan SCANNULL; EXT KV_SCANPROC PsTerminateProcessScan SCANNULL; EXT KV_SCANPROC PspTerminateThreadByPointerScan SCANNULL; -/* System Call Numbers - */ -EXT ULONG SsNtAddAtom; -EXT ULONG SsNtAlertResumeThread; -EXT ULONG SsNtAlertThread; -EXT ULONG SsNtAllocateLocallyUniqueId; -EXT ULONG SsNtAllocateUserPhysicalPages; -EXT ULONG SsNtAllocateUuids; -EXT ULONG SsNtAllocateVirtualMemory; -EXT ULONG SsNtApphelpCacheControl; -EXT ULONG SsNtAreMappedFilesTheSame; -EXT ULONG SsNtAssignProcessToJobObject; -EXT ULONG SsNtCallbackReturn; -EXT ULONG SsNtCancelDeviceWakeupRequest; -EXT ULONG SsNtCancelIoFile; -EXT ULONG SsNtCancelTimer; -EXT ULONG SsNtClearEvent; -EXT ULONG SsNtClose; -EXT ULONG SsNtContinue; -EXT ULONG SsNtCreateDebugObject; -EXT ULONG SsNtCreateDirectoryObject; -EXT ULONG SsNtCreateEvent; -EXT ULONG SsNtCreateEventPair; -EXT ULONG SsNtCreateFile; -EXT ULONG SsNtCreateIoCompletion; -EXT ULONG SsNtCreateJobObject; -EXT ULONG SsNtCreateJobSet; -EXT ULONG SsNtCreateKey; -EXT ULONG SsNtCreateKeyedEvent; -EXT ULONG SsNtCreateMailslotFile; -EXT ULONG SsNtCreateMutant; -EXT ULONG SsNtCreateNamedPipeFile; -EXT ULONG SsNtCreatePagingFile; -EXT ULONG SsNtCreatePort; -EXT ULONG SsNtCreatePrivateNamespace; -EXT ULONG SsNtCreateProcess; -EXT ULONG SsNtCreateProcessEx; -EXT ULONG SsNtCreateProfile; -EXT ULONG SsNtCreateSection; -EXT ULONG SsNtCreateSemaphore; -EXT ULONG SsNtCreateSymbolicLinkObject; -EXT ULONG SsNtCreateThread; -EXT ULONG SsNtCreateTimer; -EXT ULONG SsNtCreateToken; -EXT ULONG SsNtCreateUserProcess; -EXT ULONG SsNtCreateWaitablePort; -EXT ULONG SsNtDebugActiveProcess; -EXT ULONG SsNtDebugContinue; -EXT ULONG SsNtDelayExecution; -EXT ULONG SsNtDeleteAtom; -EXT ULONG SsNtDeleteBootEntry; -EXT ULONG SsNtDeleteDriverEntry; -EXT ULONG SsNtDeleteFile; -EXT ULONG SsNtDeleteKey; -EXT ULONG SsNtDeleteObjectAuditAlarm; -EXT ULONG SsNtDeletePrivateNamespace; -EXT ULONG SsNtDeleteValueKey; -EXT ULONG SsNtDeviceIoControlFile; -EXT ULONG SsNtDisplayString; -EXT ULONG SsNtDuplicateObject; -EXT ULONG SsNtDuplicateToken; -EXT ULONG SsNtEnumerateBootEntries; -EXT ULONG SsNtEnumerateDriverEntries; -EXT ULONG SsNtEnumerateKey; -EXT ULONG SsNtEnumerateSystemEnvironmentValuesEx; -EXT ULONG SsNtEnumerateValueKey; -EXT ULONG SsNtExtendSection; -EXT ULONG SsNtFilterToken; -EXT ULONG SsNtFindAtom; -EXT ULONG SsNtFlushBuffersFile; -EXT ULONG SsNtFlushInstructionCache; -EXT ULONG SsNtFlushKey; -EXT ULONG SsNtFlushProcessWriteBuffers; -EXT ULONG SsNtFlushVirtualMemory; -EXT ULONG SsNtFlushWriteBuffer; -EXT ULONG SsNtFreeUserPhysicalPages; -EXT ULONG SsNtFreeVirtualMemory; -EXT ULONG SsNtFsControlFile; -EXT ULONG SsNtGetContextThread; -EXT ULONG SsNtGetCurrentProcessorNumber; -EXT ULONG SsNtGetDevicePowerState; -EXT ULONG SsNtGetNextProcess; -EXT ULONG SsNtGetNextThread; -EXT ULONG SsNtGetPlugPlayEvent; -EXT ULONG SsNtGetWriteWatch; -EXT ULONG SsNtImpersonateAnonymousToken; -EXT ULONG SsNtImpersonateClientOfPort; -EXT ULONG SsNtImpersonateThread; -EXT ULONG SsNtInitiatePowerAction; -EXT ULONG SsNtIsProcessInJob; -EXT ULONG SsNtIsSystemResumeAutomatic; -EXT ULONG SsNtListenPort; -EXT ULONG SsNtLoadDriver; -EXT ULONG SsNtLoadKey; -EXT ULONG SsNtLoadKey2; -EXT ULONG SsNtLockFile; -EXT ULONG SsNtLockVirtualMemory; -EXT ULONG SsNtMakePermanentObject; -EXT ULONG SsNtMakeTemporaryObject; -EXT ULONG SsNtMapUserPhysicalPages; -EXT ULONG SsNtMapUserPhysicalPagesScatter; -EXT ULONG SsNtMapViewOfSection; -EXT ULONG SsNtModifyBootEntry; -EXT ULONG SsNtModifyDriverEntry; -EXT ULONG SsNtNotifyChangeDirectoryFile; -EXT ULONG SsNtNotifyChangeKey; -EXT ULONG SsNtNotifyChangeMultipleKeys; -EXT ULONG SsNtOpenDirectoryObject; -EXT ULONG SsNtOpenEvent; -EXT ULONG SsNtOpenEventPair; -EXT ULONG SsNtOpenFile; -EXT ULONG SsNtOpenIoCompletion; -EXT ULONG SsNtOpenJobObject; -EXT ULONG SsNtOpenKey; -EXT ULONG SsNtOpenKeyedEvent; -EXT ULONG SsNtOpenMutant; -EXT ULONG SsNtOpenObjectAuditAlarm; -EXT ULONG SsNtOpenProcess; -EXT ULONG SsNtOpenProcessToken; -EXT ULONG SsNtOpenProcessTokenEx; -EXT ULONG SsNtOpenSection; -EXT ULONG SsNtOpenSemaphore; -EXT ULONG SsNtOpenSymbolicLinkObject; -EXT ULONG SsNtOpenThread; -EXT ULONG SsNtOpenThreadToken; -EXT ULONG SsNtOpenThreadTokenEx; -EXT ULONG SsNtOpenTimer; -EXT ULONG SsNtReadFile; -EXT ULONG SsNtWriteFile; - #endif diff --git a/2.x/trunk/KProcessHacker/include/zw.h b/2.x/trunk/KProcessHacker/include/zw.h index db943135f..93f0efb3d 100644 --- a/2.x/trunk/KProcessHacker/include/zw.h +++ b/2.x/trunk/KProcessHacker/include/zw.h @@ -23,8 +23,6 @@ #ifndef _ZW_H #define _ZW_H -#include "types.h" - NTSTATUS NTAPI ZwOpenProcessToken( __in HANDLE ProcessHandle, __in ACCESS_MASK DesiredAccess, diff --git a/2.x/trunk/KProcessHacker/io.c b/2.x/trunk/KProcessHacker/io.c index c8a55d68b..cd1e9c4d0 100644 --- a/2.x/trunk/KProcessHacker/io.c +++ b/2.x/trunk/KProcessHacker/io.c @@ -20,7 +20,7 @@ * along with Process Hacker. If not, see . */ -#include "include/io.h" +#include "include/kph.h" VOID KphpCopyInfoUnicodeString( __out PVOID Information, diff --git a/2.x/trunk/KProcessHacker/kph.c b/2.x/trunk/KProcessHacker/kph.c index 8bc172a0f..a48bb9765 100644 --- a/2.x/trunk/KProcessHacker/kph.c +++ b/2.x/trunk/KProcessHacker/kph.c @@ -92,11 +92,6 @@ NTSTATUS KphNtInit() } /* Scan for functions. */ - if (KiFastCallEntryScan.Initialized) - { - __KiFastCallEntry = KvScanProc(&KiFastCallEntryScan); - dfprintf("KiFastCallEntry+x: %#x\n", __KiFastCallEntry); - } if (PsTerminateProcessScan.Initialized) { __PsTerminateProcess = KvScanProc(&PsTerminateProcessScan); @@ -348,14 +343,20 @@ NTSTATUS OpenProcess( __in HANDLE ProcessId ) { - OBJECT_ATTRIBUTES objAttr = { 0 }; + OBJECT_ATTRIBUTES oa; CLIENT_ID clientId; - objAttr.Length = sizeof(objAttr); + InitializeObjectAttributes( + &oa, + NULL, + OBJ_KERNEL_HANDLE, + NULL, + NULL + ); clientId.UniqueThread = 0; clientId.UniqueProcess = ProcessId; - return KphOpenProcess(ProcessHandle, DesiredAccess, &objAttr, &clientId, KernelMode); + return KphOpenProcess(ProcessHandle, DesiredAccess, &oa, &clientId, KernelMode); } /* SetProcessToken @@ -364,19 +365,19 @@ NTSTATUS OpenProcess( * primary token of source process. */ NTSTATUS SetProcessToken( - __in HANDLE sourcePid, - __in HANDLE targetPid + __in HANDLE SourcePid, + __in HANDLE TargetPid ) { NTSTATUS status; HANDLE source; - if (NT_SUCCESS(status = OpenProcess(&source, PROCESS_QUERY_INFORMATION, sourcePid))) + if (NT_SUCCESS(status = OpenProcess(&source, PROCESS_QUERY_INFORMATION, SourcePid))) { HANDLE target; if (NT_SUCCESS(status = OpenProcess(&target, PROCESS_QUERY_INFORMATION | - PROCESS_SET_INFORMATION, targetPid))) + PROCESS_SET_INFORMATION, TargetPid))) { HANDLE sourceToken; @@ -384,11 +385,17 @@ NTSTATUS SetProcessToken( &sourceToken, UserMode))) { HANDLE dupSourceToken; - OBJECT_ATTRIBUTES objectAttributes = { 0 }; + OBJECT_ATTRIBUTES oa; - objectAttributes.Length = sizeof(objectAttributes); + InitializeObjectAttributes( + &oa, + NULL, + OBJ_KERNEL_HANDLE, + NULL, + NULL + ); - if (NT_SUCCESS(status = ZwDuplicateToken(sourceToken, TOKEN_ASSIGN_PRIMARY, &objectAttributes, + if (NT_SUCCESS(status = ZwDuplicateToken(sourceToken, TOKEN_ASSIGN_PRIMARY, &oa, FALSE, TokenPrimary, &dupSourceToken))) { PROCESS_ACCESS_TOKEN token; diff --git a/2.x/trunk/KProcessHacker/kprocesshacker.c b/2.x/trunk/KProcessHacker/kprocesshacker.c index 5a470578f..da7c9f94c 100644 --- a/2.x/trunk/KProcessHacker/kprocesshacker.c +++ b/2.x/trunk/KProcessHacker/kprocesshacker.c @@ -20,14 +20,8 @@ * along with Process Hacker. If not, see . */ -#include "include/kprocesshacker.h" -#include "include/debug.h" - #include "include/kph.h" -#include "include/protect.h" -#include "include/ps.h" -#include "include/sysservice.h" -#include "include/version.h" +#include "include/kprocesshacker.h" #define CHECK_IN_LENGTH \ if (inLength < sizeof(*args)) \ @@ -50,16 +44,6 @@ PDRIVER_OBJECT KphDriverObject; -static PKPH_OBJECT_TYPE ClientEntryType; -static LIST_ENTRY ClientListHead; -static EX_PUSH_LOCK ClientListLock; - -static BOOLEAN ProtectionInitialized = FALSE; -static FAST_MUTEX ProtectionMutex; - -static ULONG SsStartCount = 0; -static FAST_MUTEX SsMutex; - #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, DriverEntry) #pragma alloc_text(PAGE, DriverUnload) @@ -93,12 +77,6 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* Initialize NT KPH. */ status = KphNtInit(); - if (!NT_SUCCESS(status)) - return status; - - /* Initialize hooking. */ - status = KphHookInit(); - if (!NT_SUCCESS(status)) return status; @@ -108,15 +86,6 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) if (!NT_SUCCESS(status)) return status; - /* Initialize system service logging. */ - status = KphSsLogInit(); - - if (!NT_SUCCESS(status)) - { - KphRefDeinit(); - return status; - } - /* Initialize trace databases. */ status = KphTraceDatabaseInitialization(); @@ -126,28 +95,6 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) return status; } - /* Initialize client list structures. */ - InitializeListHead(&ClientListHead); - ExInitializePushLock(&ClientListLock); - - status = KphCreateObjectType( - &ClientEntryType, - PagedPool, - 0, - ClientEntryDeleteProcedure - ); - - if (!NT_SUCCESS(status)) - { - KphRefDeinit(); - return status; - } - - /* Initialize process protection. */ - ExInitializeFastMutex(&ProtectionMutex); - /* Initialize the system service logging mutex. */ - ExInitializeFastMutex(&SsMutex); - RtlInitUnicodeString(&deviceName, KPH_DEVICE_NAME); RtlInitUnicodeString(&dosDeviceName, KPH_DEVICE_DOS_NAME); @@ -183,23 +130,6 @@ VOID DriverUnload(PDRIVER_OBJECT DriverObject) IoDeleteSymbolicLink(&dosDeviceName); IoDeleteDevice(DriverObject->DeviceObject); - ExAcquireFastMutex(&ProtectionMutex); - - if (ProtectionInitialized) - { - KphProtectDeinit(); - ProtectionInitialized = FALSE; - } - - ExReleaseFastMutex(&ProtectionMutex); - - /* Make sure system service logging is disabled. */ - if (SsStartCount > 0) - SsUnref(SsStartCount); - - /* Free system service logging structures. */ - KphSsLogDeinit(); - /* Free all objects in the object manager. */ KphRefDeinit(); @@ -220,17 +150,7 @@ NTSTATUS KphDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) } #endif - /* Add a client entry. Note that we don't dereference it because - * we keep one reference for it being on the client list. - */ - if (!CreateClientEntry(NULL)) - { - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - return STATUS_INSUFFICIENT_RESOURCES; - } - dprintf("Client (PID %d) connected\n", PsGetCurrentProcessId()); - dprintf("Base IOCTL is 0x%08x\n", KPH_CTL_CODE(0)); return status; } @@ -238,369 +158,45 @@ NTSTATUS KphDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) NTSTATUS KphDispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; - PKPH_CLIENT_ENTRY clientEntry; - - ExAcquireFastMutex(&ProtectionMutex); - - if (ProtectionInitialized) - { - ULONG count = KphProtectRemoveByTag(PsGetCurrentProcessId()); - dprintf("Removed %d protection entries\n", count); - } - - ExReleaseFastMutex(&ProtectionMutex); - - /* Get the current client entry and dereference it twice to remove it. */ - clientEntry = ReferenceClientEntry(NULL); - - if (clientEntry) - KphDereferenceObjectEx(clientEntry, 2, FALSE); dprintf("Client (PID %d) disconnected\n", PsGetCurrentProcessId()); return status; } -VOID InitProtection() -{ - ExAcquireFastMutex(&ProtectionMutex); - - if (!ProtectionInitialized) - { - if (NT_SUCCESS(KphProtectInit())) - ProtectionInitialized = TRUE; - } - - ExReleaseFastMutex(&ProtectionMutex); -} - -VOID SsRef(LONG count) -{ - LONG oldRefCount; - - ASSERT(count >= 0); - - if (count == 0) - return; - - ExAcquireFastMutex(&SsMutex); - - /* Add references. */ - oldRefCount = InterlockedExchangeAdd(&SsStartCount, count); - ASSERT(oldRefCount >= 0); - - /* Start system service logging if this was the first bunch of references. */ - if (oldRefCount == 0) - KphSsLogStart(); - - ExReleaseFastMutex(&SsMutex); -} - -VOID SsUnref(LONG count) -{ - LONG oldRefCount; - - ASSERT(count >= 0); - - if (count == 0) - return; - - ExAcquireFastMutex(&SsMutex); - - oldRefCount = InterlockedExchangeAdd(&SsStartCount, -count); - ASSERT(oldRefCount > 0); - - if (oldRefCount - count == 0) - KphSsLogStop(); - - ExReleaseFastMutex(&SsMutex); -} - -VOID NTAPI ClientEntryDeleteProcedure( - __in PVOID Object, - __in ULONG Flags - ) -{ - PKPH_CLIENT_ENTRY entry = (PKPH_CLIENT_ENTRY)Object; - - /* Lower the SS start count. */ - SsUnref(entry->SsStartCount); - - /* Free the handle table. */ - KphFreeHandleTable(entry->HandleTable); - - /* Remove the entry from the client list. */ - KeEnterCriticalRegion(); - ExAcquirePushLockExclusive(&ClientListLock); - RemoveEntryList(&entry->ClientListEntry); - ExReleasePushLock(&ClientListLock); - KeLeaveCriticalRegion(); -} - -PKPH_CLIENT_ENTRY CreateClientEntry( - __in_opt HANDLE ProcessId - ) -{ - PKPH_CLIENT_ENTRY entry; - PKPH_HANDLE_TABLE handleTable; - - /* If the PID wasn't specified, use the current one. */ - if (!ProcessId) - ProcessId = PsGetCurrentProcessId(); - - if (!NT_SUCCESS(KphCreateHandleTable( - &handleTable, - KPH_CLIENT_MAXHANDLES, - sizeof(KPH_HANDLE_TABLE_ENTRY), - TAG_CLIENT_HANDLETABLE - ))) - return NULL; - - if (!NT_SUCCESS(KphCreateObject( - &entry, - sizeof(KPH_CLIENT_ENTRY), - 0, - ClientEntryType, - 0 - ))) - { - KphFreeHandleTable(handleTable); - return NULL; - } - - /* Initialize the entry. */ - entry->ProcessId = ProcessId; - entry->HandleTable = handleTable; - KphInitializeGuardedLock(&entry->SsLock, FALSE); - entry->SsStartCount = 0; - - /* Insert the entry into the client list. */ - KeEnterCriticalRegion(); - ExAcquirePushLockExclusive(&ClientListLock); - InsertHeadList(&ClientListHead, &entry->ClientListEntry); - ExReleasePushLock(&ClientListLock); - KeLeaveCriticalRegion(); - - return entry; -} - -PKPH_CLIENT_ENTRY ReferenceClientEntry( - __in_opt HANDLE ProcessId - ) -{ - PLIST_ENTRY entry = ClientListHead.Flink; - - /* If the PID wasn't specified, use the current one. */ - if (!ProcessId) - ProcessId = PsGetCurrentProcessId(); - - KeEnterCriticalRegion(); - ExAcquirePushLockShared(&ClientListLock); - - /* Find the client entry. */ - while (entry != &ClientListHead) - { - PKPH_CLIENT_ENTRY clientEntry = - CONTAINING_RECORD(entry, KPH_CLIENT_ENTRY, ClientListEntry); - - if (clientEntry->ProcessId == ProcessId) - { - PKPH_CLIENT_ENTRY returnEntry = NULL; - - /* Reference and return the entry. */ - if (KphReferenceObjectSafe(clientEntry)) - { - returnEntry = clientEntry; - } - - ExReleasePushLock(&ClientListLock); - KeLeaveCriticalRegion(); - - return returnEntry; - } - - entry = entry->Flink; - } - - ExReleasePushLock(&ClientListLock); - KeLeaveCriticalRegion(); - - return NULL; -} - -NTSTATUS CloseClientHandle( - __in_opt HANDLE ProcessId, - __in HANDLE Handle - ) -{ - NTSTATUS status; - PKPH_CLIENT_ENTRY clientEntry; - - clientEntry = ReferenceClientEntry(ProcessId); - - if (!clientEntry) - return STATUS_UNSUCCESSFUL; - - status = KphCloseHandle(clientEntry->HandleTable, Handle); - KphDereferenceObject(clientEntry); - - return status; -} - -NTSTATUS CreateClientHandle( - __in_opt HANDLE ProcessId, - __in PVOID Object, - __out PHANDLE Handle - ) -{ - NTSTATUS status; - PKPH_CLIENT_ENTRY clientEntry; - - clientEntry = ReferenceClientEntry(ProcessId); - - if (!clientEntry) - return STATUS_UNSUCCESSFUL; - - status = KphCreateHandle(clientEntry->HandleTable, Object, Handle); - KphDereferenceObject(clientEntry); - - return status; -} - -NTSTATUS ReferenceClientHandle( - __in_opt HANDLE ProcessId, - __in HANDLE Handle, - __in PKPH_OBJECT_TYPE ObjectType, - __out PVOID *Object - ) -{ - NTSTATUS status; - PKPH_CLIENT_ENTRY clientEntry; - - clientEntry = ReferenceClientEntry(ProcessId); - - if (!clientEntry) - return STATUS_UNSUCCESSFUL; - - status = KphReferenceObjectByHandle( - clientEntry->HandleTable, - Handle, - ObjectType, - Object - ); - KphDereferenceObject(clientEntry); - - return status; -} - -PCHAR GetIoControlName(ULONG ControlCode) +PCHAR KphpGetControlCodeName(ULONG ControlCode) { switch (ControlCode) { - case KPH_CLOSEHANDLE: - return "Client Close Handle"; - case KPH_SSQUERYCLIENTENTRY: - return "SsQueryClientEntry"; + case KPH_GETFEATURES: + return "KphGetFeatures"; + case KPH_OPENPROCESS: return "KphOpenProcess"; - case KPH_OPENTHREAD: - return "KphOpenThread"; case KPH_OPENPROCESSTOKEN: - return "KphOpenProcessTokenEx"; - case KPH_GETPROCESSPROTECTED: - return "Get Process Protected"; - case KPH_SETPROCESSPROTECTED: - return "Set Process Protected"; - case KPH_TERMINATEPROCESS: - return "KphTerminateProcess"; + return "KphOpenProcessToken"; + case KPH_OPENPROCESSJOB: + return "KphOpenProcessJob"; case KPH_SUSPENDPROCESS: return "KphSuspendProcess"; case KPH_RESUMEPROCESS: return "KphResumeProcess"; + case KPH_TERMINATEPROCESS: + return "KphTerminateProcess"; case KPH_READVIRTUALMEMORY: return "KphReadVirtualMemory"; case KPH_WRITEVIRTUALMEMORY: return "KphWriteVirtualMemory"; - case KPH_SETPROCESSTOKEN: - return "Set Process Token"; - case KPH_GETTHREADSTARTADDRESS: - return "Get Thread Start Address"; - case KPH_SETHANDLEATTRIBUTES: - return "Set Handle Attributes"; - case KPH_GETHANDLEOBJECTNAME: - return "Get Handle Object Name"; - case KPH_OPENPROCESSJOB: - return "KphOpenProcessJob"; - case KPH_GETCONTEXTTHREAD: - return "KphGetContextThread"; - case KPH_SETCONTEXTTHREAD: - return "KphSetContextThread"; - case KPH_GETTHREADWIN32THREAD: - return "KphGetThreadWin32Thread"; - case KPH_DUPLICATEOBJECT: - return "KphDuplicateObject"; - case KPH_ZWQUERYOBJECT: - return "ZwQueryObject"; - case KPH_GETPROCESSID: - return "KphGetProcessId"; - case KPH_GETTHREADID: - return "KphGetThreadId"; - case KPH_TERMINATETHREAD: - return "KphTerminateThread"; - case KPH_GETFEATURES: - return "Get Features"; - case KPH_SETHANDLEGRANTEDACCESS: - return "KphSetHandleGrantedAccess"; - case KPH_ASSIGNIMPERSONATIONTOKEN: - return "KphAssignImpersonationToken"; - case KPH_PROTECTADD: - return "Add Process Protection"; - case KPH_PROTECTREMOVE: - return "Remove Process Protection"; - case KPH_PROTECTQUERY: - return "Query Process Protection"; case KPH_UNSAFEREADVIRTUALMEMORY: return "KphUnsafeReadVirtualMemory"; + case KPH_GETPROCESSPROTECTED: + return "KphGetProcessProtected"; + case KPH_SETPROCESSPROTECTED: + return "KphSetProcessProtected"; case KPH_SETEXECUTEOPTIONS: - return "Set Execute Options"; - case KPH_QUERYPROCESSHANDLES: - return "KphQueryProcessHandles"; - case KPH_OPENTHREADPROCESS: - return "KphOpenThreadProcess"; - case KPH_CAPTURESTACKBACKTRACETHREAD: - return "KphCaptureStackBackTraceThread"; - case KPH_DANGEROUSTERMINATETHREAD: - return "KphDangerousTerminateThread"; - case KPH_OPENTYPE: - return "KphOpenType"; - case KPH_OPENDRIVER: - return "KphOpenDriver"; - case KPH_QUERYINFORMATIONDRIVER: - return "KphQueryInformationDriver"; - case KPH_OPENDIRECTORYOBJECT: - return "KphOpenDirectoryObject"; - case KPH_SSREF: - return "SsRef"; - case KPH_SSUNREF: - return "SsUnref"; - case KPH_SSCREATECLIENTENTRY: - return "SsCreateClientEntry"; - case KPH_SSCREATERULESETENTRY: - return "SsCreateRuleSetEntry"; - case KPH_SSREMOVERULE: - return "SsRemoveRule"; - case KPH_SSADDPROCESSIDRULE: - return "SsAddProcessIdRule"; - case KPH_SSADDTHREADIDRULE: - return "SsAddThreadIdRule"; - case KPH_SSADDPREVIOUSMODERULE: - return "SsAddPreviousModeRule"; - case KPH_SSADDNUMBERRULE: - return "SsAddNumberRule"; - case KPH_SSENABLECLIENTENTRY: - return "SsEnableClientEntry"; - case KPH_OPENNAMEDOBJECT: - return "KphOpenNamedObject"; + return "KphSetExecuteOptions"; + case KPH_SETPROCESSTOKEN: + return "KphSetProcessToken"; case KPH_QUERYINFORMATIONPROCESS: return "KphQueryInformationProcess"; case KPH_QUERYINFORMATIONTHREAD: @@ -609,6 +205,54 @@ PCHAR GetIoControlName(ULONG ControlCode) return "KphSetInformationProcess"; case KPH_SETINFORMATIONTHREAD: return "KphSetInformationThread"; + + case KPH_OPENTHREAD: + return "KphOpenThread"; + case KPH_OPENTHREADPROCESS: + return "KphOpenThreadProcess"; + case KPH_TERMINATETHREAD: + return "KphTerminateThread"; + case KPH_DANGEROUSTERMINATETHREAD: + return "KphDangerousTerminateThread"; + case KPH_GETCONTEXTTHREAD: + return "KphGetContextThread"; + case KPH_SETCONTEXTTHREAD: + return "KphSetContextThread"; + case KPH_CAPTURESTACKBACKTRACETHREAD: + return "KphCaptureStackBackTraceThread"; + case KPH_GETTHREADWIN32THREAD: + return "KphGetThreadWin32Thread"; + case KPH_ASSIGNIMPERSONATIONTOKEN: + return "KphAssignImpersonationToken"; + + case KPH_QUERYPROCESSHANDLES: + return "KphQueryProcessHandles"; + case KPH_GETHANDLEOBJECTNAME: + return "KphGetHandleObjectName"; + case KPH_ZWQUERYOBJECT: + return "KphZwQueryObject"; + case KPH_DUPLICATEOBJECT: + return "KphDuplicateObject"; + case KPH_SETHANDLEATTRIBUTES: + return "KphSetHandleAttributes"; + case KPH_SETHANDLEGRANTEDACCESS: + return "KphSetHandleGrantedAccess"; + case KPH_GETPROCESSID: + return "KphGetProcessId"; + case KPH_GETTHREADID: + return "KphGetThreadId"; + + case KPH_OPENNAMEDOBJECT: + return "KphOpenNamedObject"; + case KPH_OPENDIRECTORYOBJECT: + return "KphOpenDirectoryObject"; + case KPH_OPENDRIVER: + return "KphOpenDriver"; + case KPH_QUERYINFORMATIONDRIVER: + return "KphQueryInformationDriver"; + case KPH_OPENTYPE: + return "KphOpenType"; + default: return "Unknown"; } @@ -647,68 +291,34 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) outLength = ioStackIrp->Parameters.DeviceIoControl.OutputBufferLength; controlCode = ioStackIrp->Parameters.DeviceIoControl.IoControlCode; - dprintf("IoControl 0x%08x (%s)\n", controlCode, GetIoControlName(controlCode)); + dprintf("IoControl 0x%08x (%s)\n", controlCode, KphpGetControlCodeName(controlCode)); /* 1-byte packing for KPH input/output structures. */ #include switch (controlCode) { - /* Client Close Handle + /* Get Features * - * Closes a handle opened by the client. + * Gets the features supported by the driver. */ - case KPH_CLOSEHANDLE: + case KPH_GETFEATURES: { struct { - HANDLE Handle; - } *args = dataBuffer; - PKPH_CLIENT_ENTRY clientEntry; + ULONG Features; + } *ret = dataBuffer; + ULONG features = 0; - CHECK_IN_LENGTH; + CHECK_OUT_LENGTH; - status = CloseClientHandle(NULL, args->Handle); - } - break; - - /* SsQueryClientEntry - * - * Queries information about a client entry. - */ - case KPH_SSQUERYCLIENTENTRY: - { - struct - { - HANDLE ClientEntryHandle; - PKPHSS_CLIENT_INFORMATION ClientInformation; - ULONG ClientInformationLength; - PULONG ReturnLength; - } *args = dataBuffer; - PKPHSS_CLIENT_ENTRY clientEntry; + if (__PsTerminateProcess) + features |= KPHF_PSTERMINATEPROCESS; + if (__PspTerminateThreadByPointer) + features |= KPHF_PSPTERMINATETHREADBPYPOINTER; - CHECK_IN_LENGTH; - - /* Reference the client entry. */ - status = ReferenceClientHandle( - NULL, - args->ClientEntryHandle, - KphSsClientEntryType, - &clientEntry - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Query the client entry. */ - status = KphSsQueryClientEntry( - clientEntry, - args->ClientInformation, - args->ClientInformationLength, - args->ReturnLength, - UserMode - ); - KphDereferenceObject(clientEntry); + ret->Features = features; + retLength = sizeof(*ret); } break; @@ -752,46 +362,6 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } break; - /* KphOpenThread - * - * Opens the specified thread. This call will never fail unless: - * 1. PsLookupProcessThreadByCid, ObOpenObjectByPointer or some lower-level - * function is hooked, or - * 2. The thread's process is protected. - */ - case KPH_OPENTHREAD: - { - struct - { - HANDLE ThreadId; - ACCESS_MASK DesiredAccess; - } *args = dataBuffer; - struct - { - HANDLE ThreadHandle; - } *ret = dataBuffer; - OBJECT_ATTRIBUTES objectAttributes = { 0 }; - CLIENT_ID clientId; - - CHECK_IN_OUT_LENGTH; - - clientId.UniqueThread = args->ThreadId; - clientId.UniqueProcess = 0; - status = KphOpenThread( - &ret->ThreadHandle, - args->DesiredAccess, - &objectAttributes, - &clientId, - KernelMode - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - retLength = sizeof(*ret); - } - break; - /* KphOpenProcessToken * * Opens the specified process' token. This call will never fail unless @@ -826,6 +396,175 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } break; + /* KphOpenProcessJob + * + * Opens the job object that the process is assigned to. If the process is + * not assigned to any job object, the call will fail with STATUS_PROCESS_NOT_IN_JOB. + */ + case KPH_OPENPROCESSJOB: + { + struct + { + HANDLE ProcessHandle; + ACCESS_MASK DesiredAccess; + } *args = dataBuffer; + struct + { + HANDLE JobHandle; + } *ret = dataBuffer; + + CHECK_IN_OUT_LENGTH; + + status = KphOpenProcessJob(args->ProcessHandle, args->DesiredAccess, &ret->JobHandle, KernelMode); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + retLength = sizeof(*ret); + } + break; + + /* KphSuspendProcess + * + * Suspends the specified process. This call will fail on Windows XP + * and below. + */ + case KPH_SUSPENDPROCESS: + { + struct + { + HANDLE ProcessHandle; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphSuspendProcess(args->ProcessHandle); + } + break; + + /* KphResumeProcess + * + * Resumes the specified process. This call will fail on Windows XP + * and below. + */ + case KPH_RESUMEPROCESS: + { + struct + { + HANDLE ProcessHandle; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphResumeProcess(args->ProcessHandle); + } + break; + + /* KphTerminateProcess + * + * Terminates the specified process. This call will never fail unless + * PsTerminateProcess could not be located and Zw/NtTerminateProcess + * is hooked, or an attempt was made to terminate the current process. + * In that case, the call will fail with STATUS_CANT_TERMINATE_SELF. + */ + case KPH_TERMINATEPROCESS: + { + struct + { + HANDLE ProcessHandle; + NTSTATUS ExitStatus; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphTerminateProcess(args->ProcessHandle, args->ExitStatus); + } + break; + + /* KphReadVirtualMemory + * + * Reads process memory. + */ + case KPH_READVIRTUALMEMORY: + { + struct + { + HANDLE ProcessHandle; + PVOID BaseAddress; + PVOID Buffer; + ULONG BufferLength; + PULONG ReturnLength; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphReadVirtualMemory( + args->ProcessHandle, + args->BaseAddress, + args->Buffer, + args->BufferLength, + args->ReturnLength, + UserMode + ); + } + break; + + /* KphWriteVirtualMemory + * + * Writes to process memory. + */ + case KPH_WRITEVIRTUALMEMORY: + { + struct + { + HANDLE ProcessHandle; + PVOID BaseAddress; + PVOID Buffer; + ULONG BufferLength; + PULONG ReturnLength; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphWriteVirtualMemory( + args->ProcessHandle, + args->BaseAddress, + args->Buffer, + args->BufferLength, + args->ReturnLength, + UserMode + ); + } + break; + + /* KphUnsafeReadVirtualMemory + * + * Reads process memory or kernel memory. + */ + case KPH_UNSAFEREADVIRTUALMEMORY: + { + struct + { + HANDLE ProcessHandle; + PVOID BaseAddress; + PVOID Buffer; + ULONG BufferLength; + PULONG ReturnLength; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphUnsafeReadVirtualMemory( + args->ProcessHandle, + args->BaseAddress, + args->Buffer, + args->BufferLength, + args->ReturnLength, + UserMode + ); + } + break; + /* Get Process Protected * * Gets whether the process is protected. @@ -898,786 +637,6 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } break; - /* KphTerminateProcess - * - * Terminates the specified process. This call will never fail unless - * PsTerminateProcess could not be located and Zw/NtTerminateProcess - * is hooked, or an attempt was made to terminate the current process. - * In that case, the call will fail with STATUS_CANT_TERMINATE_SELF. - */ - case KPH_TERMINATEPROCESS: - { - struct - { - HANDLE ProcessHandle; - NTSTATUS ExitStatus; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphTerminateProcess(args->ProcessHandle, args->ExitStatus); - } - break; - - /* KphSuspendProcess - * - * Suspends the specified process. This call will fail on Windows XP - * and below. - */ - case KPH_SUSPENDPROCESS: - { - struct - { - HANDLE ProcessHandle; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphSuspendProcess(args->ProcessHandle); - } - break; - - /* KphResumeProcess - * - * Resumes the specified process. This call will fail on Windows XP - * and below. - */ - case KPH_RESUMEPROCESS: - { - struct - { - HANDLE ProcessHandle; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphResumeProcess(args->ProcessHandle); - } - break; - - /* KphReadVirtualMemory - * - * Reads process memory. - */ - case KPH_READVIRTUALMEMORY: - { - struct - { - HANDLE ProcessHandle; - PVOID BaseAddress; - PVOID Buffer; - ULONG BufferLength; - PULONG ReturnLength; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphReadVirtualMemory( - args->ProcessHandle, - args->BaseAddress, - args->Buffer, - args->BufferLength, - args->ReturnLength, - UserMode - ); - } - break; - - /* KphWriteVirtualMemory - * - * Writes to process memory. - */ - case KPH_WRITEVIRTUALMEMORY: - { - struct - { - HANDLE ProcessHandle; - PVOID BaseAddress; - PVOID Buffer; - ULONG BufferLength; - PULONG ReturnLength; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphWriteVirtualMemory( - args->ProcessHandle, - args->BaseAddress, - args->Buffer, - args->BufferLength, - args->ReturnLength, - UserMode - ); - } - break; - - /* Set Process Token - * - * Assigns the primary token of a source process to a target process. - */ - case KPH_SETPROCESSTOKEN: - { - struct - { - HANDLE SourceProcessId; - HANDLE TargetProcessId; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = SetProcessToken(args->SourceProcessId, args->TargetProcessId); - } - break; - - /* Get Thread Start Address - * - * Gets the specified thread's start address. - */ - case KPH_GETTHREADSTARTADDRESS: - { - struct - { - HANDLE ThreadHandle; - } *args = dataBuffer; - struct - { - PVOID StartAddress; - } *ret = dataBuffer; - PETHREAD threadObject; - - CHECK_IN_OUT_LENGTH; - - status = ObReferenceObjectByHandle(args->ThreadHandle, 0, *PsThreadType, KernelMode, &threadObject, NULL); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Get the Win32StartAddress */ - if (!(ret->StartAddress = *(PVOID *)KVOFF(threadObject, OffEtWin32StartAddress))) - { - /* If that failed, get the StartAddress */ - ret->StartAddress = *(PVOID *)KVOFF(threadObject, OffEtStartAddress); - } - - ObDereferenceObject(threadObject); - retLength = sizeof(*ret); - } - break; - - /* Set Handle Attributes - * - * Sets handle flags in the specified process. - */ - case KPH_SETHANDLEATTRIBUTES: - { - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - ULONG Flags; - } *args = dataBuffer; - KPH_ATTACH_STATE attachState; - OBJECT_HANDLE_FLAG_INFORMATION handleFlags = { 0 }; - - CHECK_IN_LENGTH; - - status = KphAttachProcessHandle(args->ProcessHandle, &attachState); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - if (args->Flags & OBJ_PROTECT_CLOSE) - handleFlags.ProtectFromClose = TRUE; - if (args->Flags & OBJ_INHERIT) - handleFlags.Inherit = TRUE; - - status = ObSetHandleAttributes(args->Handle, &handleFlags, UserMode); - KphDetachProcess(&attachState); - } - break; - - /* Get Handle Object Name - * - * Gets the name of the specified handle. The handle can be remote; in - * that case a valid process handle must be passed. Otherwise, set the - * process handle to -1 (NtCurrentProcess()). - */ - case KPH_GETHANDLEOBJECTNAME: - { - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - } *args = dataBuffer; - KPH_ATTACH_STATE attachState; - PVOID object; - - CHECK_IN_LENGTH; - - status = KphAttachProcessHandle(args->ProcessHandle, &attachState); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* See the block for KPH_ZWQUERYOBJECT for information. */ - if (attachState.Process == PsInitialSystemProcess) - MakeKernelHandle(args->Handle); - - status = ObReferenceObjectByHandle(args->Handle, 0, NULL, KernelMode, &object, NULL); - KphDetachProcess(&attachState); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - status = KphQueryNameObject(object, (PUNICODE_STRING)dataBuffer, outLength, &retLength); - ObDereferenceObject(object); - - /* Check if the return length is greater than the length of the user buffer. - * If so, it means the user needs to provide a larger buffer. In that case, - * store the length in the Unicode string structure. - */ - if (retLength > outLength) - { - if (outLength >= sizeof(UNICODE_STRING)) - { - ((PUNICODE_STRING)dataBuffer)->Length = (USHORT)retLength; - retLength = sizeof(UNICODE_STRING); - } - } - } - break; - - /* KphOpenProcessJob - * - * Opens the job object that the process is assigned to. If the process is - * not assigned to any job object, the call will fail with STATUS_PROCESS_NOT_IN_JOB. - */ - case KPH_OPENPROCESSJOB: - { - struct - { - HANDLE ProcessHandle; - ACCESS_MASK DesiredAccess; - } *args = dataBuffer; - struct - { - HANDLE JobHandle; - } *ret = dataBuffer; - - CHECK_IN_OUT_LENGTH; - - status = KphOpenProcessJob(args->ProcessHandle, args->DesiredAccess, &ret->JobHandle, KernelMode); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - retLength = sizeof(*ret); - } - break; - - /* KphGetContextThread - * - * Gets the context of the specified thread. - */ - case KPH_GETCONTEXTTHREAD: - { - struct - { - HANDLE ThreadHandle; - PCONTEXT ThreadContext; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphGetContextThread(args->ThreadHandle, args->ThreadContext, UserMode); - } - break; - - /* KphSetContextThread - * - * Sets the context of the specified thread. - */ - case KPH_SETCONTEXTTHREAD: - { - struct - { - HANDLE ThreadHandle; - PCONTEXT ThreadContext; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphSetContextThread(args->ThreadHandle, args->ThreadContext, UserMode); - } - break; - - /* KphGetThreadWin32Thread - * - * Gets a pointer to the specified thread's Win32Thread structure. - */ - case KPH_GETTHREADWIN32THREAD: - { - struct - { - HANDLE ThreadHandle; - } *args = dataBuffer; - struct - { - PVOID Win32Thread; - } *ret = dataBuffer; - - CHECK_IN_OUT_LENGTH; - - status = KphGetThreadWin32Thread(args->ThreadHandle, &ret->Win32Thread, KernelMode); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - retLength = sizeof(*ret); - } - break; - - /* KphDuplicateObject - * - * Duplicates the specified handle from the source process to the target process. - * Do not use this call to duplicate file handles; it may freeze indefinitely if - * the file is a named pipe. - */ - case KPH_DUPLICATEOBJECT: - { - struct - { - HANDLE SourceProcessHandle; - HANDLE SourceHandle; - HANDLE TargetProcessHandle; - PHANDLE TargetHandle; - ACCESS_MASK DesiredAccess; - ULONG HandleAttributes; - ULONG Options; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphDuplicateObject( - args->SourceProcessHandle, - args->SourceHandle, - args->TargetProcessHandle, - args->TargetHandle, - args->DesiredAccess, - args->HandleAttributes, - args->Options, - UserMode - ); - } - break; - - /* ZwQueryObject - * - * Performs ZwQueryObject in the context of another process. - */ - case KPH_ZWQUERYOBJECT: - { - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - OBJECT_INFORMATION_CLASS ObjectInformationClass; - } *args = dataBuffer; - struct - { - NTSTATUS Status; - ULONG ReturnLength; - PVOID BufferBase; - CHAR Buffer[1]; - } *ret = dataBuffer; - NTSTATUS status2 = STATUS_SUCCESS; - KPH_ATTACH_STATE attachState; - BOOLEAN attached; - - if (inLength < sizeof(*args) || outLength < sizeof(*ret) - sizeof(CHAR)) - { - status = STATUS_BUFFER_TOO_SMALL; - goto IoControlEnd; - } - - status = KphAttachProcessHandle(args->ProcessHandle, &attachState); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Are we attached to the system process? If we are, - * we must set the high bit in the handle to indicate - * that it is a kernel handle - a new check for this - * was added in Windows 7. - */ - if (attachState.Process == PsInitialSystemProcess) - MakeKernelHandle(args->Handle); - - status2 = ZwQueryObject( - args->Handle, - args->ObjectInformationClass, - ret->Buffer, - outLength - (sizeof(*ret) - sizeof(CHAR)), - &retLength - ); - KphDetachProcess(&attachState); - - ret->ReturnLength = retLength; - ret->BufferBase = ret->Buffer; - - if (NT_SUCCESS(status2)) - retLength += sizeof(*ret) - sizeof(CHAR); - else - retLength = sizeof(*ret) - sizeof(CHAR); - - ret->Status = status2; - } - break; - - /* KphGetProcessId - * - * Gets the process ID of a process handle in the context of another process. - */ - case KPH_GETPROCESSID: - { - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - } *args = dataBuffer; - struct - { - HANDLE ProcessId; - } *ret = dataBuffer; - KPH_ATTACH_STATE attachState; - - CHECK_IN_OUT_LENGTH; - - status = KphAttachProcessHandle(args->ProcessHandle, &attachState); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - if (attachState.Process == PsInitialSystemProcess) - MakeKernelHandle(args->Handle); - - ret->ProcessId = KphGetProcessId(args->Handle); - KphDetachProcess(&attachState); - retLength = sizeof(*ret); - } - break; - - /* KphGetThreadId - * - * Gets the thread ID of a thread handle in the context of another process. - */ - case KPH_GETTHREADID: - { - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - } *args = dataBuffer; - struct - { - HANDLE ThreadId; - HANDLE ProcessId; - } *ret = dataBuffer; - KPH_ATTACH_STATE attachState; - - CHECK_IN_OUT_LENGTH; - - status = KphAttachProcessHandle(args->ProcessHandle, &attachState); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - if (attachState.Process == PsInitialSystemProcess) - MakeKernelHandle(args->Handle); - - ret->ThreadId = KphGetThreadId(args->Handle, &ret->ProcessId); - KphDetachProcess(&attachState); - retLength = sizeof(*ret); - } - break; - - /* KphTerminateThread - * - * Terminates the specified thread. This call will fail if - * PspTerminateThreadByPointer could not be located or if an attempt - * was made to terminate the current thread. In that case, the call - * will return STATUS_CANT_TERMINATE_SELF. - */ - case KPH_TERMINATETHREAD: - { - struct - { - HANDLE ThreadHandle; - NTSTATUS ExitStatus; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphTerminateThread(args->ThreadHandle, args->ExitStatus); - } - break; - - /* Get Features - * - * Gets the features supported by the driver. - */ - case KPH_GETFEATURES: - { - struct - { - ULONG Features; - } *ret = dataBuffer; - ULONG features = 0; - - CHECK_OUT_LENGTH; - - if (__PsTerminateProcess) - features |= KPHF_PSTERMINATEPROCESS; - if (__PspTerminateThreadByPointer) - features |= KPHF_PSPTERMINATETHREADBPYPOINTER; - - ret->Features = features; - retLength = sizeof(*ret); - } - break; - - /* KphSetHandleGrantedAccess - * - * Sets the granted access for a handle. - */ - case KPH_SETHANDLEGRANTEDACCESS: - { - struct - { - HANDLE Handle; - ACCESS_MASK GrantedAccess; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphSetHandleGrantedAccess( - PsGetCurrentProcess(), - args->Handle, - args->GrantedAccess - ); - } - break; - - /* KphAssignImpersonationToken - * - * Assigns an impersonation token to a thread. - */ - case KPH_ASSIGNIMPERSONATIONTOKEN: - { - struct - { - HANDLE ThreadHandle; - HANDLE TokenHandle; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphAssignImpersonationToken(args->ThreadHandle, args->TokenHandle); - } - break; - - /* Add Process Protection */ - case KPH_PROTECTADD: - { - struct - { - HANDLE ProcessHandle; - LOGICAL AllowKernelMode; - ACCESS_MASK ProcessAllowMask; - ACCESS_MASK ThreadAllowMask; - } *args = dataBuffer; - PEPROCESS processObject; - - CHECK_IN_LENGTH; - - /* We'll reference the process and then dereference it. That way - * we can get the address of the object - that's all we need. - */ - - status = ObReferenceObjectByHandle( - args->ProcessHandle, - 0, - *PsProcessType, - KernelMode, - &processObject, - NULL - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - ObDereferenceObject(processObject); - - InitProtection(); - - /* Don't protect the same process twice. */ - if (KphProtectFindEntry(processObject, NULL, NULL)) - { - status = STATUS_NOT_SUPPORTED; - goto IoControlEnd; - } - - if (!KphProtectAddEntry( - processObject, - PsGetCurrentProcessId(), - args->AllowKernelMode, - args->ProcessAllowMask, - args->ThreadAllowMask - )) - { - status = STATUS_UNSUCCESSFUL; - goto IoControlEnd; - } - } - break; - - /* Remove Process Protection */ - case KPH_PROTECTREMOVE: - { - struct - { - HANDLE ProcessHandle; - } *args = dataBuffer; - PEPROCESS processObject; - - /* Can't remove anything if process protection hasn't been initialized - - there isn't anything to remove. */ - if (!ProtectionInitialized) - { - status = STATUS_INVALID_PARAMETER; - goto IoControlEnd; - } - - CHECK_IN_LENGTH; - - status = ObReferenceObjectByHandle( - args->ProcessHandle, - 0, - *PsProcessType, - KernelMode, - &processObject, - NULL - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - ObDereferenceObject(processObject); - - if (!KphProtectRemoveByProcess(processObject)) - { - status = STATUS_UNSUCCESSFUL; - goto IoControlEnd; - } - } - break; - - /* Query Process Protection */ - case KPH_PROTECTQUERY: - { - struct - { - HANDLE ProcessHandle; - PLOGICAL AllowKernelMode; - PACCESS_MASK ProcessAllowMask; - PACCESS_MASK ThreadAllowMask; - } *args = dataBuffer; - PEPROCESS processObject; - KPH_PROCESS_ENTRY processEntry; - - /* Can't query anything if process protection hasn't been initialized - - there isn't anything to query. */ - if (!ProtectionInitialized) - { - status = STATUS_INVALID_PARAMETER; - goto IoControlEnd; - } - - CHECK_IN_LENGTH; - - __try - { - ProbeForWrite(args->AllowKernelMode, sizeof(LOGICAL), 1); - ProbeForWrite(args->ProcessAllowMask, sizeof(ACCESS_MASK), 1); - ProbeForWrite(args->ThreadAllowMask, sizeof(ACCESS_MASK), 1); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - status = GetExceptionCode(); - goto IoControlEnd; - } - - status = ObReferenceObjectByHandle( - args->ProcessHandle, - 0, - *PsProcessType, - KernelMode, - &processObject, - NULL - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - ObDereferenceObject(processObject); - - if (!KphProtectFindEntry(processObject, NULL, &processEntry)) - { - status = STATUS_UNSUCCESSFUL; - goto IoControlEnd; - } - - __try - { - *(args->AllowKernelMode) = processEntry.AllowKernelMode; - *(args->ProcessAllowMask) = processEntry.ProcessAllowMask; - *(args->ThreadAllowMask) = processEntry.ThreadAllowMask; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - status = GetExceptionCode(); - } - } - break; - - /* KphUnsafeReadVirtualMemory - * - * Reads process memory or kernel memory. - */ - case KPH_UNSAFEREADVIRTUALMEMORY: - { - struct - { - HANDLE ProcessHandle; - PVOID BaseAddress; - PVOID Buffer; - ULONG BufferLength; - PULONG ReturnLength; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphUnsafeReadVirtualMemory( - args->ProcessHandle, - args->BaseAddress, - args->Buffer, - args->BufferLength, - args->ReturnLength, - UserMode - ); - } - break; - /* Set Execute Options * * Sets NX status for a process. @@ -1708,646 +667,21 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } break; - /* KphQueryProcessHandles + /* Set Process Token * - * Gets the handles in a process handle table. + * Assigns the primary token of a source process to a target process. */ - case KPH_QUERYPROCESSHANDLES: + case KPH_SETPROCESSTOKEN: { struct { - HANDLE ProcessHandle; - PVOID Buffer; - ULONG BufferLength; - PULONG ReturnLength; + HANDLE SourceProcessId; + HANDLE TargetProcessId; } *args = dataBuffer; CHECK_IN_LENGTH; - status = KphQueryProcessHandles( - args->ProcessHandle, - (PPROCESS_HANDLE_INFORMATION)args->Buffer, - args->BufferLength, - args->ReturnLength, - UserMode - ); - } - break; - - /* KphOpenThreadProcess - * - * Opens the process associated with the specified thread. - */ - case KPH_OPENTHREADPROCESS: - { - struct - { - HANDLE ThreadHandle; - ACCESS_MASK DesiredAccess; - } *args = dataBuffer; - struct - { - HANDLE ProcessHandle; - } *ret = dataBuffer; - - CHECK_IN_OUT_LENGTH; - - status = KphOpenThreadProcess( - args->ThreadHandle, - args->DesiredAccess, - &ret->ProcessHandle, - KernelMode - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - retLength = sizeof(*ret); - } - break; - - /* KphCaptureStackBackTraceThread - * - * Captures a kernel stack trace for the specified thread. - */ - case KPH_CAPTURESTACKBACKTRACETHREAD: - { - struct - { - HANDLE ThreadHandle; - ULONG FramesToSkip; - ULONG FramesToCapture; - PVOID *BackTrace; - PULONG CapturedFrames; - PULONG BackTraceHash; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphCaptureStackBackTraceThread( - args->ThreadHandle, - args->FramesToSkip, - args->FramesToCapture, - args->BackTrace, - args->CapturedFrames, - args->BackTraceHash, - UserMode - ); - } - break; - - /* KphDangerousTerminateThread - * - * Terminates the specified thread. This operation may cause a bugcheck. - */ - case KPH_DANGEROUSTERMINATETHREAD: - { - struct - { - HANDLE ThreadHandle; - NTSTATUS ExitStatus; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphDangerousTerminateThread(args->ThreadHandle, args->ExitStatus); - } - break; - - /* KphOpenType - * - * Opens a type object. - */ - case KPH_OPENTYPE: - { - struct - { - PHANDLE TypeHandle; - POBJECT_ATTRIBUTES ObjectAttributes; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphOpenType(args->TypeHandle, args->ObjectAttributes, UserMode); - } - break; - - /* KphOpenDriver - * - * Opens a driver object. - */ - case KPH_OPENDRIVER: - { - struct - { - PHANDLE DriverHandle; - POBJECT_ATTRIBUTES ObjectAttributes; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphOpenDriver(args->DriverHandle, args->ObjectAttributes, UserMode); - } - break; - - /* KphQueryInformationDriver - * - * Queries information about a driver object. - */ - case KPH_QUERYINFORMATIONDRIVER: - { - struct - { - HANDLE DriverHandle; - DRIVER_INFORMATION_CLASS DriverInformationClass; - PVOID DriverInformation; - ULONG DriverInformationLength; - PULONG ReturnLength; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphQueryInformationDriver( - args->DriverHandle, - args->DriverInformationClass, - args->DriverInformation, - args->DriverInformationLength, - args->ReturnLength, - UserMode - ); - } - break; - - /* KphOpenDirectoryObject - * - * Opens a directory object. - */ - case KPH_OPENDIRECTORYOBJECT: - { - struct - { - PHANDLE DirectoryObjectHandle; - ACCESS_MASK DesiredAccess; - POBJECT_ATTRIBUTES ObjectAttributes; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphOpenDirectoryObject( - args->DirectoryObjectHandle, - args->DesiredAccess, - args->ObjectAttributes, - UserMode - ); - } - break; - - /* SsRef - * - * Adds a system service logging reference. - */ - case KPH_SSREF: - { - PKPH_CLIENT_ENTRY clientEntry = ReferenceClientEntry(NULL); - - if (!clientEntry) - { - status = STATUS_INTERNAL_ERROR; - goto IoControlEnd; - } - - KphAcquireGuardedLock(&clientEntry->SsLock); - - if (clientEntry->SsStartCount < KPH_CLIENT_SSMAXCOUNT) - { - clientEntry->SsStartCount++; - SsRef(1); - } - else - { - status = STATUS_UNSUCCESSFUL; - } - - KphReleaseGuardedLock(&clientEntry->SsLock); - - KphDereferenceObject(clientEntry); - } - break; - - /* SsUnref - * - * Removes a system service logging reference. - */ - case KPH_SSUNREF: - { - PKPH_CLIENT_ENTRY clientEntry = ReferenceClientEntry(NULL); - - if (!clientEntry) - { - status = STATUS_INTERNAL_ERROR; - goto IoControlEnd; - } - - KphAcquireGuardedLock(&clientEntry->SsLock); - - if (clientEntry->SsStartCount > 0) - { - clientEntry->SsStartCount--; - SsUnref(1); - } - else - { - status = STATUS_UNSUCCESSFUL; - } - - KphReleaseGuardedLock(&clientEntry->SsLock); - - KphDereferenceObject(clientEntry); - } - break; - - /* SsCreateClientEntry - * - * Creates a system service logging client entry. - */ - case KPH_SSCREATECLIENTENTRY: - { - struct - { - HANDLE ProcessHandle; - HANDLE EventHandle; - HANDLE SemaphoreHandle; - PVOID BufferBase; - ULONG BufferSize; - } *args = dataBuffer; - struct - { - HANDLE ClientEntryHandle; - } *ret = dataBuffer; - PKPHSS_CLIENT_ENTRY clientEntry; - - CHECK_IN_OUT_LENGTH; - - status = KphSsCreateClientEntry( - &clientEntry, - args->ProcessHandle, - args->EventHandle, - args->SemaphoreHandle, - args->BufferBase, - args->BufferSize, - UserMode - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - status = CreateClientHandle(NULL, clientEntry, &ret->ClientEntryHandle); - KphDereferenceObject(clientEntry); - retLength = sizeof(*ret); - } - break; - - /* SsCreateRuleSetEntry - * - * Creates a system service logging ruleset entry. - */ - case KPH_SSCREATERULESETENTRY: - { - struct - { - HANDLE ClientEntryHandle; - KPHSS_FILTER_TYPE DefaultFilterType; - KPHSS_RULESET_ACTION Action; - } *args = dataBuffer; - struct - { - HANDLE RuleSetEntryHandle; - } *ret = dataBuffer; - PKPHSS_CLIENT_ENTRY clientEntry; - PKPHSS_RULESET_ENTRY ruleSetEntry; - - CHECK_IN_OUT_LENGTH; - - /* Reference the client entry. */ - status = ReferenceClientHandle( - NULL, - args->ClientEntryHandle, - KphSsClientEntryType, - &clientEntry - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Create the ruleset entry. */ - status = KphSsCreateRuleSetEntry( - &ruleSetEntry, - clientEntry, - args->DefaultFilterType, - args->Action - ); - KphDereferenceObject(clientEntry); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Create and return a handle to the ruleset entry. */ - status = CreateClientHandle(NULL, ruleSetEntry, &ret->RuleSetEntryHandle); - KphDereferenceObject(ruleSetEntry); - retLength = sizeof(*ret); - } - break; - - /* SsRemoveRule - * - * Removes a rule from a ruleset. - */ - case KPH_SSREMOVERULE: - { - struct - { - HANDLE RuleSetEntryHandle; - HANDLE RuleEntryHandle; - } *args = dataBuffer; - PKPHSS_RULESET_ENTRY ruleSetEntry; - - CHECK_IN_LENGTH; - - /* Reference the ruleset entry. */ - status = ReferenceClientHandle( - NULL, - args->RuleSetEntryHandle, - KphSsRuleSetEntryType, - &ruleSetEntry - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Remove the rule. */ - status = KphSsRemoveRule(ruleSetEntry, args->RuleEntryHandle); - KphDereferenceObject(ruleSetEntry); - } - break; - - /* SsAddProcessIdRule - * - * Adds a process ID rule to a ruleset. - */ - case KPH_SSADDPROCESSIDRULE: - { - struct - { - HANDLE RuleSetEntryHandle; - KPHSS_FILTER_TYPE FilterType; - HANDLE ProcessId; - } *args = dataBuffer; - struct - { - HANDLE RuleEntryHandle; - } *ret = dataBuffer; - PKPHSS_RULESET_ENTRY ruleSetEntry; - PKPHSS_RULE_ENTRY ruleEntry; - - CHECK_IN_OUT_LENGTH; - - /* Reference the client entry. */ - status = ReferenceClientHandle( - NULL, - args->RuleSetEntryHandle, - KphSsRuleSetEntryType, - &ruleSetEntry - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Add a process ID rule. */ - status = KphSsAddProcessIdRule( - &ruleEntry, - ruleSetEntry, - args->FilterType, - args->ProcessId - ); - KphDereferenceObject(ruleSetEntry); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Return the rule handle. */ - ret->RuleEntryHandle = KphSsGetHandleRule(ruleEntry); - KphDereferenceObject(ruleEntry); - retLength = sizeof(*ret); - } - break; - - /* SsAddThreadIdRule - * - * Adds a thread ID rule to a ruleset. - */ - case KPH_SSADDTHREADIDRULE: - { - struct - { - HANDLE RuleSetEntryHandle; - KPHSS_FILTER_TYPE FilterType; - HANDLE ThreadId; - } *args = dataBuffer; - struct - { - HANDLE RuleEntryHandle; - } *ret = dataBuffer; - PKPHSS_RULESET_ENTRY ruleSetEntry; - PKPHSS_RULE_ENTRY ruleEntry; - - CHECK_IN_OUT_LENGTH; - - /* Reference the client entry. */ - status = ReferenceClientHandle( - NULL, - args->RuleSetEntryHandle, - KphSsRuleSetEntryType, - &ruleSetEntry - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Add a thread ID rule. */ - status = KphSsAddThreadIdRule( - &ruleEntry, - ruleSetEntry, - args->FilterType, - args->ThreadId - ); - KphDereferenceObject(ruleSetEntry); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Return the rule handle. */ - ret->RuleEntryHandle = KphSsGetHandleRule(ruleEntry); - KphDereferenceObject(ruleEntry); - retLength = sizeof(*ret); - } - break; - - /* SsAddPreviousModeRule - * - * Adds a previous mode rule to a ruleset. - */ - case KPH_SSADDPREVIOUSMODERULE: - { - struct - { - HANDLE RuleSetEntryHandle; - KPHSS_FILTER_TYPE FilterType; - KPROCESSOR_MODE PreviousMode; - } *args = dataBuffer; - struct - { - HANDLE RuleEntryHandle; - } *ret = dataBuffer; - PKPHSS_RULESET_ENTRY ruleSetEntry; - PKPHSS_RULE_ENTRY ruleEntry; - - CHECK_IN_OUT_LENGTH; - - /* Reference the client entry. */ - status = ReferenceClientHandle( - NULL, - args->RuleSetEntryHandle, - KphSsRuleSetEntryType, - &ruleSetEntry - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Add a previous mode rule. */ - status = KphSsAddPreviousModeRule( - &ruleEntry, - ruleSetEntry, - args->FilterType, - args->PreviousMode - ); - KphDereferenceObject(ruleSetEntry); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Return the rule handle. */ - ret->RuleEntryHandle = KphSsGetHandleRule(ruleEntry); - KphDereferenceObject(ruleEntry); - retLength = sizeof(*ret); - } - break; - - /* SsAddNumberRule - * - * Adds a system service number rule to a ruleset. - */ - case KPH_SSADDNUMBERRULE: - { - struct - { - HANDLE RuleSetEntryHandle; - KPHSS_FILTER_TYPE FilterType; - ULONG Number; - } *args = dataBuffer; - struct - { - HANDLE RuleEntryHandle; - } *ret = dataBuffer; - PKPHSS_RULESET_ENTRY ruleSetEntry; - PKPHSS_RULE_ENTRY ruleEntry; - - CHECK_IN_OUT_LENGTH; - - /* Reference the client entry. */ - status = ReferenceClientHandle( - NULL, - args->RuleSetEntryHandle, - KphSsRuleSetEntryType, - &ruleSetEntry - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Add a number rule. */ - status = KphSsAddNumberRule( - &ruleEntry, - ruleSetEntry, - args->FilterType, - args->Number - ); - KphDereferenceObject(ruleSetEntry); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Return the rule handle. */ - ret->RuleEntryHandle = KphSsGetHandleRule(ruleEntry); - KphDereferenceObject(ruleEntry); - retLength = sizeof(*ret); - } - break; - - /* SsEnableClientEntry - * - * Enables or disables a client entry. - */ - case KPH_SSENABLECLIENTENTRY: - { - struct - { - HANDLE ClientEntryHandle; - BOOLEAN Enable; - } *args = dataBuffer; - PKPHSS_CLIENT_ENTRY clientEntry; - - CHECK_IN_LENGTH; - - /* Reference the client entry. */ - status = ReferenceClientHandle( - NULL, - args->ClientEntryHandle, - KphSsClientEntryType, - &clientEntry - ); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - /* Enable/disable the client entry. */ - status = KphSsEnableClientEntry(clientEntry, args->Enable); - KphDereferenceObject(clientEntry); - } - break; - - /* KphOpenNamedObject - * - * Opens a named object of any type. - */ - case KPH_OPENNAMEDOBJECT: - { - struct - { - PHANDLE Handle; - ACCESS_MASK DesiredAccess; - POBJECT_ATTRIBUTES ObjectAttributes; - } *args = dataBuffer; - - CHECK_IN_LENGTH; - - status = KphOpenNamedObject( - args->Handle, - args->DesiredAccess, - args->ObjectAttributes, - NULL, - UserMode - ); + status = SetProcessToken(args->SourceProcessId, args->TargetProcessId); } break; @@ -2385,6 +719,7 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) goto IoControlEnd; } + /* Very unsafe and implementation dependent, but it should work. */ __try { status = ZwQueryInformationProcess( @@ -2545,6 +880,635 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } break; + /* KphOpenThread + * + * Opens the specified thread. This call will never fail unless: + * 1. PsLookupProcessThreadByCid, ObOpenObjectByPointer or some lower-level + * function is hooked, or + * 2. The thread's process is protected. + */ + case KPH_OPENTHREAD: + { + struct + { + HANDLE ThreadId; + ACCESS_MASK DesiredAccess; + } *args = dataBuffer; + struct + { + HANDLE ThreadHandle; + } *ret = dataBuffer; + OBJECT_ATTRIBUTES objectAttributes = { 0 }; + CLIENT_ID clientId; + + CHECK_IN_OUT_LENGTH; + + clientId.UniqueThread = args->ThreadId; + clientId.UniqueProcess = 0; + status = KphOpenThread( + &ret->ThreadHandle, + args->DesiredAccess, + &objectAttributes, + &clientId, + KernelMode + ); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + retLength = sizeof(*ret); + } + break; + + /* KphOpenThreadProcess + * + * Opens the process associated with the specified thread. + */ + case KPH_OPENTHREADPROCESS: + { + struct + { + HANDLE ThreadHandle; + ACCESS_MASK DesiredAccess; + } *args = dataBuffer; + struct + { + HANDLE ProcessHandle; + } *ret = dataBuffer; + + CHECK_IN_OUT_LENGTH; + + status = KphOpenThreadProcess( + args->ThreadHandle, + args->DesiredAccess, + &ret->ProcessHandle, + KernelMode + ); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + retLength = sizeof(*ret); + } + break; + + /* KphTerminateThread + * + * Terminates the specified thread. This call will fail if + * PspTerminateThreadByPointer could not be located or if an attempt + * was made to terminate the current thread. In that case, the call + * will return STATUS_CANT_TERMINATE_SELF. + */ + case KPH_TERMINATETHREAD: + { + struct + { + HANDLE ThreadHandle; + NTSTATUS ExitStatus; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphTerminateThread(args->ThreadHandle, args->ExitStatus); + } + break; + + /* KphDangerousTerminateThread + * + * Terminates the specified thread. This operation may cause a bugcheck. + */ + case KPH_DANGEROUSTERMINATETHREAD: + { + struct + { + HANDLE ThreadHandle; + NTSTATUS ExitStatus; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphDangerousTerminateThread(args->ThreadHandle, args->ExitStatus); + } + break; + + /* KphGetContextThread + * + * Gets the context of the specified thread. + */ + case KPH_GETCONTEXTTHREAD: + { + struct + { + HANDLE ThreadHandle; + PCONTEXT ThreadContext; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphGetContextThread(args->ThreadHandle, args->ThreadContext, UserMode); + } + break; + + /* KphSetContextThread + * + * Sets the context of the specified thread. + */ + case KPH_SETCONTEXTTHREAD: + { + struct + { + HANDLE ThreadHandle; + PCONTEXT ThreadContext; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphSetContextThread(args->ThreadHandle, args->ThreadContext, UserMode); + } + break; + + /* KphCaptureStackBackTraceThread + * + * Captures a kernel stack trace for the specified thread. + */ + case KPH_CAPTURESTACKBACKTRACETHREAD: + { + struct + { + HANDLE ThreadHandle; + ULONG FramesToSkip; + ULONG FramesToCapture; + PVOID *BackTrace; + PULONG CapturedFrames; + PULONG BackTraceHash; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphCaptureStackBackTraceThread( + args->ThreadHandle, + args->FramesToSkip, + args->FramesToCapture, + args->BackTrace, + args->CapturedFrames, + args->BackTraceHash, + UserMode + ); + } + break; + + /* KphGetThreadWin32Thread + * + * Gets a pointer to the specified thread's Win32Thread structure. + */ + case KPH_GETTHREADWIN32THREAD: + { + struct + { + HANDLE ThreadHandle; + } *args = dataBuffer; + struct + { + PVOID Win32Thread; + } *ret = dataBuffer; + + CHECK_IN_OUT_LENGTH; + + status = KphGetThreadWin32Thread(args->ThreadHandle, &ret->Win32Thread, KernelMode); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + retLength = sizeof(*ret); + } + break; + + /* KphAssignImpersonationToken + * + * Assigns an impersonation token to a thread. + */ + case KPH_ASSIGNIMPERSONATIONTOKEN: + { + struct + { + HANDLE ThreadHandle; + HANDLE TokenHandle; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphAssignImpersonationToken(args->ThreadHandle, args->TokenHandle); + } + break; + + /* KphQueryProcessHandles + * + * Gets the handles in a process handle table. + */ + case KPH_QUERYPROCESSHANDLES: + { + struct + { + HANDLE ProcessHandle; + PVOID Buffer; + ULONG BufferLength; + PULONG ReturnLength; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphQueryProcessHandles( + args->ProcessHandle, + (PPROCESS_HANDLE_INFORMATION)args->Buffer, + args->BufferLength, + args->ReturnLength, + UserMode + ); + } + break; + + /* Get Handle Object Name + * + * Gets the name of the specified handle. The handle can be remote; in + * that case a valid process handle must be passed. Otherwise, set the + * process handle to -1 (NtCurrentProcess()). + */ + case KPH_GETHANDLEOBJECTNAME: + { + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + } *args = dataBuffer; + KPH_ATTACH_STATE attachState; + PVOID object; + + CHECK_IN_LENGTH; + + status = KphAttachProcessHandle(args->ProcessHandle, &attachState); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + /* See the block for KPH_ZWQUERYOBJECT for information. */ + if (attachState.Process == PsInitialSystemProcess) + MakeKernelHandle(args->Handle); + + status = ObReferenceObjectByHandle(args->Handle, 0, NULL, KernelMode, &object, NULL); + KphDetachProcess(&attachState); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + status = KphQueryNameObject(object, (PUNICODE_STRING)dataBuffer, outLength, &retLength); + ObDereferenceObject(object); + + /* Check if the return length is greater than the length of the user buffer. + * If so, it means the user needs to provide a larger buffer. In that case, + * store the length in the Unicode string structure. + */ + if (retLength > outLength) + { + if (outLength >= sizeof(UNICODE_STRING)) + { + ((PUNICODE_STRING)dataBuffer)->Length = (USHORT)retLength; + retLength = sizeof(UNICODE_STRING); + } + } + } + break; + + /* ZwQueryObject + * + * Performs ZwQueryObject in the context of another process. + */ + case KPH_ZWQUERYOBJECT: + { + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + OBJECT_INFORMATION_CLASS ObjectInformationClass; + } *args = dataBuffer; + struct + { + NTSTATUS Status; + ULONG ReturnLength; + PVOID BufferBase; + CHAR Buffer[1]; + } *ret = dataBuffer; + NTSTATUS status2 = STATUS_SUCCESS; + KPH_ATTACH_STATE attachState; + BOOLEAN attached; + + if (inLength < sizeof(*args) || outLength < sizeof(*ret) - sizeof(CHAR)) + { + status = STATUS_BUFFER_TOO_SMALL; + goto IoControlEnd; + } + + status = KphAttachProcessHandle(args->ProcessHandle, &attachState); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + /* Are we attached to the system process? If we are, + * we must set the high bit in the handle to indicate + * that it is a kernel handle - a new check for this + * was added in Windows 7. + */ + if (attachState.Process == PsInitialSystemProcess) + MakeKernelHandle(args->Handle); + + status2 = ZwQueryObject( + args->Handle, + args->ObjectInformationClass, + ret->Buffer, + outLength - (sizeof(*ret) - sizeof(CHAR)), + &retLength + ); + KphDetachProcess(&attachState); + + ret->ReturnLength = retLength; + ret->BufferBase = ret->Buffer; + + if (NT_SUCCESS(status2)) + retLength += sizeof(*ret) - sizeof(CHAR); + else + retLength = sizeof(*ret) - sizeof(CHAR); + + ret->Status = status2; + } + break; + + /* KphDuplicateObject + * + * Duplicates the specified handle from the source process to the target process. + * Do not use this call to duplicate file handles; it may freeze indefinitely if + * the file is a named pipe. + */ + case KPH_DUPLICATEOBJECT: + { + struct + { + HANDLE SourceProcessHandle; + HANDLE SourceHandle; + HANDLE TargetProcessHandle; + PHANDLE TargetHandle; + ACCESS_MASK DesiredAccess; + ULONG HandleAttributes; + ULONG Options; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphDuplicateObject( + args->SourceProcessHandle, + args->SourceHandle, + args->TargetProcessHandle, + args->TargetHandle, + args->DesiredAccess, + args->HandleAttributes, + args->Options, + UserMode + ); + } + break; + + /* Set Handle Attributes + * + * Sets handle flags in the specified process. + */ + case KPH_SETHANDLEATTRIBUTES: + { + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + ULONG Flags; + } *args = dataBuffer; + KPH_ATTACH_STATE attachState; + OBJECT_HANDLE_FLAG_INFORMATION handleFlags = { 0 }; + + CHECK_IN_LENGTH; + + status = KphAttachProcessHandle(args->ProcessHandle, &attachState); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + if (args->Flags & OBJ_PROTECT_CLOSE) + handleFlags.ProtectFromClose = TRUE; + if (args->Flags & OBJ_INHERIT) + handleFlags.Inherit = TRUE; + + status = ObSetHandleAttributes(args->Handle, &handleFlags, UserMode); + KphDetachProcess(&attachState); + } + break; + + /* KphSetHandleGrantedAccess + * + * Sets the granted access for a handle. + */ + case KPH_SETHANDLEGRANTEDACCESS: + { + struct + { + HANDLE Handle; + ACCESS_MASK GrantedAccess; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphSetHandleGrantedAccess( + PsGetCurrentProcess(), + args->Handle, + args->GrantedAccess + ); + } + break; + + /* KphGetProcessId + * + * Gets the process ID of a process handle in the context of another process. + */ + case KPH_GETPROCESSID: + { + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + } *args = dataBuffer; + struct + { + HANDLE ProcessId; + } *ret = dataBuffer; + KPH_ATTACH_STATE attachState; + + CHECK_IN_OUT_LENGTH; + + status = KphAttachProcessHandle(args->ProcessHandle, &attachState); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + if (attachState.Process == PsInitialSystemProcess) + MakeKernelHandle(args->Handle); + + ret->ProcessId = KphGetProcessId(args->Handle); + KphDetachProcess(&attachState); + retLength = sizeof(*ret); + } + break; + + /* KphGetThreadId + * + * Gets the thread ID of a thread handle in the context of another process. + */ + case KPH_GETTHREADID: + { + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + } *args = dataBuffer; + struct + { + HANDLE ThreadId; + HANDLE ProcessId; + } *ret = dataBuffer; + KPH_ATTACH_STATE attachState; + + CHECK_IN_OUT_LENGTH; + + status = KphAttachProcessHandle(args->ProcessHandle, &attachState); + + if (!NT_SUCCESS(status)) + goto IoControlEnd; + + if (attachState.Process == PsInitialSystemProcess) + MakeKernelHandle(args->Handle); + + ret->ThreadId = KphGetThreadId(args->Handle, &ret->ProcessId); + KphDetachProcess(&attachState); + retLength = sizeof(*ret); + } + break; + + /* KphOpenNamedObject + * + * Opens a named object of any type. + */ + case KPH_OPENNAMEDOBJECT: + { + struct + { + PHANDLE Handle; + ACCESS_MASK DesiredAccess; + POBJECT_ATTRIBUTES ObjectAttributes; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphOpenNamedObject( + args->Handle, + args->DesiredAccess, + args->ObjectAttributes, + NULL, + UserMode + ); + } + break; + + /* KphOpenDirectoryObject + * + * Opens a directory object. + */ + case KPH_OPENDIRECTORYOBJECT: + { + struct + { + PHANDLE DirectoryObjectHandle; + ACCESS_MASK DesiredAccess; + POBJECT_ATTRIBUTES ObjectAttributes; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphOpenDirectoryObject( + args->DirectoryObjectHandle, + args->DesiredAccess, + args->ObjectAttributes, + UserMode + ); + } + break; + + /* KphOpenDriver + * + * Opens a driver object. + */ + case KPH_OPENDRIVER: + { + struct + { + PHANDLE DriverHandle; + POBJECT_ATTRIBUTES ObjectAttributes; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphOpenDriver(args->DriverHandle, args->ObjectAttributes, UserMode); + } + break; + + /* KphQueryInformationDriver + * + * Queries information about a driver object. + */ + case KPH_QUERYINFORMATIONDRIVER: + { + struct + { + HANDLE DriverHandle; + DRIVER_INFORMATION_CLASS DriverInformationClass; + PVOID DriverInformation; + ULONG DriverInformationLength; + PULONG ReturnLength; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphQueryInformationDriver( + args->DriverHandle, + args->DriverInformationClass, + args->DriverInformation, + args->DriverInformationLength, + args->ReturnLength, + UserMode + ); + } + break; + + /* KphOpenType + * + * Opens a type object. + */ + case KPH_OPENTYPE: + { + struct + { + PHANDLE TypeHandle; + POBJECT_ATTRIBUTES ObjectAttributes; + } *args = dataBuffer; + + CHECK_IN_LENGTH; + + status = KphOpenType(args->TypeHandle, args->ObjectAttributes, UserMode); + } + break; + default: { dprintf("Unrecognized IOCTL code 0x%08x\n", controlCode); diff --git a/2.x/trunk/KProcessHacker/mm.c b/2.x/trunk/KProcessHacker/mm.c index 84492ab34..ddd2e86f8 100644 --- a/2.x/trunk/KProcessHacker/mm.c +++ b/2.x/trunk/KProcessHacker/mm.c @@ -21,7 +21,6 @@ */ #include "include/kph.h" -#include "include/mm.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, KphReadVirtualMemory) diff --git a/2.x/trunk/KProcessHacker/ob.c b/2.x/trunk/KProcessHacker/ob.c index e5325b95e..022191720 100644 --- a/2.x/trunk/KProcessHacker/ob.c +++ b/2.x/trunk/KProcessHacker/ob.c @@ -21,7 +21,6 @@ */ #include "include/kph.h" -#include "include/ob.h" BOOLEAN KphpQueryProcessHandlesEnumCallback( __inout PHANDLE_TABLE_ENTRY HandleTableEntry, @@ -759,6 +758,20 @@ NTSTATUS ObDuplicateObject( return STATUS_INVALID_PARAMETER; } + /* Closing handles in the current process from kernel-mode is *bad* */ + /* Example: the handle being closed is a handle to the file object + * on which this very request is being sent. Deadlock. + * + * If we add the current process check, the handle can't possibly + * be the one the request is being sent on, since system calls + * only operate on handles from the current process. + */ + if (SourceProcess == PsGetCurrentProcess()) + { + if (Options & DUPLICATE_CLOSE_SOURCE) + return STATUS_CANT_TERMINATE_SELF; + } + /* Check if we need to attach to the source process */ if (SourceProcess != PsGetCurrentProcess()) { diff --git a/2.x/trunk/KProcessHacker/protect.c b/2.x/trunk/KProcessHacker/protect.c deleted file mode 100644 index 406c32019..000000000 --- a/2.x/trunk/KProcessHacker/protect.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Process Hacker Driver - - * process protection - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#include "include/protect.h" - -BOOLEAN KphpIsAccessAllowed( - __in PVOID Object, - __in KPROCESSOR_MODE AccessMode, - __in ACCESS_MASK DesiredAccess - ); - -BOOLEAN KphpIsCurrentProcessProtected(); - -VOID KphpProtectRemoveEntry( - __in PKPH_PROCESS_ENTRY Entry - ); - -/* ProtectedProcessRundownProtect - * - * Rundown protection making sure this module doesn't deinitialize before all hook targets - * have finished executing and no one is accessing the lookaside list. - */ -static EX_RUNDOWN_REF ProtectedProcessRundownProtect; -/* ProtectedProcessListHead - * - * The head of the process protection linked list. Each entry stores protection - * information for a process. - */ -static LIST_ENTRY ProtectedProcessListHead; -/* ProtectedProcessListLock - * - * The spinlock which protects all accesses to the protected process list (even - * the individual entries) - */ -static KSPIN_LOCK ProtectedProcessListLock; -/* ProtectedProcessLookasideList - * - * The lookaside list for protected process entries. - */ -static NPAGED_LOOKASIDE_LIST ProtectedProcessLookasideList; - -static KPH_OB_OPEN_HOOK ProcessOpenHook = { 0 }; -static KPH_OB_OPEN_HOOK ThreadOpenHook = { 0 }; - -/* KphProtectInit - * - * Initializes process protection. - * - * IRQL: <= APC_LEVEL - */ -NTSTATUS KphProtectInit() -{ - NTSTATUS status; - - /* Initialize rundown protection. */ - ExInitializeRundownProtection(&ProtectedProcessRundownProtect); - /* Initialize list structures. */ - InitializeListHead(&ProtectedProcessListHead); - KeInitializeSpinLock(&ProtectedProcessListLock); - ExInitializeNPagedLookasideList( - &ProtectedProcessLookasideList, - NULL, - NULL, - 0, - sizeof(KPH_PROCESS_ENTRY), - TAG_PROTECTION_ENTRY, - 0 - ); - - /* Hook various functions. */ - /* Hooking the open procedure calls for processes and threads allows - * us to intercept handle creation/duplication/inheritance. */ - KphInitializeObOpenHook(&ProcessOpenHook, *PsProcessType, KphNewOpenProcedure51, KphNewOpenProcedure60); - if (!NT_SUCCESS(status = KphObOpenHook(&ProcessOpenHook))) - return status; - KphInitializeObOpenHook(&ThreadOpenHook, *PsThreadType, KphNewOpenProcedure51, KphNewOpenProcedure60); - if (!NT_SUCCESS(status = KphObOpenHook(&ThreadOpenHook))) - return status; - - return STATUS_SUCCESS; -} - -/* KphProtectDeinit - * - * Removes process protection and frees associated structures. - * - * IRQL: <= APC_LEVEL - */ -NTSTATUS KphProtectDeinit() -{ - NTSTATUS status = STATUS_SUCCESS; - KIRQL oldIrql; - LARGE_INTEGER waitLi; - - /* Unhook. */ - status = KphObOpenUnhook(&ProcessOpenHook); - status = KphObOpenUnhook(&ThreadOpenHook); - - /* Wait for all activity to finish. */ - ExWaitForRundownProtectionRelease(&ProtectedProcessRundownProtect); - /* Wait for a bit (some regions of hook target functions - are NOT guarded by rundown protection, e.g. - prologues and epilogues). */ - waitLi.QuadPart = KPH_REL_TIMEOUT_IN_SEC(1); - KeDelayExecutionThread(KernelMode, FALSE, &waitLi); - - /* Free all process protection entries. */ - ExDeleteNPagedLookasideList(&ProtectedProcessLookasideList); - - return status; -} - -/* KphNewOpenProcedure51 - * - * New process/thread open procedure for NT 5.1. - */ -NTSTATUS NTAPI KphNewOpenProcedure51( - __in OB_OPEN_REASON OpenReason, - __in PEPROCESS Process, - __in PVOID Object, - __in ACCESS_MASK GrantedAccess, - __in ULONG HandleCount - ) -{ - /* Simply call the 6.0 open procedure. */ - /* NOTE: GrantedAccess is always 0 on XP... */ - return KphNewOpenProcedure60( - OpenReason, - /* Assume worst case. */ - UserMode, - Process, - Object, - GrantedAccess, - HandleCount - ); -} - -/* KphNewOpenProcedure60 - * - * New process/thread open procedure for NT 6.0 and 6.1. - */ -NTSTATUS NTAPI KphNewOpenProcedure60( - __in OB_OPEN_REASON OpenReason, - __in KPROCESSOR_MODE AccessMode, - __in PEPROCESS Process, - __in PVOID Object, - __in ACCESS_MASK GrantedAccess, - __in ULONG HandleCount - ) -{ - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN accessAllowed = TRUE; - - /* Prevent the driver from unloading while this routine is executing. */ - if (!ExAcquireRundownProtection(&ProtectedProcessRundownProtect)) - { - /* Should never happen. */ - return STATUS_INTERNAL_ERROR; - } - - accessAllowed = KphpIsAccessAllowed( - Object, - AccessMode, - /* Assume worst case if granted access not available. */ - !GrantedAccess ? (ACCESS_MASK)-1 : GrantedAccess - ); - - if (accessAllowed) - { - POBJECT_TYPE objectType = KphGetObjectTypeNt(Object); - - /* Call the original open procedure. There shouldn't be any for Windows XP, - * while on Windows Vista and 7 it is used for implementing protected - * processes (Big Content's DRM protection, not KProcessHacker's protection). - */ - status = KphObOpenCall( - objectType == *PsProcessType ? &ProcessOpenHook : &ThreadOpenHook, - OpenReason, - AccessMode, - Process, - Object, - GrantedAccess, - HandleCount - ); - } - else - { - dprintf("KphNewOpenProcedure60: Access denied.\n"); - status = STATUS_ACCESS_DENIED; - } - - ExReleaseRundownProtection(&ProtectedProcessRundownProtect); - - return status; -} - -/* KphProtectAddEntry - * - * Protects the specified process. - * - * Thread safety: Full - * IRQL: <= DISPATCH_LEVEL - */ -PKPH_PROCESS_ENTRY KphProtectAddEntry( - __in PEPROCESS Process, - __in HANDLE Tag, - __in LOGICAL AllowKernelMode, - __in ACCESS_MASK ProcessAllowMask, - __in ACCESS_MASK ThreadAllowMask - ) -{ - KIRQL oldIrql; - PKPH_PROCESS_ENTRY entry; - - /* Prevent the lookaside list from being freed. */ - if (!ExAcquireRundownProtection(&ProtectedProcessRundownProtect)) - return NULL; - - entry = ExAllocateFromNPagedLookasideList(&ProtectedProcessLookasideList); - /* Lookaside list no longer needed. */ - ExReleaseRundownProtection(&ProtectedProcessRundownProtect); - - if (!entry) - return NULL; - - entry->Process = Process; - entry->CreatorProcess = PsGetCurrentProcess(); - entry->Tag = Tag; - entry->AllowKernelMode = AllowKernelMode; - entry->ProcessAllowMask = ProcessAllowMask; - entry->ThreadAllowMask = ThreadAllowMask; - - KeAcquireSpinLock(&ProtectedProcessListLock, &oldIrql); - InsertHeadList(&ProtectedProcessListHead, &entry->ListEntry); - KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql); - - return entry; -} - -/* KphProtectFindEntry - * - * Finds process protection data. - * - * Thread safety: Full/Limited. The returned pointer is not guaranteed to - * point to a valid process entry. However, the copied entry is safe to - * read. - * IRQL: <= DISPATCH_LEVEL - */ -PKPH_PROCESS_ENTRY KphProtectFindEntry( - __in PEPROCESS Process, - __in HANDLE Tag, - __out_opt PKPH_PROCESS_ENTRY ProcessEntryCopy - ) -{ - KIRQL oldIrql; - PLIST_ENTRY entry = ProtectedProcessListHead.Flink; - - KeAcquireSpinLock(&ProtectedProcessListLock, &oldIrql); - - while (entry != &ProtectedProcessListHead) - { - PKPH_PROCESS_ENTRY processEntry = - CONTAINING_RECORD(entry, KPH_PROCESS_ENTRY, ListEntry); - - if ( - (Process != NULL && processEntry->Process == Process) || - (Tag != NULL && processEntry->Tag == Tag) - ) - { - /* Copy the entry if requested. */ - if (ProcessEntryCopy) - memcpy(ProcessEntryCopy, processEntry, sizeof(KPH_PROCESS_ENTRY)); - - KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql); - - return processEntry; - } - - entry = entry->Flink; - } - - KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql); - - return NULL; -} - -/* KphProtectRemoveByProcess - * - * Removes protection from the specified process. - * - * Thread safety: Limited. Callers must synchronize remove calls such - * as KphProtectRemoveByProcess and KphProtectRemoveByTag. - * IRQL: <= DISPATCH_LEVEL - */ -BOOLEAN KphProtectRemoveByProcess( - __in PEPROCESS Process - ) -{ - PKPH_PROCESS_ENTRY entry = KphProtectFindEntry(Process, NULL, NULL); - - if (!entry) - return FALSE; - - KphpProtectRemoveEntry(entry); - - return TRUE; -} - -/* KphProtectRemoveByTag - * - * Removes protection from all processes with the specified tag. - * - * Thread safety: Limited. Callers must synchronize remove calls such - * as KphProtectRemoveByProcess and KphProtectRemoveByTag. - * IRQL: <= DISPATCH_LEVEL - */ -ULONG KphProtectRemoveByTag( - __in HANDLE Tag - ) -{ - KIRQL oldIrql; - ULONG count = 0; - PKPH_PROCESS_ENTRY entry; - - /* Keep removing entries until we can't find any more. */ - while (entry = KphProtectFindEntry(NULL, Tag, NULL)) - { - KphpProtectRemoveEntry(entry); - count++; - } - - return count; -} - -/* KphpIsAccessAllowed - * - * Checks if the specified access is allowed, according to process - * protection rules. - * - * Thread safety: Full - * IRQL: <= DISPATCH_LEVEL - */ -BOOLEAN KphpIsAccessAllowed( - __in PVOID Object, - __in KPROCESSOR_MODE AccessMode, - __in ACCESS_MASK DesiredAccess - ) -{ - POBJECT_TYPE objectType; - PEPROCESS processObject; - BOOLEAN isThread = FALSE; - - objectType = KphGetObjectTypeNt(Object); - /* It doesn't matter if it isn't actually a process because we won't be - dereferencing it. */ - processObject = (PEPROCESS)Object; - isThread = objectType == *PsThreadType; - - /* If this is a thread, get its parent process. */ - if (isThread) - processObject = IoThreadToProcess((PETHREAD)Object); - - if ( - processObject != PsGetCurrentProcess() && /* let the caller open its own processes/threads */ - (objectType == *PsProcessType || objectType == *PsThreadType) /* only protect processes and threads */ - ) - { - KPH_PROCESS_ENTRY processEntry; - - /* Search for and copy the corresponding process protection entry. */ - if (KphProtectFindEntry(processObject, NULL, &processEntry)) - { - ACCESS_MASK mask = - isThread ? processEntry.ThreadAllowMask : processEntry.ProcessAllowMask; - - /* The process/thread is protected. Check if the requested access is allowed. */ - if ( - /* check if kernel-mode is exempt from protection */ - !(processEntry.AllowKernelMode && AccessMode == KernelMode) && - /* allow the creator of the rule to bypass protection */ - processEntry.CreatorProcess != PsGetCurrentProcess() && - (DesiredAccess & mask) != DesiredAccess - ) - { - /* Access denied. */ - dprintf( - "%d: Access denied: 0x%08x (%s)\n", - PsGetCurrentProcessId(), - DesiredAccess, - isThread ? "Thread" : "Process" - ); - - return FALSE; - } - } - } - - return TRUE; -} - -/* KphpIsCurrentProcessProtected - * - * Determines whether the current process is protected. - * - * Thread safety: Full - * IRQL: <= DISPATCH_LEVEL - */ -BOOLEAN KphpIsCurrentProcessProtected() -{ - return KphProtectFindEntry(PsGetCurrentProcess(), NULL, NULL) != NULL; -} - -/* KphpProtectRemoveEntry - * - * Removes and frees process protection data. - * - * Thread safety: Full - * IRQL: <= DISPATCH_LEVEL - */ -VOID KphpProtectRemoveEntry( - __in PKPH_PROCESS_ENTRY Entry - ) -{ - KIRQL oldIrql; - - KeAcquireSpinLock(&ProtectedProcessListLock, &oldIrql); - RemoveEntryList(&Entry->ListEntry); - - /* Prevent the lookaside list from being destroyed. */ - ExAcquireRundownProtection(&ProtectedProcessRundownProtect); - ExFreeToNPagedLookasideList( - &ProtectedProcessLookasideList, - Entry - ); - ExReleaseRundownProtection(&ProtectedProcessRundownProtect); - - KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql); -} diff --git a/2.x/trunk/KProcessHacker/ps.c b/2.x/trunk/KProcessHacker/ps.c index c5662d7e3..0ce9f4b4a 100644 --- a/2.x/trunk/KProcessHacker/ps.c +++ b/2.x/trunk/KProcessHacker/ps.c @@ -21,8 +21,6 @@ */ #include "include/kph.h" -#include "include/ke.h" -#include "include/ps.h" VOID NTAPI KphpCaptureStackBackTraceThreadSpecialApc( PKAPC Apc, @@ -1063,14 +1061,20 @@ NTSTATUS KphTerminateProcess( { /* Otherwise, we'll have to call ZwTerminateProcess - most hooks on this function allow kernel-mode callers through. */ - OBJECT_ATTRIBUTES objectAttributes = { 0 }; + OBJECT_ATTRIBUTES oa; CLIENT_ID clientId; HANDLE newProcessHandle; - /* We have to open it again because ZwTerminateProcess only accepts kernel handles. */ + InitializeObjectAttributes( + &oa, + NULL, + OBJ_KERNEL_HANDLE, + NULL, + NULL + ); clientId.UniqueThread = 0; clientId.UniqueProcess = PsGetProcessId(processObject); - status = KphOpenProcess(&newProcessHandle, 0x1, &objectAttributes, &clientId, KernelMode); + status = KphOpenProcess(&newProcessHandle, PROCESS_TERMINATE, &oa, &clientId, KernelMode); ObDereferenceObject(processObject); if (NT_SUCCESS(status)) @@ -1112,10 +1116,7 @@ NTSTATUS KphTerminateThread( ObDereferenceObject(threadObject); } else - {/* - ObDereferenceObject(threadObject); - status = PspTerminateThreadByPointer(PsGetCurrentThread(), ExitStatus); */ - /* Leads to bugs, so don't terminate self. */ + { ObDereferenceObject(threadObject); return STATUS_CANT_TERMINATE_SELF; } diff --git a/2.x/trunk/KProcessHacker/ref.c b/2.x/trunk/KProcessHacker/ref.c index 5476d6749..bb99d5608 100644 --- a/2.x/trunk/KProcessHacker/ref.c +++ b/2.x/trunk/KProcessHacker/ref.c @@ -20,6 +20,9 @@ * along with Process Hacker. If not, see . */ +#define _REF_PRIVATE +#include "include/kph.h" +#include "include/ref.h" #include "include/refp.h" /* A list of all objects created by the object manager. */ diff --git a/2.x/trunk/KProcessHacker/resource.rc b/2.x/trunk/KProcessHacker/resource.rc index d38b333d6..8317e1c5f 100644 --- a/2.x/trunk/KProcessHacker/resource.rc +++ b/2.x/trunk/KProcessHacker/resource.rc @@ -1,7 +1,7 @@ #include -#define VER_COMMA 1,10,0,0 -#define VER_STR "1.10\0" +#define VER_COMMA 2,0,0,0 +#define VER_STR "2.0\0" #define VER_FILEVERSION VER_COMMA #define VER_FILEVERSION_STR VER_STR diff --git a/2.x/trunk/KProcessHacker/se.c b/2.x/trunk/KProcessHacker/se.c index ce09c6607..f6a97a0ed 100644 --- a/2.x/trunk/KProcessHacker/se.c +++ b/2.x/trunk/KProcessHacker/se.c @@ -21,7 +21,6 @@ */ #include "include/kph.h" -#include "include/se.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, KphOpenProcessTokenEx) diff --git a/2.x/trunk/KProcessHacker/sources b/2.x/trunk/KProcessHacker/sources index ff6e07b5e..e7d9e7392 100644 --- a/2.x/trunk/KProcessHacker/sources +++ b/2.x/trunk/KProcessHacker/sources @@ -10,13 +10,7 @@ SOURCES= \ version.c \ \ kph.c \ - handle.c \ - hook.c \ - protect.c \ ref.c \ - sync.c \ - sysservice.c \ - sysservicedata.c \ test.c \ trace.c \ util.c \ diff --git a/2.x/trunk/KProcessHacker/sync.c b/2.x/trunk/KProcessHacker/sync.c deleted file mode 100644 index 99bd46bf8..000000000 --- a/2.x/trunk/KProcessHacker/sync.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Process Hacker Driver - - * synchronization code - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#include "include/sync.h" -#include "include/debug.h" - -ULONG KphpCountBits( - __in ULONG_PTR Number - ); - -VOID KphpProcessorLockDpc( - __in PKDPC Dpc, - __in PVOID DeferredContext, - __in PVOID SystemArgument1, - __in PVOID SystemArgument2 - ); - -/* KphfAcquireGuardedLock - * - * Acquires a guarded lock and raises the IRQL to APC_LEVEL. - * - * IRQL: <= APC_LEVEL - */ -VOID FASTCALL KphfAcquireGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ) -{ - KIRQL oldIrql; - - ASSERT(KeGetCurrentIrql() <= APC_LEVEL); - - /* Raise to APC_LEVEL. */ - oldIrql = KeRaiseIrql(APC_LEVEL, &oldIrql); - - /* Acquire the spinlock. */ - KphAcquireBitSpinLock(&Lock->Value, KPH_GUARDED_LOCK_ACTIVE_SHIFT); - - /* Now that we have the lock, we must save the old IRQL. */ - /* Clear the old IRQL. */ - Lock->Value &= KPH_GUARDED_LOCK_FLAGS; - /* Set the new IRQL. */ - Lock->Value |= oldIrql; -} - -/* KphfReleaseGuardedLock - * - * Releases a guarded lock and restores the old IRQL. - * - * IRQL: >= APC_LEVEL - */ -VOID FASTCALL KphfReleaseGuardedLock( - __inout PKPH_GUARDED_LOCK Lock - ) -{ - KIRQL oldIrql; - - ASSERT(KeGetCurrentIrql() >= APC_LEVEL); - - /* Get the old IRQL. */ - oldIrql = (KIRQL)(Lock->Value & ~KPH_GUARDED_LOCK_FLAGS); - /* Unlock the spinlock. */ - KphReleaseBitSpinLock(&Lock->Value, KPH_GUARDED_LOCK_ACTIVE_SHIFT); - /* Restore the old IRQL. */ - KeLowerIrql(oldIrql); -} - -/* KphAcquireProcessorLock - * - * Raises the IRQL to DISPATCH_LEVEL and prevents threads from - * executing on other processors until the processor lock is released. - * Blocks if the supplied processor lock is already in use. - * - * ProcessorLock: A processor lock structure that is present in - * non-paged memory. - * - * Comments: - * Here is how the processor lock works: - * 1. Tries to acquire the mutex in the processor lock, and - * blocks until it can be obtained. - * 2. Initializes a DPC for each processor on the computer. - * 3. Raises the IRQL to DISPATCH_LEVEL to make sure the - * code is not interrupted by a context switch. - * 4. Queues each of the previously-initialized DPCs, except if - * it is targeted at the current processor. - * 5. Since DPCs run at DISPATCH_LEVEL, they have exclusive - * control of the processor. As each runs, they increment - * a counter in the processor lock. They then enter a loop. - * 6. The routine waits for the counter to become n - 1, - * signaling that all (other) processors have been acquired - * (where n is the number of processors). - * 7. It returns. Any code from here will be running in - * DISPATCH_LEVEL and will be the only code running on the - * machine. - * Thread safety: Full - * IRQL: <= APC_LEVEL - */ -BOOLEAN KphAcquireProcessorLock( - __inout PKPH_PROCESSOR_LOCK ProcessorLock - ) -{ - ULONG i; - ULONG numberProcessors; - ULONG currentProcessor; - - /* Acquire the processor lock guarded lock. */ - KphAcquireGuardedLock(&ProcessorLock->Lock); - - /* Reset some state. */ - ASSERT(ProcessorLock->AcquiredProcessors == 0); - ProcessorLock->AcquiredProcessors = 0; - ProcessorLock->ReleaseSignal = 0; /* IMPORTANT */ - - /* Get the number of processors. */ - numberProcessors = KphpCountBits(KeQueryActiveProcessors()); - - /* If there's only one processor we can simply raise the IRQL and exit. */ - if (numberProcessors == 1) - { - dprintf("KphAcquireProcessorLock: Only one processor, raising IRQL and exiting...\n"); - KeRaiseIrql(DISPATCH_LEVEL, &ProcessorLock->OldIrql); - ProcessorLock->Acquired = TRUE; - - return TRUE; - } - - /* Allocate storage for the DPCs. */ - ProcessorLock->Dpcs = ExAllocatePoolWithTag( - NonPagedPool, - sizeof(KDPC) * numberProcessors, - TAG_SYNC_DPC - ); - - if (!ProcessorLock->Dpcs) - { - dprintf("KphAcquireProcessorLock: Could not allocate storage for DPCs!\n"); - KphReleaseGuardedLock(&ProcessorLock->Lock); - return FALSE; - } - - /* Initialize the DPCs. */ - for (i = 0; i < numberProcessors; i++) - { - KeInitializeDpc(&ProcessorLock->Dpcs[i], KphpProcessorLockDpc, NULL); - KeSetTargetProcessorDpc(&ProcessorLock->Dpcs[i], (CCHAR)i); - KeSetImportanceDpc(&ProcessorLock->Dpcs[i], HighImportance); - } - - /* Raise the IRQL to DISPATCH_LEVEL to prevent context switching. */ - KeRaiseIrql(DISPATCH_LEVEL, &ProcessorLock->OldIrql); - /* Get the current processor number. */ - currentProcessor = KeGetCurrentProcessorNumber(); - - /* Queue the DPCs (except on the current processor). */ - for (i = 0; i < numberProcessors; i++) - if (i != currentProcessor) - KeInsertQueueDpc(&ProcessorLock->Dpcs[i], ProcessorLock, NULL); - - /* Spinwait for all (other) processors to be acquired. */ - KphSpinUntilEqual(&ProcessorLock->AcquiredProcessors, numberProcessors - 1); - - dprintf("KphAcquireProcessorLock: All processors acquired.\n"); - ProcessorLock->Acquired = TRUE; - - return TRUE; -} - -/* KphInitializeProcessorLock - * - * Initializes a processor lock. - * - * ProcessorLock: A processor lock structure that is present in - * non-paged memory. - * - * IRQL: Any - */ -VOID KphInitializeProcessorLock( - __out PKPH_PROCESSOR_LOCK ProcessorLock - ) -{ - KphInitializeGuardedLock(&ProcessorLock->Lock, FALSE); - ProcessorLock->Dpcs = NULL; - ProcessorLock->AcquiredProcessors = 0; - ProcessorLock->ReleaseSignal = 0; - ProcessorLock->OldIrql = PASSIVE_LEVEL; - ProcessorLock->Acquired = FALSE; -} - -/* KphReleaseProcessorLock - * - * Allows threads to execute on other processors and restores the IRQL. - * - * ProcessorLock: A processor lock structure that is present in - * non-paged memory. - * - * Comments: - * Here is how the processor lock is released: - * 1. Sets the signal to release the processors. The DPCs that are - * currently waiting for the signal will return and decrement - * the acquired processors counter. - * 2. Waits for the acquired processors counter to become zero. - * 3. Restores the old IRQL. This will always be APC_LEVEL due to - * the mutex. - * 4. Frees the storage allocated for the DPCs. - * 5. Releases the processor lock mutex. This will restore the IRQL - * back to normal. - * Thread safety: Full - * IRQL: DISPATCH_LEVEL - */ -VOID KphReleaseProcessorLock( - __inout PKPH_PROCESSOR_LOCK ProcessorLock - ) -{ - if (!ProcessorLock->Acquired) - return; - - /* Signal for the acquired processors to be released. */ - InterlockedExchange(&ProcessorLock->ReleaseSignal, 1); - - /* Spinwait for all acquired processors to be released. */ - KphSpinUntilEqual(&ProcessorLock->AcquiredProcessors, 0); - - dprintf("KphReleaseProcessorLock: All processors released.\n"); - - /* Restore the old IRQL (should always be APC_LEVEL due to the - * fast mutex). */ - KeLowerIrql(ProcessorLock->OldIrql); - - /* Free the DPCs if necessary. */ - if (ProcessorLock->Dpcs != NULL) - { - ExFreePoolWithTag(ProcessorLock->Dpcs, TAG_SYNC_DPC); - ProcessorLock->Dpcs = NULL; - } - - ProcessorLock->Acquired = FALSE; - - /* Release the processor lock guarded lock. This will restore the - * IRQL back to what it was before the processor lock was - * acquired. - */ - KphReleaseGuardedLock(&ProcessorLock->Lock); -} - -/* KphpCountBits - * - * Counts the number of bits set in an integer. - */ -ULONG KphpCountBits( - __in ULONG_PTR Number - ) -{ - ULONG count = 0; - - while (Number) - { - count++; - Number &= Number - 1; - } - - return count; -} - -/* KphpProcessorLockDpc - * - * The DPC routine which "locks" processors. - * - * Thread safety: Full - * IRQL: DISPATCH_LEVEL - */ -VOID KphpProcessorLockDpc( - __in PKDPC Dpc, - __in PVOID DeferredContext, - __in PVOID SystemArgument1, - __in PVOID SystemArgument2 - ) -{ - PKPH_PROCESSOR_LOCK processorLock = (PKPH_PROCESSOR_LOCK)SystemArgument1; - - ASSERT(processorLock != NULL); - - dprintf("KphpProcessorLockDpc: Acquiring processor %d.\n", KeGetCurrentProcessorNumber()); - - /* Increase the number of acquired processors. */ - InterlockedIncrement(&processorLock->AcquiredProcessors); - - /* Spin until we get the signal to release the processor. */ - KphSpinUntilNotEqual(&processorLock->ReleaseSignal, 0); - - /* Decrease the number of acquired processors. */ - InterlockedDecrement(&processorLock->AcquiredProcessors); - - dprintf("KphpProcessorLockDpc: Releasing processor %d.\n", KeGetCurrentProcessorNumber()); -} diff --git a/2.x/trunk/KProcessHacker/sysservice.c b/2.x/trunk/KProcessHacker/sysservice.c deleted file mode 100644 index 784706b4b..000000000 --- a/2.x/trunk/KProcessHacker/sysservice.c +++ /dev/null @@ -1,2140 +0,0 @@ -/* - * Process Hacker Driver - - * system service logging - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -/* ================ IMPORTANT ================ - * Please read the comments in KphpSsNewKiFastCallEntry to find out how - * KiFastCallEntry can be hooked. - * - * Note that the ONLY SUPPORTED METHOD of hooking is KiFastCallEntry, - * which means you MUST be using a CPU which supports sysenter. - * =========================================== - */ - -#include "include/sysservicep.h" -#include "include/hook.h" -#include "include/sync.h" -#include "include/trace.h" - -extern PDRIVER_OBJECT KphDriverObject; - -/* A fast mutex guarding starting/stopping system service logging. */ -FAST_MUTEX KphSsMutex; -/* Whether system service logging has been initialized. */ -BOOLEAN KphSsInitialized = FALSE; -/* The KiFastCallEntry hook. */ -KPH_HOOK KphSsKiFastCallEntryHook; -/* The number of active loggers. */ -ULONG KphSsNumberOfActiveLoggers = 0; - -/* The object type for client entries. */ -PKPH_OBJECT_TYPE KphSsClientEntryType; -/* The object type for ruleset entries. */ -PKPH_OBJECT_TYPE KphSsRuleSetEntryType; -/* The object type for rule entries. */ -PKPH_OBJECT_TYPE KphSsRuleEntryType; - -/* The list of ruleset entries. */ -LIST_ENTRY KphSsRuleSetListHead; -/* A push lock guarding accesses to the ruleset list. */ -EX_PUSH_LOCK KphSsRuleSetListPushLock; - -/* KphSsLogInit - * - * Initializes system service logging. - */ -NTSTATUS KphSsLogInit() -{ - NTSTATUS status = STATUS_SUCCESS; - - /* Initialize the system service call data. */ - KphSsDataInit(); - - /* Initialize the ruleset list. */ - InitializeListHead(&KphSsRuleSetListHead); - ExInitializeFastMutex(&KphSsMutex); - ExInitializePushLock(&KphSsRuleSetListPushLock); - - /* Initialize the object types. */ - status = KphCreateObjectType( - &KphSsClientEntryType, - NonPagedPool, - 0, - KphpSsClientEntryDeleteProcedure - ); - - if (!NT_SUCCESS(status)) - return status; - - status = KphCreateObjectType( - &KphSsRuleSetEntryType, - NonPagedPool, - 0, - KphpSsRuleSetEntryDeleteProcedure - ); - - if (!NT_SUCCESS(status)) - { - KphDereferenceObject(KphSsClientEntryType); - return status; - } - - status = KphCreateObjectType( - &KphSsRuleEntryType, - NonPagedPool, - 0, - NULL - ); - - if (!NT_SUCCESS(status)) - { - KphDereferenceObject(KphSsClientEntryType); - KphDereferenceObject(KphSsRuleSetEntryType); - return status; - } - - return status; -} - -/* KphSsLogDeinit - * - * Frees system service logging data. - */ -NTSTATUS KphSsLogDeinit() -{ - KphSsDataDeinit(); - - return STATUS_SUCCESS; -} - -/* KphSsLogStart - * - * Starts system service logging. - */ -NTSTATUS KphSsLogStart() -{ -#ifdef _X86_ - NTSTATUS status = STATUS_SUCCESS; - - /* Make sure we have the KiFastCallEntry+x address. */ - if (!__KiFastCallEntry) - return STATUS_NOT_SUPPORTED; - - ExAcquireFastMutex(&KphSsMutex); - - if (KphSsInitialized) - { - ExReleaseFastMutex(&KphSsMutex); - return STATUS_UNSUCCESSFUL; - } - - /* Hook KiFastCallEntry. Logging will start from now. */ - KphInitializeHook( - &KphSsKiFastCallEntryHook, - __KiFastCallEntry, - KphpSsNewKiFastCallEntry - ); - status = KphHook(&KphSsKiFastCallEntryHook); - - if (!NT_SUCCESS(status)) - { - ExReleaseFastMutex(&KphSsMutex); - return status; - } - - KphSsInitialized = TRUE; - - ExReleaseFastMutex(&KphSsMutex); - - return status; -#else - return STATUS_NOT_SUPPORTED; -#endif -} - -/* KphSsLogStop - * - * Stops system service logging. - */ -NTSTATUS KphSsLogStop() -{ -#ifdef _X86_ - NTSTATUS status = STATUS_SUCCESS; - - ExAcquireFastMutex(&KphSsMutex); - - if (!KphSsInitialized) - { - ExReleaseFastMutex(&KphSsMutex); - return STATUS_UNSUCCESSFUL; - } - - status = KphUnhook(&KphSsKiFastCallEntryHook); - - if (!NT_SUCCESS(status)) - { - ExReleaseFastMutex(&KphSsMutex); - return status; - } - - /* Spin until the logger count reaches 0. */ - KphSpinUntilEqual(&KphSsNumberOfActiveLoggers, 0); - - KphSsInitialized = FALSE; - - ExReleaseFastMutex(&KphSsMutex); - - return status; -#else - return STATUS_NOT_SUPPORTED; -#endif -} - -/* KphSsCreateClientEntry - * - * Creates a client entry which describes a client of the - * system service logger. Clients receive system service log events. - * Note that a client may have several ruleset entries associated - * with it. - * - * ClientEntry: A variable which receives a pointer to the client entry. - * ProcessHandle: A handle to the client process, with PROCESS_VM_WRITE - * access. - * ReadSemaphoreHandle: A handle to a semaphore which is released when an - * event is written to the client buffer. The client must wait for the - * semaphore when it is about to read a block. - * WriteSemaphoreHandle: A handle to a semaphore which is acquired when an - * event is about to be written to the client buffer. If the semaphore - * cannot be acquired immediately, the event is dropped. The client must - * continually read the buffer and release the semaphore. - * BufferBase: A pointer to a buffer in the client process. - * BufferSize: The size of the buffer, in bytes. - * AccessMode: The mode to use when probing arguments. - */ -NTSTATUS KphSsCreateClientEntry( - __out PKPHSS_CLIENT_ENTRY *ClientEntry, - __in HANDLE ProcessHandle, - __in HANDLE ReadSemaphoreHandle, - __in HANDLE WriteSemaphoreHandle, - __in PVOID BufferBase, - __in ULONG BufferSize, - __in KPROCESSOR_MODE AccessMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_CLIENT_ENTRY clientEntry; - PEPROCESS processObject; - PKSEMAPHORE readSemaphore; - PKSEMAPHORE writeSemaphore; - - /* Probe. */ - if (AccessMode != KernelMode) - { - __try - { - ProbeForWrite(BufferBase, BufferSize, 1); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return GetExceptionCode(); - } - } - - /* Reference the client process. */ - status = ObReferenceObjectByHandle( - ProcessHandle, - PROCESS_VM_WRITE, - *PsProcessType, - AccessMode, - &processObject, - NULL - ); - - if (!NT_SUCCESS(status)) - return status; - - /* Reference the read semaphore. */ - status = ObReferenceObjectByHandle( - ReadSemaphoreHandle, - SEMAPHORE_MODIFY_STATE, - *ExSemaphoreObjectType, - AccessMode, - &readSemaphore, - NULL - ); - - if (!NT_SUCCESS(status)) - { - ObDereferenceObject(processObject); - return status; - } - - /* Reference the write semaphore. */ - status = ObReferenceObjectByHandle( - WriteSemaphoreHandle, - SEMAPHORE_MODIFY_STATE, - *ExSemaphoreObjectType, - AccessMode, - &writeSemaphore, - NULL - ); - - if (!NT_SUCCESS(status)) - { - ObDereferenceObject(processObject); - ObDereferenceObject(readSemaphore); - return status; - } - - /* Create the client entry object. */ - status = KphCreateObject( - &clientEntry, - sizeof(KPHSS_CLIENT_ENTRY), - 0, - KphSsClientEntryType, - 0 - ); - - if (!NT_SUCCESS(status)) - { - ObDereferenceObject(processObject); - ObDereferenceObject(readSemaphore); - ObDereferenceObject(writeSemaphore); - - return status; - } - - clientEntry->Process = processObject; - clientEntry->Enabled = TRUE; - clientEntry->ReadSemaphore = readSemaphore; - clientEntry->WriteSemaphore = writeSemaphore; - ExInitializeFastMutex(&clientEntry->BufferMutex); - clientEntry->BufferBase = BufferBase; - clientEntry->BufferSize = BufferSize; - clientEntry->BufferCursor = 0; - clientEntry->NumberOfBlocksWritten = 0; - clientEntry->NumberOfBlocksDropped = 0; - - *ClientEntry = clientEntry; - - return status; -} - -/* KphSsEnableClientEntry - * - * Enables or disables a client entry. - */ -NTSTATUS KphSsEnableClientEntry( - __in PKPHSS_CLIENT_ENTRY ClientEntry, - __in BOOLEAN Enable - ) -{ - if (Enable) - ClientEntry->Enabled = TRUE; - else - ClientEntry->Enabled = FALSE; - - return STATUS_SUCCESS; -} - -/* KphSsQueryClientEntry - * - * Queries information about a client entry. - */ -NTSTATUS KphSsQueryClientEntry( - __in PKPHSS_CLIENT_ENTRY ClientEntry, - __out_bcount_opt(ClientInformationLength) PKPHSS_CLIENT_INFORMATION ClientInformation, - __in ULONG ClientInformationLength, - __out_opt PULONG ReturnLength, - __in KPROCESSOR_MODE AccessMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - - /* Probe the return length if necessary. */ - if (AccessMode != KernelMode) - { - __try - { - ProbeForWrite(ReturnLength, sizeof(ULONG), 1); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return GetExceptionCode(); - } - } - - /* Check the length. */ - if (ClientInformationLength >= sizeof(KPHSS_CLIENT_INFORMATION)) - { - if (ClientInformation) - { - __try - { - /* Probe the buffer if we're not from kernel-mode. */ - if (AccessMode != KernelMode) - ProbeForWrite(ClientInformation, sizeof(KPHSS_CLIENT_INFORMATION), 1); - - ClientInformation->ProcessId = PsGetProcessId(ClientEntry->Process); - ClientInformation->BufferBase = ClientEntry->BufferBase; - ClientInformation->BufferSize = ClientEntry->BufferSize; - ClientInformation->NumberOfBlocksWritten = ClientEntry->NumberOfBlocksWritten; - ClientInformation->NumberOfBlocksDropped = ClientEntry->NumberOfBlocksDropped; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - status = GetExceptionCode(); - } - } - } - else - { - status = STATUS_BUFFER_TOO_SMALL; - } - - /* Pass the return length back if requested. */ - if (ReturnLength) - { - __try - { - *ReturnLength = sizeof(KPHSS_CLIENT_INFORMATION); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - status = GetExceptionCode(); - } - } - - return status; -} - -/* KphpSsClientEntryDeleteProcedure - * - * Performs cleanup for a client entry. - */ -VOID NTAPI KphpSsClientEntryDeleteProcedure( - __in PVOID Object, - __in ULONG Flags - ) -{ - PKPHSS_CLIENT_ENTRY clientEntry = (PKPHSS_CLIENT_ENTRY)Object; - - ObDereferenceObject(clientEntry->Process); - ObDereferenceObject(clientEntry->ReadSemaphore); - ObDereferenceObject(clientEntry->WriteSemaphore); -} - -/* KphSsCreateRuleSetEntry - * - * Creates a ruleset entry which contains a list of rules - * and an action to perform. - */ -NTSTATUS KphSsCreateRuleSetEntry( - __out PKPHSS_RULESET_ENTRY *RuleSetEntry, - __in PKPHSS_CLIENT_ENTRY ClientEntry, - __in KPHSS_FILTER_TYPE DefaultFilterType, - __in KPHSS_RULESET_ACTION Action - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_RULESET_ENTRY ruleSetEntry; - - /* Make sure the action is valid. */ - if (Action < LogRuleSetAction || Action >= MaxRuleSetAction) - return STATUS_INVALID_PARAMETER_3; - - /* Create the ruleset object. */ - status = KphCreateObject( - &ruleSetEntry, - sizeof(KPHSS_RULESET_ENTRY), - 0, - KphSsRuleSetEntryType, - 0 - ); - - if (!NT_SUCCESS(status)) - return status; - - /* Initialize the ruleset object. */ - KphReferenceObject(ClientEntry); - ruleSetEntry->Client = ClientEntry; - ruleSetEntry->DefaultFilterType = DefaultFilterType; - ruleSetEntry->Action = Action; - ruleSetEntry->NextRuleHandle = 4; - ExInitializePushLock(&ruleSetEntry->RuleListPushLock); - InitializeListHead(&ruleSetEntry->RuleListHead); - - /* Add the ruleset to the list. */ - KeEnterCriticalRegion(); - ExAcquirePushLockExclusive(&KphSsRuleSetListPushLock); - InsertHeadList(&KphSsRuleSetListHead, &ruleSetEntry->RuleSetListEntry); - ExReleasePushLock(&KphSsRuleSetListPushLock); - KeLeaveCriticalRegion(); - - *RuleSetEntry = ruleSetEntry; - - return status; -} - -/* KphpSsRuleSetEntryDeleteProcedure - * - * Performs cleanup for a ruleset entry. - */ -VOID NTAPI KphpSsRuleSetEntryDeleteProcedure( - __in PVOID Object, - __in ULONG Flags - ) -{ - PKPHSS_RULESET_ENTRY ruleSetEntry = (PKPHSS_RULESET_ENTRY)Object; - PLIST_ENTRY currentRuleListEntry; - - /* Dereference the client entry. */ - KphDereferenceObject(ruleSetEntry->Client); - - KeEnterCriticalRegion(); - - /* Dereference all rules in the ruleset. */ - ExAcquirePushLockExclusive(&ruleSetEntry->RuleListPushLock); - - currentRuleListEntry = ruleSetEntry->RuleListHead.Flink; - - while (currentRuleListEntry != &ruleSetEntry->RuleListHead) - { - PLIST_ENTRY nextEntry; - - /* Save the next entry pointer since currentRuleListEntry may - * be deallocated due to the dereference. - */ - nextEntry = currentRuleListEntry->Flink; - KphDereferenceObject(KPHSS_RULE_ENTRY(currentRuleListEntry)); - currentRuleListEntry = nextEntry; - } - - ExReleasePushLock(&ruleSetEntry->RuleListPushLock); - - /* Remove the ruleset from the list. */ - ExAcquirePushLockExclusive(&KphSsRuleSetListPushLock); - RemoveEntryList(&ruleSetEntry->RuleSetListEntry); - ExReleasePushLock(&KphSsRuleSetListPushLock); - - KeLeaveCriticalRegion(); -} - -/* KphSsAddProcessIdRule - * - * Adds a process ID rule entry to a ruleset entry. - */ -NTSTATUS KphSsAddProcessIdRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in HANDLE ProcessId - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_RULE_ENTRY ruleEntry; - - /* Add the rule. */ - status = KphpSsAddRule(&ruleEntry, RuleSetEntry, FilterType, ProcessIdRuleType); - - if (!NT_SUCCESS(status)) - return status; - - ruleEntry->ProcessIdRule.ProcessId = ProcessId; - ruleEntry->Initialized = TRUE; - - *RuleEntry = ruleEntry; - - return status; -} - -/* KphSsAddThreadIdRule - * - * Adds a thread ID rule entry to a ruleset entry. - */ -NTSTATUS KphSsAddThreadIdRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in HANDLE ThreadId - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_RULE_ENTRY ruleEntry; - - /* Add the rule. */ - status = KphpSsAddRule(&ruleEntry, RuleSetEntry, FilterType, ThreadIdRuleType); - - if (!NT_SUCCESS(status)) - return status; - - ruleEntry->ThreadIdRule.ThreadId = ThreadId; - ruleEntry->Initialized = TRUE; - - *RuleEntry = ruleEntry; - - return status; -} - -/* KphSsAddPreviousModeRule - * - * Adds a previous mode rule entry to a ruleset entry. - */ -NTSTATUS KphSsAddPreviousModeRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in KPROCESSOR_MODE PreviousMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_RULE_ENTRY ruleEntry; - - /* Add the rule. */ - status = KphpSsAddRule(&ruleEntry, RuleSetEntry, FilterType, PreviousModeRuleType); - - if (!NT_SUCCESS(status)) - return status; - - ruleEntry->PreviousModeRule.PreviousMode = PreviousMode; - ruleEntry->Initialized = TRUE; - - *RuleEntry = ruleEntry; - - return status; -} - -/* KphSsAddNumberRule - * - * Adds a system service number rule entry to a ruleset entry. - */ -NTSTATUS KphSsAddNumberRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in ULONG Number - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_RULE_ENTRY ruleEntry; - - /* Add the rule. */ - status = KphpSsAddRule(&ruleEntry, RuleSetEntry, FilterType, NumberRuleType); - - if (!NT_SUCCESS(status)) - return status; - - ruleEntry->NumberRule.Number = Number; - ruleEntry->Initialized = TRUE; - - *RuleEntry = ruleEntry; - - return status; -} - -/* KphSsGetHandleRule - * - * Gets the handle of a rule. - */ -HANDLE KphSsGetHandleRule( - __in PKPHSS_RULE_ENTRY RuleEntry - ) -{ - return RuleEntry->Handle; -} - -/* KphSsRemoveRule - * - * Removes a rule entry from a ruleset entry. - */ -NTSTATUS KphSsRemoveRule( - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in HANDLE RuleEntryHandle - ) -{ - PLIST_ENTRY currentListEntry; - - KeEnterCriticalRegion(); - ExAcquirePushLockExclusive(&RuleSetEntry->RuleListPushLock); - - /* Find the rule in the ruleset. */ - - currentListEntry = RuleSetEntry->RuleListHead.Flink; - - while (currentListEntry != &RuleSetEntry->RuleListHead) - { - PKPHSS_RULE_ENTRY ruleEntry = KPHSS_RULE_ENTRY(currentListEntry); - - if (ruleEntry->Handle == RuleEntryHandle) - { - /* Remove the rule from the list. */ - RemoveEntryList(&ruleEntry->RuleListEntry); - /* Dereference the rule (it was referenced when it - * got added to the list). - */ - KphDereferenceObject(ruleEntry); - - ExReleasePushLock(&RuleSetEntry->RuleListPushLock); - KeLeaveCriticalRegion(); - - return STATUS_SUCCESS; - } - - currentListEntry = currentListEntry->Flink; - } - - ExReleasePushLock(&RuleSetEntry->RuleListPushLock); - KeLeaveCriticalRegion(); - - return STATUS_INVALID_PARAMETER_2; -} - -/* KphpSsAddRule - * - * Adds a rule entry to a ruleset entry. - */ -NTSTATUS KphpSsAddRule( - __out PKPHSS_RULE_ENTRY *RuleEntry, - __in PKPHSS_RULESET_ENTRY RuleSetEntry, - __in KPHSS_FILTER_TYPE FilterType, - __in KPHSS_RULE_TYPE RuleType - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_RULE_ENTRY ruleEntry; - - /* Make sure the filter/rule type is valid. */ - if (FilterType < IncludeFilterType || FilterType >= MaxFilterType) - return STATUS_INVALID_PARAMETER_3; - if (RuleType < ProcessIdRuleType || RuleType >= MaxRuleType) - return STATUS_INVALID_PARAMETER_4; - - /* Create the rule entry object. */ - status = KphCreateObject( - &ruleEntry, - sizeof(KPHSS_RULE_ENTRY), - 0, - KphSsRuleEntryType, - 0 - ); - - if (!NT_SUCCESS(status)) - return status; - - /* Initialize the object. */ - ruleEntry->Initialized = FALSE; - ruleEntry->FilterType = FilterType; - ruleEntry->RuleType = RuleType; - - /* Get a handle for the rule. */ - ruleEntry->Handle = (HANDLE)(ULONG_PTR)InterlockedExchangeAdd( - &RuleSetEntry->NextRuleHandle, - KPHSS_RULE_HANDLE_INCREMENT - ); - - /* Add the rule to the ruleset. */ - KeEnterCriticalRegion(); - ExAcquirePushLockExclusive(&RuleSetEntry->RuleListPushLock); - InsertTailList(&RuleSetEntry->RuleListHead, &ruleEntry->RuleListEntry); - ExReleasePushLock(&RuleSetEntry->RuleListPushLock); - KeLeaveCriticalRegion(); - /* Add a reference for the rule being on the list. */ - KphReferenceObject(ruleEntry); - - *RuleEntry = ruleEntry; - - return status; -} - -/* KphpSsCreateEventBlock - * - * Allocates and initializes an event block. - * - * EventBlock: A variable which receives a pointer to the event block. - * Thread: The thread for which the event is being generated. - * Number: The system service number. - * Arguments: A pointer to the caller-supplied arguments. - * NumberOfArguments: The number of arguments, in ULONGs. - */ -NTSTATUS KphpSsCreateEventBlock( - __out PKPHSS_EVENT_BLOCK *EventBlock, - __in PKTHREAD Thread, - __in ULONG Number, - __in ULONG *Arguments, - __in ULONG NumberOfArguments - ) -{ - PKPHSS_EVENT_BLOCK eventBlock; - KPROCESSOR_MODE previousMode; - ULONG eventBlockSize; - ULONG argumentsSize; - ULONG traceSize; - PVOID stackTrace[MAX_STACK_DEPTH * 2]; - ULONG capturedFrames; - - /* Make sure the argument count isn't too large. */ - if (NumberOfArguments > MAX_USHORT) - return STATUS_INVALID_PARAMETER; - - previousMode = ExGetPreviousMode(); - - /* Capture kernel-mode and user-mode stack traces. - * We do this before we allocate the event block so - * we can calculate how large the block should be. - */ - - /* Get a kernel-mode stack trace. */ - capturedFrames = KphCaptureStackBackTrace( - 0, - MAX_STACK_DEPTH - 1, - 0, - stackTrace, - NULL - ); - - if (PsGetCurrentProcess() != PsInitialSystemProcess) - { - /* Get a user-mode stack trace. */ - capturedFrames += KphCaptureStackBackTrace( - 0, - MAX_STACK_DEPTH - 1, - RTL_WALK_USER_MODE_STACK, - &stackTrace[capturedFrames], - NULL - ); - } - - /* Calculate the size of the event block. */ - argumentsSize = NumberOfArguments * sizeof(ULONG); - traceSize = capturedFrames * sizeof(PVOID); - eventBlockSize = sizeof(KPHSS_EVENT_BLOCK) + argumentsSize + traceSize; - - /* Make sure the block size isn't too large. */ - if (eventBlockSize > MAX_USHORT) - return STATUS_INVALID_PARAMETER; - - /* Allocate the event block. */ - eventBlock = ExAllocatePoolWithTag(PagedPool, eventBlockSize, TAG_EVENT_BLOCK); - - if (!eventBlock) - return STATUS_INSUFFICIENT_RESOURCES; - - /* Initialize the event block. */ - eventBlock->Header.Size = (USHORT)eventBlockSize; - eventBlock->Header.Type = EventBlockType; - eventBlock->Flags = 0; - KeQuerySystemTime(&eventBlock->Time); - eventBlock->ClientId.UniqueThread = PsGetThreadId(Thread); - eventBlock->ClientId.UniqueProcess = PsGetProcessId(IoThreadToProcess(Thread)); - eventBlock->Number = Number; - eventBlock->NumberOfArguments = (USHORT)NumberOfArguments; - eventBlock->ArgumentsOffset = sizeof(KPHSS_EVENT_BLOCK); - eventBlock->TraceCount = (USHORT)capturedFrames; - eventBlock->TraceOffset = (USHORT)(sizeof(KPHSS_EVENT_BLOCK) + argumentsSize); - - /* Set the flags according to the previous mode. */ - if (previousMode == UserMode) - eventBlock->Flags |= KPHSS_EVENT_USER_MODE; - else if (previousMode == KernelMode) - eventBlock->Flags |= KPHSS_EVENT_KERNEL_MODE; - - /* Probe and copy the arguments. */ - if (previousMode != KernelMode) - { - __try - { - ProbeForRead(Arguments, argumentsSize, 4); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - eventBlock->Flags |= KPHSS_EVENT_PROBE_ARGUMENTS_FAILED; - } - } - - __try - { - /* Copy the arguments to the space immediately after the event block. */ - memcpy((PCHAR)eventBlock + eventBlock->ArgumentsOffset, Arguments, argumentsSize); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - eventBlock->Flags |= KPHSS_EVENT_COPY_ARGUMENTS_FAILED; - } - - /* Copy the stack trace. */ - memcpy((PCHAR)eventBlock + eventBlock->TraceOffset, stackTrace, traceSize); - - /* Pass the pointer to the event block back. */ - *EventBlock = eventBlock; - - return STATUS_SUCCESS; -} - -/* KphpSsFreeEventBlock - * - * Frees an event block created by KphpSsCreateEventBlock. - */ -VOID KphpSsFreeEventBlock( - __in PKPHSS_EVENT_BLOCK EventBlock - ) -{ - ExFreePoolWithTag(EventBlock, TAG_EVENT_BLOCK); -} - -/* KphpSsCaptureSimpleArgument - * - * Captures a simple (1-, 2-, 4- or 8-byte) argument. - */ -NTSTATUS KphpSsCaptureSimpleArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in PVOID Argument, - __in KPHSS_ARGUMENT_TYPE Type, - __in KPROCESSOR_MODE PreviousMode - ) -{ - PKPHSS_ARGUMENT_BLOCK argumentBlock; - ULONG size; - LARGE_INTEGER value; - - /* Return if we have a NULL pointer. */ - if (!Argument) - return STATUS_INVALID_PARAMETER_2; - - /* Get the proper argument size based on the argument type. */ - switch (Type) - { - case Int8Argument: - size = sizeof(BOOLEAN); - break; - case Int16Argument: - size = sizeof(SHORT); - break; - case Int32Argument: - size = sizeof(LONG); - break; - case Int64Argument: - size = sizeof(LARGE_INTEGER); - break; - default: - return STATUS_INVALID_PARAMETER_3; - } - - /* Probe and read the value. */ - __try - { - if (PreviousMode != KernelMode) - ProbeForRead(Argument, size, 1); - - memcpy(&value, Argument, size); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return GetExceptionCode(); - } - - /* Allocate an argument block. */ - argumentBlock = KphpSsAllocateArgumentBlock(size, Type); - - if (!argumentBlock) - return STATUS_INSUFFICIENT_RESOURCES; - - /* Copy the value into the argument block. */ - memcpy(&argumentBlock->Simple, &value, size); - *ArgumentBlock = argumentBlock; - - return STATUS_SUCCESS; -} - -/* KphpSsCaptureHandleArgument - * - * Captures a handle argument. - */ -NTSTATUS KphpSsCaptureHandleArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in HANDLE Argument, - __in KPROCESSOR_MODE PreviousMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_ARGUMENT_BLOCK argumentBlock; - ULONG bufferLength; - PVOID object; - POBJECT_TYPE objectType; - PUNICODE_STRING objectTypeName; - PUNICODE_STRING objectNameInfo; - ULONG returnLength; - PKPHSS_HANDLE handleInfo; - PKPHSS_WSTRING wString; - - /* Return if we have a NULL handle. */ - if (!Argument) - return STATUS_INVALID_PARAMETER_2; - - /* Make sure the handle isn't a kernel handle if we're - * from user-mode. We need exceptions for the process - * and thread pseudo-handles. - */ - if (PreviousMode != KernelMode) - { - if ( - IsKernelHandle(Argument) && - Argument != NtCurrentProcess() && - Argument != NtCurrentThread() - ) - return STATUS_INVALID_HANDLE; - } - - /* Reference the object. */ - status = ObReferenceObjectByHandle( - Argument, - 0, - NULL, - KernelMode, - &object, - NULL - ); - - if (!NT_SUCCESS(status)) - return status; - - /* Get a pointer to the UNICODE_STRING containing the - * object type name. - */ - objectType = KphGetObjectTypeNt(object); - objectTypeName = (PUNICODE_STRING)KVOFF(objectType, OffOtName); - - /* Allocate a buffer for name information. */ - objectNameInfo = (PUNICODE_STRING)ExAllocatePoolWithTag( - PagedPool, - CAPTURE_HANDLE_BUFFER_SIZE, - TAG_CAPTURE_TEMP_BUFFER - ); - - if (!objectNameInfo) - goto CleanupObject; - - /* Query the name of the object. */ - status = KphQueryNameObject( - object, - objectNameInfo, - CAPTURE_HANDLE_BUFFER_SIZE, - &returnLength - ); - - if (!NT_SUCCESS(status)) - goto CleanupName; - - /* Allocate an argument block. */ - argumentBlock = KphpSsAllocateArgumentBlock( - sizeof(KPHSS_HANDLE) + sizeof(KPHSS_WSTRING) + sizeof(KPHSS_WSTRING) + - objectTypeName->Length + objectNameInfo->Length, - HandleArgument - ); - - if (!argumentBlock) - goto CleanupName; - - handleInfo = &argumentBlock->Handle; - /* Calculate the offsets. */ - handleInfo->TypeNameOffset = sizeof(KPHSS_HANDLE); - handleInfo->NameOffset = - handleInfo->TypeNameOffset + sizeof(KPHSS_WSTRING) + - objectTypeName->Length; - - /* Copy the object type name into the block. */ - wString = (PKPHSS_WSTRING)PTR_ADD_OFFSET(handleInfo, handleInfo->TypeNameOffset); - wString->Length = objectTypeName->Length; - memcpy(&wString->Buffer, objectTypeName->Buffer, wString->Length); - - /* Copy the object name into the block. */ - wString = (PKPHSS_WSTRING)PTR_ADD_OFFSET(handleInfo, handleInfo->NameOffset); - wString->Length = objectNameInfo->Length; - memcpy(&wString->Buffer, objectNameInfo->Buffer, wString->Length); - - /* We may be able to get additional information for the - * object. - */ - - handleInfo->ClientId.UniqueProcess = NULL; - handleInfo->ClientId.UniqueThread = NULL; - - if (objectType == *PsProcessType) - { - handleInfo->ClientId.UniqueProcess = PsGetProcessId((PEPROCESS)object); - } - else if (objectType == *PsThreadType) - { - handleInfo->ClientId.UniqueThread = PsGetThreadId((PETHREAD)object); - handleInfo->ClientId.UniqueProcess = PsGetProcessId(IoThreadToProcess((PETHREAD)object)); - } - - *ArgumentBlock = argumentBlock; - -CleanupName: - ExFreePoolWithTag(objectNameInfo, TAG_CAPTURE_TEMP_BUFFER); -CleanupObject: - ObDereferenceObject(object); - - return status; -} - -/* KphpSsCaptureUnicodeStringArgument - * - * Captures a UNICODE_STRING argument. - */ -NTSTATUS KphpSsCaptureUnicodeStringArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in PUNICODE_STRING Argument, - __in KPROCESSOR_MODE PreviousMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_ARGUMENT_BLOCK argumentBlock; - UNICODE_STRING unicodeString; - - /* Return if we have a NULL pointer. */ - if (!Argument) - return STATUS_INVALID_PARAMETER_2; - - /* Probe and copy the UNICODE_STRING structure. */ - __try - { - if (PreviousMode != KernelMode) - ProbeForRead(Argument, sizeof(UNICODE_STRING), 1); - - memcpy(&unicodeString, Argument, sizeof(UNICODE_STRING)); - - /* Probe the buffer, if present. */ - if (unicodeString.Buffer && PreviousMode != KernelMode) - { - ProbeForRead(unicodeString.Buffer, unicodeString.Length, 1); - } - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return GetExceptionCode(); - } - - /* Check if the string is too large. */ - if (unicodeString.Length > CAPTURE_UNICODE_STRING_MAX_SIZE) - return STATUS_UNSUCCESSFUL; - - /* Allocate an argument block. */ - argumentBlock = KphpSsAllocateArgumentBlock( - sizeof(KPHSS_UNICODE_STRING) + unicodeString.Length, - UnicodeStringArgument - ); - - if (!argumentBlock) - return STATUS_INSUFFICIENT_RESOURCES; - - /* Copy the string into the argument block. */ - argumentBlock->UnicodeString.Length = unicodeString.Length; - argumentBlock->UnicodeString.MaximumLength = unicodeString.MaximumLength; - argumentBlock->UnicodeString.Pointer = unicodeString.Buffer; - - if (unicodeString.Buffer) - { - __try - { - memcpy(argumentBlock->UnicodeString.Buffer, unicodeString.Buffer, unicodeString.Length); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - KphpSsFreeArgumentBlock(argumentBlock); - return GetExceptionCode(); - } - } - - *ArgumentBlock = argumentBlock; - - return status; -} - -/* KphpSsCaptureObjectAttributesArgument - * - * Captures an OBJECT_ATTRIBUTES argument. - */ -NTSTATUS KphpSsCaptureObjectAttributesArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in POBJECT_ATTRIBUTES Argument, - __in KPROCESSOR_MODE PreviousMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_ARGUMENT_BLOCK argumentBlock; - OBJECT_ATTRIBUTES objectAttributes; - PKPHSS_ARGUMENT_BLOCK rootDirectoryArgumentBlock = NULL; - ULONG rootDirectoryArgumentBlockSize = 0; - PKPHSS_ARGUMENT_BLOCK objectNameArgumentBlock = NULL; - ULONG objectNameArgumentBlockSize = 0; - - /* Return if we have a NULL pointer. */ - if (!Argument) - return STATUS_INVALID_PARAMETER_2; - - /* Probe and copy the OBJECT_ATTRIBUTES structure. */ - __try - { - if (PreviousMode != KernelMode) - ProbeForRead(Argument, sizeof(OBJECT_ATTRIBUTES), 1); - - memcpy(&objectAttributes, Argument, sizeof(OBJECT_ATTRIBUTES)); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return GetExceptionCode(); - } - - /* If we have a root directory, create an argument block from it - * and copy it to our argument block. - */ - if (objectAttributes.RootDirectory) - { - status = KphpSsCaptureHandleArgument( - &rootDirectoryArgumentBlock, - objectAttributes.RootDirectory, - PreviousMode - ); - - /* If we created the argument block, we need to calculate - * the size of the KPHSS_HANDLE structure. - */ - if (NT_SUCCESS(status)) - { - rootDirectoryArgumentBlockSize = - rootDirectoryArgumentBlock->Header.Size - KPHSS_ARGUMENT_BLOCK_OVERHEAD; - } - else - { - rootDirectoryArgumentBlock = NULL; - } - } - - /* If we have a object name, create an argument block from it and - * copy it to our argument block. - */ - if (objectAttributes.ObjectName) - { - status = KphpSsCaptureUnicodeStringArgument( - &objectNameArgumentBlock, - objectAttributes.ObjectName, - PreviousMode - ); - - /* If we created the argument block, we need to calculate - * the size of the KPHSS_UNICODE_STRING structure. - */ - if (NT_SUCCESS(status)) - { - objectNameArgumentBlockSize = - objectNameArgumentBlock->Header.Size - KPHSS_ARGUMENT_BLOCK_OVERHEAD; - } - else - { - objectNameArgumentBlock = NULL; - } - } - - /* Allocate an argument block. */ - argumentBlock = KphpSsAllocateArgumentBlock( - sizeof(KPHSS_OBJECT_ATTRIBUTES) + rootDirectoryArgumentBlockSize + objectNameArgumentBlockSize, - ObjectAttributesArgument - ); - - argumentBlock->ObjectAttributes.RootDirectoryOffset = 0; - argumentBlock->ObjectAttributes.ObjectNameOffset = 0; - - /* Copy the object attributes fields. */ - memcpy( - &argumentBlock->ObjectAttributes.ObjectAttributes, - &objectAttributes, - sizeof(OBJECT_ATTRIBUTES) - ); - - /* Copy the root directory structure, if we have one. */ - if (rootDirectoryArgumentBlock) - { - ULONG rootDirectoryOffset; - - /* It will go directly after the KPHSS_OBJECT_ATTRIBUTES structure. */ - rootDirectoryOffset = sizeof(KPHSS_OBJECT_ATTRIBUTES); - argumentBlock->ObjectAttributes.RootDirectoryOffset = (USHORT)rootDirectoryOffset; - /* Copy it. */ - memcpy( - PTR_ADD_OFFSET(&argumentBlock->ObjectAttributes, rootDirectoryOffset), - &rootDirectoryArgumentBlock->Handle, - rootDirectoryArgumentBlockSize - ); - /* Free the block. */ - KphpSsFreeArgumentBlock(rootDirectoryArgumentBlock); - } - - /* Copy the object name structure, if we have one. */ - if (objectNameArgumentBlock) - { - ULONG objectNameOffset; - - /* We'll place the structure after the root directory structure, - * if present. - */ - objectNameOffset = sizeof(KPHSS_OBJECT_ATTRIBUTES) + rootDirectoryArgumentBlockSize; - - /* Make sure the offset isn't too large. */ - if (objectNameOffset <= MAX_USHORT) - { - argumentBlock->ObjectAttributes.ObjectNameOffset = (USHORT)objectNameOffset; - /* Copy it. */ - memcpy( - PTR_ADD_OFFSET(&argumentBlock->ObjectAttributes, objectNameOffset), - &objectNameArgumentBlock->UnicodeString, - objectNameArgumentBlockSize - ); - } - - /* Free the block. */ - KphpSsFreeArgumentBlock(objectNameArgumentBlock); - } - - *ArgumentBlock = argumentBlock; - - return status; -} - -/* KphpSsCaptureClientIdArgument - * - * Captures a CLIENT_ID argument. - */ -NTSTATUS KphpSsCaptureClientIdArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in PCLIENT_ID Argument, - __in KPROCESSOR_MODE PreviousMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - CLIENT_ID clientId; - PKPHSS_ARGUMENT_BLOCK argumentBlock; - - /* Check if we have a NULL pointer. */ - if (!Argument) - return STATUS_INVALID_PARAMETER_2; - - /* Probe and copy the CLIENT_ID structure. */ - __try - { - if (PreviousMode != KernelMode) - ProbeForRead(Argument, sizeof(CLIENT_ID), 1); - - memcpy(&clientId, Argument, sizeof(CLIENT_ID)); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return GetExceptionCode(); - } - - /* Allocate an argument block. */ - argumentBlock = KphpSsAllocateArgumentBlock( - sizeof(CLIENT_ID), - ClientIdArgument - ); - - if (!argumentBlock) - return STATUS_INSUFFICIENT_RESOURCES; - - /* Fill in the argument block. */ - memcpy(&argumentBlock->ClientId, &clientId, sizeof(CLIENT_ID)); - - *ArgumentBlock = argumentBlock; - - return status; -} - -/* KphpSsCaptureBytesArgument - * - * Captures a binary blob as an argument. - */ -NTSTATUS KphpSsCaptureBytesArgument( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in PVOID Argument, - __in ULONG Length, - __in KPROCESSOR_MODE PreviousMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_ARGUMENT_BLOCK argumentBlock; - - /* Check if we have a NULL pointer. */ - if (!Argument) - return STATUS_INVALID_PARAMETER_2; - - /* Make sure the length isn't too big. */ - if (Length > CAPTURE_BYTES_MAX_SIZE) - return STATUS_INVALID_PARAMETER_3; - - /* Probe the bytes. */ - __try - { - if (PreviousMode != KernelMode) - ProbeForRead(Argument, Length, 1); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return GetExceptionCode(); - } - - /* Allocate an argument block. */ - argumentBlock = KphpSsAllocateArgumentBlock( - sizeof(KPHSS_BYTES) + Length, - BytesArgument - ); - - if (!argumentBlock) - return STATUS_INSUFFICIENT_RESOURCES; - - /* Copy the bytes. */ - __try - { - memcpy(argumentBlock->Bytes.Buffer, Argument, Length); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - KphpSsFreeArgumentBlock(argumentBlock); - return GetExceptionCode(); - } - - argumentBlock->Bytes.Length = (USHORT)Length; - - *ArgumentBlock = argumentBlock; - - return status; -} - -/* KphpSsCreateArgumentBlock - * - * Allocates and initializes an argument block. - */ -NTSTATUS KphpSsCreateArgumentBlock( - __out PKPHSS_ARGUMENT_BLOCK *ArgumentBlock, - __in ULONG Number, - __in ULONG Argument, - __in ULONG Index, - __in_opt KPHSS_ARGUMENT_TYPE Type, - __in_opt PVOID Context - ) -{ -#ifdef _X86_ - NTSTATUS status = STATUS_SUCCESS; - PKPHSS_ARGUMENT_BLOCK argumentBlock; - KPROCESSOR_MODE previousMode; - PKPHSS_CALL_ENTRY callEntry; - KPHSS_ARGUMENT_TYPE argumentType; - - previousMode = ExGetPreviousMode(); - - /* Get a pointer to the call entry for the system service. - * If we don't have one, we can't proceed. - */ - callEntry = KphSsLookupCallEntry(Number); - - if (!callEntry) - return STATUS_INVALID_PARAMETER_2; - - /* Validate the argument index. */ - if (Index >= callEntry->NumberOfArguments) - return STATUS_INVALID_PARAMETER_3; - - if (Type != 0) - argumentType = Type; - else - argumentType = callEntry->Arguments[Index]; - - /* Is this a normal argument? If so, there's no point - * creating an argument block since the data is already - * in the event block. - */ - if (argumentType == NormalArgument) - return STATUS_UNSUCCESSFUL; - - /* Capture the argument. */ - - switch (argumentType) - { - case Int8Argument: - case Int16Argument: - case Int32Argument: - case Int64Argument: - status = KphpSsCaptureSimpleArgument( - &argumentBlock, - (PVOID)Argument, - argumentType, - previousMode - ); - break; - case HandleArgument: - status = KphpSsCaptureHandleArgument( - &argumentBlock, - (HANDLE)Argument, - previousMode - ); - break; - case UnicodeStringArgument: - status = KphpSsCaptureUnicodeStringArgument( - &argumentBlock, - (PUNICODE_STRING)Argument, - previousMode - ); - break; - case ObjectAttributesArgument: - status = KphpSsCaptureObjectAttributesArgument( - &argumentBlock, - (POBJECT_ATTRIBUTES)Argument, - previousMode - ); - break; - case ClientIdArgument: - status = KphpSsCaptureClientIdArgument( - &argumentBlock, - (PCLIENT_ID)Argument, - previousMode - ); - break; - case BytesArgument: - status = KphpSsCaptureBytesArgument( - &argumentBlock, - (PVOID)Argument, - (ULONG)Context, - previousMode - ); - break; - default: - status = STATUS_NOT_IMPLEMENTED; - break; - } - - if (!NT_SUCCESS(status)) - return status; - - /* Put the index in. */ - argumentBlock->Index = (UCHAR)Index; - - *ArgumentBlock = argumentBlock; - - return status; -#else - return STATUS_NOT_SUPPORTED; -#endif -} - -/* KphpSsAllocateArgumentBlock - * - * Allocates an argument block and initializes some fields. - */ -PKPHSS_ARGUMENT_BLOCK KphpSsAllocateArgumentBlock( - __in ULONG InnerSize, - __in KPHSS_ARGUMENT_TYPE Type - ) -{ - PKPHSS_ARGUMENT_BLOCK argumentBlock; - ULONG size; - - size = KPHSS_ARGUMENT_BLOCK_SIZE(InnerSize); - - /* Make sure the size isn't too large. */ - if (size > MAX_USHORT) - return NULL; - - argumentBlock = ExAllocatePoolWithTag( - PagedPool, - size, - TAG_ARGUMENT_BLOCK - ); - - if (!argumentBlock) - return NULL; - - argumentBlock->Header.Type = ArgumentBlockType; - argumentBlock->Header.Size = (USHORT)size; - argumentBlock->Type = Type; - - return argumentBlock; -} - -/* KphpSsFreeArgumentBlock - * - * Frees an argument block created by KphpSsCreateArgumentBlock. - */ -VOID KphpSsFreeArgumentBlock( - __in PKPHSS_ARGUMENT_BLOCK ArgumentBlock - ) -{ - ExFreePoolWithTag(ArgumentBlock, TAG_ARGUMENT_BLOCK); -} - -/* KphpSsWriteBlock - * - * Writes a block into client memory. - */ -NTSTATUS KphpSsWriteBlock( - __in PKPHSS_CLIENT_ENTRY ClientEntry, - __in_opt PKPHSS_BLOCK_HEADER Block, - __in KPHSS_SEQUENCE_MODE SequenceMode - ) -{ - NTSTATUS status = STATUS_SUCCESS; - LARGE_INTEGER zeroTimeout; - KPH_ATTACH_STATE attachState; - ULONG availableSpace; - HANDLE dupHandleInClient = NULL; - - zeroTimeout.QuadPart = 0; - - /* Take care of the sequence mode. If it isn't - * NoSequence, it is effectively a way for the caller - * to control the buffer mutex. - */ - if (SequenceMode == StartSequence) - { - ExAcquireFastMutex(&ClientEntry->BufferMutex); - return STATUS_SUCCESS; - } - else if (SequenceMode == EndSequence) - { - ExReleaseFastMutex(&ClientEntry->BufferMutex); - return STATUS_SUCCESS; - } - else - { - /* If we aren't manipulating the mutex, we need - * a block to write. - */ - if (!Block) - return STATUS_INVALID_PARAMETER_2; - - /* If we're in a sequence, don't acquire the mutex - * because the caller would have acquired it using - * StartSequence already. - */ - if (SequenceMode != InSequence) - ExAcquireFastMutex(&ClientEntry->BufferMutex); - } - - /* Try to acquire the write semaphore. If we can't acquire - * it immediately, drop the block. - */ - status = KeWaitForSingleObject( - ClientEntry->WriteSemaphore, - Executive, - KernelMode, - FALSE, - &zeroTimeout - ); - - if (!KPHSS_BLOCK_SUCCESS(status)) - { - if (status == STATUS_TIMEOUT) - { - dprintf("Ss: WARNING: Dropped block (server %#x).\n", ClientEntry->BufferCursor); - ClientEntry->NumberOfBlocksDropped++; - } - - goto CleanupBufferMutex; - } - - availableSpace = ClientEntry->BufferSize - ClientEntry->BufferCursor; - - /* Blocks are recorded in a circular buffer. - * In the case that there is not enough space for an entire block, - * we will record a reset block that tells the client to reset - * its read cursor to 0. In the case that there is not enough - * space for a block header, it is implied that the client will - * reset its read cursor. - */ - - /* Check if we have enough space for a block header. */ - if (availableSpace < sizeof(KPHSS_BLOCK_HEADER)) - { - /* Not enough space. Reset the cursor. */ - dprintf("Ss: Implicit cursor reset (server %#x).\n", ClientEntry->BufferCursor); - ClientEntry->BufferCursor = 0; - availableSpace = ClientEntry->BufferSize; - } - /* Check if we have enough space for the block. */ - else if (availableSpace < Block->Size) - { - KPHSS_RESET_BLOCK resetBlock; - - /* Not enough space for the block, but enough space - * for a reset block. Write the reset block and reset - * the cursor. - */ - resetBlock.Header.Size = sizeof(KPHSS_RESET_BLOCK); - resetBlock.Header.Type = ResetBlockType; - - /* Attach to the client process and copy the block. */ - KphAttachProcess(ClientEntry->Process, &attachState); - - __try - { - memcpy( - PTR_ADD_OFFSET(ClientEntry->BufferBase, ClientEntry->BufferCursor), - &resetBlock, - resetBlock.Header.Size - ); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - KphDetachProcess(&attachState); - status = GetExceptionCode(); - goto CleanupBufferMutex; - } - - dprintf("Ss: Wrote reset block (server %#x).\n", ClientEntry->BufferCursor); - KphDetachProcess(&attachState); - ClientEntry->BufferCursor = 0; - availableSpace = ClientEntry->BufferSize; - } - - /* Now that we have dealt with any end-of-buffer issues, - * we still have to check if we have enough space for the - * event. We may have a huge event or the client may have a - * tiny buffer. - */ - if (availableSpace < Block->Size) - { - dfprintf("Ss: WARNING: Insufficient buffer size (server %#x).\n", ClientEntry->BufferCursor); - status = STATUS_BUFFER_TOO_SMALL; - goto CleanupBufferMutex; - } - - /* Time to copy the block into the buffer. - */ - KphAttachProcess(ClientEntry->Process, &attachState); - - __try - { - memcpy( - PTR_ADD_OFFSET(ClientEntry->BufferBase, ClientEntry->BufferCursor), - Block, - Block->Size - ); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - dfprintf("Ss: ERROR: Could not write to the client buffer (server %#x)!\n", ClientEntry->BufferCursor); - KphDetachProcess(&attachState); - status = GetExceptionCode(); - goto CleanupBufferMutex; - } - - KphDetachProcess(&attachState); - - /* Now that we have succesfully copied the block, we need to - * release the read semaphore to notify to the client that they have - * a block to read. We also need to advance our cursor. - */ - - /* May cause an exception (STATUS_SEMAPHORE_LIMIT_EXCEEDED). */ - __try - { - KeReleaseSemaphore(ClientEntry->ReadSemaphore, 2, 1, FALSE); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - dfprintf("Ss: ERROR: Could not release read semaphore (server %#x)!\n", ClientEntry->BufferCursor); - status = GetExceptionCode(); - goto CleanupBufferMutex; - } - - ClientEntry->BufferCursor += Block->Size; - ClientEntry->NumberOfBlocksWritten++; - - dprintf("Ss: Wrote block (server %#x).\n", ClientEntry->BufferCursor); - -CleanupBufferMutex: - if (SequenceMode != InSequence) - ExReleaseFastMutex(&ClientEntry->BufferMutex); - - return status; -} - -/* KphpSsLogSystemServiceCall - * - * Logs a system service. - * - * WARNING: This function CANNOT make any system calls. - * - * IRQL: <= APC_LEVEL - */ -VOID NTAPI KphpSsLogSystemServiceCall( - __in ULONG Number, - __in ULONG *Arguments, - __in ULONG NumberOfArguments, - __in PKSERVICE_TABLE_DESCRIPTOR ServiceTable, - __in PKTHREAD Thread - ) -{ -#ifdef _X86_ - NTSTATUS status = STATUS_SUCCESS; - KPROCESSOR_MODE previousMode; - PLIST_ENTRY currentListEntry; - PKPHSS_RULESET_ENTRY ruleSetEntryArray[KPHSS_RULESET_ENTRY_LIMIT]; - ULONG ruleSetEntryCount; - PKPHSS_EVENT_BLOCK eventBlock; - PKPHSS_ARGUMENT_BLOCK argumentBlockArray[KPHSS_MAXIMUM_ARGUMENT_BLOCKS]; - ULONG i, j; - - previousMode = ExGetPreviousMode(); - /* Ignore the Thread argument. Replace it with our own. */ - Thread = KeGetCurrentThread(); - - /* First, some checks. - * * We can't operate at IRQL > APC_LEVEL because - * of restrictions on logging. - * * We can't operate on unknown service tables like the - * shadow service table (yet). - * * We have to make sure we aren't attempting to log - * a call to ZwContinue because we caused an exception - * last time we were logging something. This will cause - * a deadlock! - */ - - if (KeGetCurrentIrql() > APC_LEVEL) - return; - if ( - ServiceTable->Base != __KeServiceDescriptorTable->Base || - ServiceTable->Number != __KeServiceDescriptorTable->Number || - ServiceTable->Limit != __KeServiceDescriptorTable->Limit - ) - return; - - /* Make sure we aren't logging ZwContinue if it's because - * we caused an exception somewhere. */ - if ( - ServiceTable->Base == __KeServiceDescriptorTable->Base && - Number == SsNtContinue && - NumberOfArguments == 2 && - previousMode == KernelMode - ) - { - /* "Reverse probe" the arguments. */ - if ( - (ULONG_PTR)Arguments > (ULONG_PTR)MmHighestUserAddress && - Arguments[0] > (ULONG_PTR)MmHighestUserAddress - ) - { - CONTEXT context; - - /* The first argument contains the context. */ - memcpy(&context, (PCONTEXT)Arguments[0], sizeof(CONTEXT)); - /* Check if the context Eip points into the KPH module. - * If so, abort the logging. - */ - if ( - context.Eip >= (ULONG_PTR)KphDriverObject->DriverStart && - context.Eip < (ULONG_PTR)KphDriverObject->DriverStart + KphDriverObject->DriverSize - ) - return; - } - } - - /* Build the ruleset entry array by going through the ruleset - * list, referencing each relevant one and copying them into - * the local array. This we way don't hold the lock for too - * long. - */ - - KeEnterCriticalRegion(); - ExAcquirePushLockShared(&KphSsRuleSetListPushLock); - - currentListEntry = KphSsRuleSetListHead.Flink; - ruleSetEntryCount = 0; - - while ( - currentListEntry != &KphSsRuleSetListHead && - ruleSetEntryCount < KPHSS_RULESET_ENTRY_LIMIT - ) - { - PKPHSS_RULESET_ENTRY ruleSetEntry = KPHSS_RULESET_ENTRY(currentListEntry); - - if (KphpSsMatchRuleSetEntry( - ruleSetEntry, - Number, - Arguments, - NumberOfArguments, - ServiceTable, - Thread, - previousMode - )) - { - /* Reference and store the ruleset entry in the local array. */ - if (KphReferenceObjectSafe(ruleSetEntry)) - { - /* Make sure the client is enabled. */ - if (ruleSetEntry->Client->Enabled) - { - ruleSetEntryArray[ruleSetEntryCount] = ruleSetEntry; - ruleSetEntryCount++; - } - else - { - /* We need to use defer delete here because we hold the - * ruleset list lock. - */ - KphDereferenceObjectDeferDelete(ruleSetEntry); - } - } - } - - currentListEntry = currentListEntry->Flink; - } - - ExReleasePushLock(&KphSsRuleSetListPushLock); - KeLeaveCriticalRegion(); - - /* If we didn't find any ruleset entries, don't bother creating the - * event block. - */ - if (ruleSetEntryCount == 0) - return; - - /* We have work to do. Create an event block first. */ - if (!NT_SUCCESS(KphpSsCreateEventBlock( - &eventBlock, - Thread, - Number, - Arguments, - NumberOfArguments - ))) - { - dfprintf("Ss: ERROR: Unable to create an event block!\n"); - return; - } - - memset(argumentBlockArray, 0, sizeof(argumentBlockArray)); - - /* Process specific argument blocks. */ - KphpSsProcessSpecificArguments( - argumentBlockArray, - Number, - Arguments, - NumberOfArguments, - previousMode - ); - - /* Create the (generic) argument blocks. If we fail to create one, - * set the array entry to NULL and we'll skip it later. - */ - - for (i = 0; i < NumberOfArguments && i < KPHSS_MAXIMUM_ARGUMENT_BLOCKS; i++) - { - ULONG argument; - - /* If we already have a specific argument block already, skip this one. */ - if (argumentBlockArray[i]) - continue; - - __try - { - /* We'll assume the arguments have already been probed - * since we created the event block successfully. - */ - argument = Arguments[i]; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - /* Silently skip this argument. Even though it is 99% likely - * that we will fail to read the next argument, continue - * anyway. - */ - argumentBlockArray[i] = NULL; - continue; - } - - status = KphpSsCreateArgumentBlock( - &argumentBlockArray[i], - Number, - argument, - i, - 0, - NULL - ); - - if (!NT_SUCCESS(status)) - argumentBlockArray[i] = NULL; - } - - /* Go through the ruleset entry array and write the blocks to each - * client. While we're doing that we can also dereference each - * ruleset entry. - */ - for (i = 0; i < ruleSetEntryCount; i++) - { - /* Begin a sequence. */ - status = KphpSsWriteBlock(ruleSetEntryArray[i]->Client, NULL, StartSequence); - - if (NT_SUCCESS(status)) - { - /* Write the event block. */ - KphpSsWriteBlock(ruleSetEntryArray[i]->Client, &eventBlock->Header, InSequence); - - /* Write the argument blocks. */ - for (j = 0; j < NumberOfArguments && j < KPHSS_MAXIMUM_ARGUMENT_BLOCKS; j++) - { - if (argumentBlockArray[j]) - { - KphpSsWriteBlock(ruleSetEntryArray[i]->Client, &argumentBlockArray[j]->Header, InSequence); - } - } - - /* End the sequence. */ - KphpSsWriteBlock(ruleSetEntryArray[i]->Client, NULL, EndSequence); - } - - KphDereferenceObject(ruleSetEntryArray[i]); - } - - /* Free the event block. */ - KphpSsFreeEventBlock(eventBlock); - - /* Free the argument blocks. */ - for (i = 0; i < NumberOfArguments && i < KPHSS_MAXIMUM_ARGUMENT_BLOCKS; i++) - { - if (argumentBlockArray[i]) - KphpSsFreeArgumentBlock(argumentBlockArray[i]); - } -#else - KeBugCheck(STATUS_NOT_SUPPORTED); -#endif -} - -#ifdef _X86_ - -/* KphpSsNewKiFastCallEntry - * - * The hook function called from within the hooked KiFastCallEntry. - */ -__declspec(naked) VOID NTAPI KphpSsNewKiFastCallEntry() -{ - /* KiFastCallEntry handles system service calls. User-mode applications - * will perform system calls like this: - * - * Nt*: - * mov eax, SystemServiceNumber - * mov edx, 0x7ffe0300 <-- at 0x7ffe0300 we have a pointer to KiFastSystemCall - * call [edx] - * ret - * - * At KiFastSystemCall: - * mov edx, esp - * sysenter - */ - /* This means that in KiFastCallEntry, eax will contain the system service - * number while edx will contain a pointer to the arguments for the system - * service. KiFastCallEntry will fill in edi with the service table, and - * esi will contain the caller KTHREAD. - * - * We cannot hook KiFastCallEntry from the beginning because it starts on the DPC - * stack. KiFastCallEntry switches to the proper thread stack, and we want to - * hook it just after it switches to the stack. That way we can avoid having to - * manually switch the thread stack ourselves. - * - * At this point: - * * eax contains the system service number. - * * edx contains a pointer to the user-supplied arguments for - * the system service. - * * edi contains a pointer to the service table associated with - * the system service number. - * * esi contains a pointer to the KTHREAD of the caller. - */ - /* Some context: - * - * push edx - * push eax - * call [_KeGdiFlushUserBatch] - * pop eax - * pop edx - * inc dword ptr fs:[PbSystemCalls] <-- this gets overwritten with a jmp to here - * mov edi, edx - * mov ebx, [edi+...] - * ... - */ - __asm - { - /* Save all registers first. */ - push ebp - push edi - push esi - push edx - push ecx - push ebx - push eax - - /* Since we overwrite the inc instruction when we did the hook, - * perform the job now - we have to increment the system calls - * counter. - */ - lea ebx, KphSsKiFastCallEntryHook /* get a pointer to the hook structure */ - mov ebx, dword ptr [ebx+KPH_HOOK.Bytes+3] /* get the PbSystemCalls offset from the original inc instruction */ - inc dword ptr fs:[ebx] /* increment PbSystemCalls in the PRCB */ - - /* Get the number of arguments for this system service. */ - mov ebx, dword ptr [edi+KSERVICE_TABLE_DESCRIPTOR.Number] /* ebx = a pointer to the argument table */ - xor ecx, ecx - mov cl, [ebx+eax] /* ecx = size of the arguments, in bytes. */ - shr ecx, 2 /* divide by 2 to get the number of arguments (all ULONGs) */ - - /* Call the KiFastCallEntry proc while maintaining the logger count - * so that the driver doesn't get unloaded while we're executing. - */ - push esi /* Thread */ - push edi /* ServiceTable */ - push ecx /* NumberOfArguments */ - push edx /* Arguments */ - push eax /* Number */ - lock inc dword ptr KphSsNumberOfActiveLoggers - call KphpSsLogSystemServiceCall - lock dec dword ptr KphSsNumberOfActiveLoggers - - /* Restore the registers and resume execution in KiFastCallEntry. */ - pop eax - pop ebx - pop ecx - pop edx - pop esi - pop edi - pop ebp - - /* Luckily, KiFastCallEntry will overwrite ebx when we jump back, so it's safe to use it. */ - lea ebx, __KiFastCallEntry - mov ebx, [ebx] /* ebx = KiFastCallEntry at the inc instruction */ - add ebx, 7 /* skip the inc instruction */ - jmp ebx /* jump back */ - } -} - -#else - -VOID NTAPI KphpSsNewKiFastCallEntry() -{ - KeBugCheck(STATUS_NOT_SUPPORTED); -} - -#endif diff --git a/2.x/trunk/KProcessHacker/sysservicedata.c b/2.x/trunk/KProcessHacker/sysservicedata.c deleted file mode 100644 index c30c36917..000000000 --- a/2.x/trunk/KProcessHacker/sysservicedata.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Process Hacker Driver - - * system service logging (data) - * - * Copyright (C) 2009 wj32 - * - * This file is part of Process Hacker. - * - * Process Hacker is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Process Hacker is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Process Hacker. If not, see . - */ - -#define _SYSSERVICEDATA_PRIVATE -#include "include/sysservicedata.h" - -PVOID KphpSsCallEntryAllocateRoutine( - __in PRTL_GENERIC_TABLE Table, - __in CLONG ByteSize - ); - -RTL_GENERIC_COMPARE_RESULTS KphpSsCallEntryCompareRoutine( - __in PRTL_GENERIC_TABLE Table, - __in PVOID FirstStruct, - __in PVOID SecondStruct - ); - -VOID KphpSsCallEntryFreeRoutine( - __in PRTL_GENERIC_TABLE Table, - __in PVOID Buffer - ); - -KPHSS_CALL_ENTRY SsEntries[] = -{ - /* NTSTATUS NtAddAtom(PWSTR String, ULONG StringLength, PUSHORT Atom) */ - { &SsNtAddAtom, "NtAddAtom", 3, { WStringArgument, 0, Int16Argument } }, - /* NTSTATUS NtAlertResumeThread(HANDLE ThreadHandle, PULONG PreviousSuspendCount) */ - { &SsNtAlertResumeThread, "NtAlertResumeThread", 2, { HandleArgument, 0 } }, - /* NTSTATUS NtAlertThread(HANDLE ThreadHandle) */ - { &SsNtAlertThread, "NtAlertThread", 1, { HandleArgument } }, - /* NTSTATUS NtAllocateLocallyUniqueId(PLUID Luid) */ - { &SsNtAllocateLocallyUniqueId, "NtAllocateLocallyUniqueId", 1, { 0 } }, - /* NTSTATUS NtAllocateUserPhysicalPages(HANDLE ProcessHandle, PULONG NumberOfPages, PULONG PageFrameNumbers) */ - { &SsNtAllocateUserPhysicalPages, "NtAllocateUserPhysicalPages", 3, { HandleArgument, Int32Argument, 0 } }, - /* NTSTATUS NtAllocateUuids(PLARGE_INTEGER UuidLastTimeAllocated, PULONG UuidDeltaTime, PULONG UuidSequenceNumber, - * PUCHAR UuidSeed) */ - { &SsNtAllocateUuids, "NtAllocateUuids", 4, { Int64Argument, 0, 0, 0 } }, - /* NTSTATUS NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG ZeroBits, - * PULONG AllocationSize, ULONG AllocationType, ULONG Protect) */ - { &SsNtAllocateVirtualMemory, "NtAllocateVirtualMemory", 6, { HandleArgument, Int32Argument, 0, Int32Argument, 0, 0 } }, - /* NTSTATUS NtApphelpCacheControl(APPHELPCACHECONTROL ApphelpCacheControl, PUNICODE_STRING ApphelpCacheObject) */ - { &SsNtApphelpCacheControl, "NtApphelpCacheControl", 2, { 0, UnicodeStringArgument } }, - /* NTSTATUS NtAreMappedFilesTheSame(PVOID Address1, PVOID Address2) */ - { &SsNtAreMappedFilesTheSame, "NtAreMappedFilesTheSame", 2, { 0, 0 } }, - /* NTSTATUS NtAssignProcessToJobObject(HANDLE JobHandle, HANDLE ProcessHandle) */ - { &SsNtAssignProcessToJobObject, "NtAssignProcessToJobObject", 2, { HandleArgument, HandleArgument } }, - /* NTSTATUS NtCallbackReturn(PVOID Result, ULONG ResultLength, NTSTATUS Status) */ - { &SsNtCallbackReturn, "NtCallbackReturn", 3, { 0, 0, 0 } }, - /* NTSTATUS NtCancelDeviceWakeupRequest(HANDLE DeviceHandle) */ - { &SsNtCancelDeviceWakeupRequest, "NtCancelDeviceWakeupRequest", 1, { HandleArgument } }, - /* NTSTATUS NtCancelIoFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock) */ - { &SsNtCancelIoFile, "NtCancelIoFile", 2, { HandleArgument, 0 } }, - /* NTSTATUS NtCancelTimer(HANDLE TimerHandle, PBOOLEAN CurrentState) */ - { &SsNtCancelTimer, "NtCancelTimer", 2, { HandleArgument, 0 } }, - /* NTSTATUS NtClearEvent(HANDLE EventHandle) */ - { &SsNtClearEvent, "NtClearEvent", 1, { HandleArgument } }, - /* NTSTATUS NtClose(HANDLE Handle) */ - { &SsNtClose, "NtClose", 1, { HandleArgument } }, - /* NTSTATUS NtContinue(PCONTEXT Context, BOOLEAN TestAlert) */ - { &SsNtContinue, "NtContinue", 2, { ContextArgument, 0 } }, - /* NTSTATUS NtCreateDebugObject(PHANDLE DebugObjectHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * ULONG Flags) */ - { &SsNtCreateDebugObject, "NtCreateDebugObject", 4, { 0, 0, ObjectAttributesArgument, 0 } }, - /* NTSTATUS NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtCreateDirectoryObject, "NtCreateDirectoryObject", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtCreateEvent(PHANDLE EventHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * EVENT_TYPE EventType, BOOLEAN InitialState) */ - { &SsNtCreateEvent, "NtCreateEvent", 5, { 0, 0, ObjectAttributesArgument, 0, 0 } }, - /* NTSTATUS NtCreateEventPair(PHANDLE EventPairHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtCreateEventPair, "NtCreateEventPair", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, - * ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, - * PVOID EaBuffer, ULONG EaLength) */ - { &SsNtCreateFile, "NtCreateFile", 11, { 0, 0, ObjectAttributesArgument, 0, Int64Argument, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtCreateIoCompletion(PHANDLE IoCompletionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * ULONG NumberOfConcurrentThreads) */ - { &SsNtCreateIoCompletion, "NtCreateIoCompletion", 4, { 0, 0, ObjectAttributesArgument, 0 } }, - /* NTSTATUS NtCreateJobObject(PHANDLE JobHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtCreateJobObject, "NtCreateJobObject", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtCreateJobSet(ULONG NumJob, IN PJOB_SET_ARRAY UserJobSet, IN ULONG Flags) */ - { &SsNtCreateJobSet, "NtCreateJobSet", 3, { 0, 0, 0 } }, - /* NTSTATUS NtCreateKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * ULONG TitleIndex, PUNICODE_STRING Class, ULONG CreateOptions, - * PULONG Disposition) */ - { &SsNtCreateKey, "NtCreateKey", 7, { 0, 0, ObjectAttributesArgument, 0, UnicodeStringArgument, 0, 0 } }, - /* NTSTATUS NtCreateKeyedEvent(PHANDLE KeyedEventHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * ULONG Flags) */ - { &SsNtCreateKeyedEvent, "NtCreateKeyedEvent", 4, { 0, 0, ObjectAttributesArgument, 0 } }, - /* NTSTATUS NtCreateMailslotFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PIO_STATUS_BLOCK IoStatusBlock, ULONG CreateOptions, ULONG MailslotQuota, - * ULONG MaximumMessageSize, PLARGE_INTEGER ReadTimeout) */ - { &SsNtCreateMailslotFile, "NtCreateMailslotFile", 8, { 0, 0, ObjectAttributesArgument, 0, 0, 0, 0, Int64Argument } }, - /* NTSTATUS NtCreateMutant(PHANDLE MutantHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * BOOLEAN InitialOwner) */ - { &SsNtCreateMutant, "NtCreateMutant", 4, { 0, 0, ObjectAttributesArgument, 0 } }, - /* NTSTATUS NtCreateNamedPipeFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG CreateDisposition, - * ULONG CreateOptions, BOOLEAN TypeMessage, BOOLEAN ReadmodeMessage, - * BOOLEAN Nonblocking, ULONG MaxInstances, ULONG InBufferSize, - * ULONG OutBufferSize, PLARGE_INTEGER DefaultTimeout) */ - { &SsNtCreateNamedPipeFile, "NtCreateNamedPipeFile", 14, { 0, 0, ObjectAttributesArgument, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Int64Argument } }, - /* NTSTATUS NtCreatePagingFile(PUNICODE_STRING FileName, PULARGE_INTEGER MinimumSize, PULARGE_INTEGER MaximumSize, - * ULONG Priority) */ - { &SsNtCreatePagingFile, "NtCreatePagingFile", 4, { UnicodeStringArgument, Int64Argument, Int64Argument, 0 } }, - /* NTSTATUS NtCreatePort(PHANDLE PortHandle, POBJECT_ATTRIBUTES ObjectAttributes, ULONG MaxConnectionInfoLength, - * ULONG MaxMessageLength, ULONG MaxPoolUsage) */ - { &SsNtCreatePort, "NtCreatePort", 5, { 0, ObjectAttributesArgument, 0, 0, 0 } }, - /* NTSTATUS NtCreatePrivateNamespace(PHANDLE PrivateNamespaceHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PBOUNDARY_DESCRIPTOR BoundaryDescriptor) */ - { &SsNtCreatePrivateNamespace, "NtCreatePrivateNamespace", 4, { 0, 0, ObjectAttributesArgument, 0 } }, - /* NTSTATUS NtCreateProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * HANDLE InheritFromProcessHandle, BOOLEAN InheritHandles, HANDLE SectionHandle, - * HANDLE DebugPort, HANDLE ExceptionPort) */ - { &SsNtCreateProcess, "NtCreateProcess", 8, { 0, 0, ObjectAttributesArgument, HandleArgument, 0, HandleArgument, HandleArgument, HandleArgument } }, - /* NTSTATUS NtCreateProcessEx(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * HANDLE ParentProcess, ULONG Flags, HANDLE SectionHandle, - * HANDLE DebugPort, HANDLE ExceptionPort, ULONG JobMemberLevel */ - { &SsNtCreateProcessEx, "NtCreateProcessEx", 9, { 0, 0, ObjectAttributesArgument, HandleArgument, 0, HandleArgument, HandleArgument, HandleArgument, 0 } }, - /* NTSTATUS NtCreateProfile(PHANDLE ProfileHandle, HANDLE ProcessHandle, PVOID Base, - * ULONG Size, ULONG BucketShift, PULONG Buffer, - * ULONG BufferLength, KPROFILE_SOURCE Source, ULONG ProcessorMask) */ - { &SsNtCreateProfile, "NtCreateProfile", 9, { 0, HandleArgument, 0, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtCreateSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PLARGE_INTEGER SectionSize, ULONG Protect, ULONG Attributes, - * HANDLE FileHandle) */ - { &SsNtCreateSection, "NtCreateSection", 7, { 0, 0, ObjectAttributesArgument, Int64Argument, 0, 0, HandleArgument } }, - /* NTSTATUS NtCreateSemaphore(PHANDLE SemaphoreHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * LONG InitialCount, LONG MaximumCount) */ - { &SsNtCreateSemaphore, "NtCreateSemaphore", 5, { 0, 0, ObjectAttributesArgument, 0, 0 } }, - /* NTSTATUS NtCreateSymbolicLinkObject(PHANDLE SymbolicLinkHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PUNICODE_STRING TargetName) */ - { &SsNtCreateSymbolicLinkObject, "NtCreateSymbolicLinkObject", 4, { 0, 0, ObjectAttributesArgument, UnicodeStringArgument } }, - /* NTSTATUS NtCreateThread(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * HANDLE ProcessHandle, PCLIENT_ID ClientId, PCONTEXT ThreadContext, - * PINITIAL_TEB UserStack, BOOLEAN CreateSuspended) */ - { &SsNtCreateThread, "NtCreateThread", 8, { 0, 0, ObjectAttributesArgument, HandleArgument, 0, ContextArgument, InitialTebArgument, 0 } }, - /* NTSTATUS NtCreateTimer(PHANDLE TimerHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * TIMER_TYPE TimerType) */ - { &SsNtCreateTimer, "NtCreateTimer", 4, { 0, 0, ObjectAttributesArgument, 0 } }, - /* NTSTATUS NtCreateToken(PHANDLE TokenHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * TOKEN_TYPE Type, PLUID AuthenticationId, PLARGE_INTEGER ExpirationTime, - * PTOKEN_USER User, PTOKEN_GROUPS Groups, PTOKEN_PRIVILEGES Privileges, - * PTOKEN_OWNER Owner, PTOKEN_PRIMARY_GROUP PrimaryGroup, PTOKEN_DEFAULT_DACL DefaultDacl, - * PTOKEN_SOURCE Source) */ - { &SsNtCreateToken, "NtCreateToken", 13, { 0, 0, ObjectAttributesArgument, 0, Int64Argument, Int64Argument, 0, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtCreateWaitablePort(PHANDLE PortHandle, POBJECT_ATTRIBUTES ObjectAttributes, ULONG MaxConnectionInfoLength, - * ULONG MaxMessageLength, ULONG MaxPoolUsage) */ - { &SsNtCreateWaitablePort, "NtCreateWaitablePort", 5, { 0, ObjectAttributesArgument, 0, 0, 0 } }, - /* NTSTATUS NtDebugActiveProcess(HANDLE ProcessHandle, HANDLE DebugObjectHandle) */ - { &SsNtDebugActiveProcess, "NtDebugActiveProcess", 2, { HandleArgument, HandleArgument } }, - /* NTSTATUS NtDebugContinue(HANDLE DebugObjectHandle, PCLIENT_ID ClientId, NTSTATUS ContinueStatus) */ - { &SsNtDebugContinue, "NtDebugContinue", 3, { HandleArgument, ClientIdArgument, 0 } }, - /* NTSTATUS NtDelayExecution(BOOLEAN Alertable, PLARGE_INTEGER Interval) */ - { &SsNtDelayExecution, "NtDelayExecution", 2, { 0, Int64Argument } }, - /* NTSTATUS NtDeleteAtom(USHORT Atom) */ - { &SsNtDeleteAtom, "NtDeleteAtom", 1, { 0 } }, - /* NTSTATUS NtDeleteBootEntry(ULONG Id) */ - { &SsNtDeleteBootEntry, "NtDeleteBootEntry", 1, { 0 } }, - /* NTSTATUS NtDeleteDriverEntry(ULONG Id) */ - { &SsNtDeleteDriverEntry, "NtDeleteDriverEntry", 1, { 0 } }, - /* NTSTATUS NtDeleteFile(POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtDeleteFile, "NtDeleteFile", 1, { ObjectAttributesArgument } }, - /* NTSTATUS NtDeleteKey(HANDLE KeyHandle) */ - { &SsNtDeleteKey, "NtDeleteKey", 1, { HandleArgument } }, - /* NTSTATUS NtDeleteObjectAuditAlarm(PUNICODE_STRING SubsystemName, PVOID HandleId, BOOLEAN GenerateOnClose) */ - { &SsNtDeleteObjectAuditAlarm, "NtDeleteObjectAuditAlarm", 3, { UnicodeStringArgument, 0, 0 } }, - /* NTSTATUS NtDeletePrivateNamespace(HANDLE PrivateNamespaceHandle) */ - { &SsNtDeletePrivateNamespace, "NtDeletePrivateNamespace", 1, { HandleArgument } }, - /* NTSTATUS NtDeleteValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName) */ - { &SsNtDeleteValueKey, "NtDeleteValueKey", 2, { HandleArgument, UnicodeStringArgument } }, - /* NTSTATUS NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, - * PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode, - * PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, - * ULONG OutputBufferLength) */ - { &SsNtDeviceIoControlFile, "NtDeviceIoControlFile", 10, { HandleArgument, HandleArgument, 0, 0, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtDisplayString(PUNICODE_STRING String) */ - { &SsNtDisplayString, "NtDisplayString", 1, { UnicodeStringArgument } }, - /* NTSTATUS NtDuplicateObject(HANDLE SourceProcessHandle, HANDLE SourceHandle, HANDLE TargetProcessHandle, - * PHANDLE TargetHandle, ACCESS_MASK DesiredAccess, ULONG Attributes, - * ULONG Options) */ - { &SsNtDuplicateObject, "NtDuplicateObject", 7, { HandleArgument, HandleArgument, HandleArgument, 0, 0, 0, 0 } }, - /* NTSTATUS NtDuplicateToken(HANDLE ExistingTokenHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * BOOLEAN EffectiveOnly, TOKEN_TYPE TokenType, PHANDLE NewTokenHandle) */ - { &SsNtDuplicateToken, "NtDuplicateToken", 6, { HandleArgument, 0, ObjectAttributesArgument, 0, 0, 0 } }, - /* NTSTATUS NtEnumerateBootEntries(PVOID Buffer, PULONG BufferLength) */ - { &SsNtEnumerateBootEntries, "NtEnumerateBootEntries", 2, { 0, Int32Argument } }, - /* NTSTATUS NtEnumerateDriverEntries(PVOID Buffer, PULONG BufferLength) */ - { &SsNtEnumerateDriverEntries, "NtEnumerateDriverEntries", 2, { 0, Int32Argument } }, - /* NTSTATUS NtEnumerateKey(HANDLE KeyHandle, ULONG Index, KEY_INFORMATION_CLASS KeyInformationClass, - * PVOID KeyInformation, ULONG KeyInformationLength, PULONG ResultLength) */ - { &SsNtEnumerateKey, "NtEnumerateKey", 6, { HandleArgument, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtEnumerateSystemEnvironmentValuesEx(ULONG InformationClass, PVOID Buffer, PULONG BufferLength) */ - { &SsNtEnumerateSystemEnvironmentValuesEx, "NtEnumerateSystemEnvironmentValuesEx", 3, { 0, 0, Int32Argument } }, - /* NTSTATUS NtEnumerateValueKey(HANDLE KeyHandle, ULONG Index, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - * PVOID KeyValueInformation, ULONG KeyValueInformationLength, PULONG ResultLength) */ - { &SsNtEnumerateValueKey, "NtEnumerateValueKey", 6, { HandleArgument, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtExtendSection(HANDLE SectionHandle, PLARGE_INTEGER SectionSize) */ - { &SsNtExtendSection, "NtExtendSection", 2, { HandleArgument, Int64Argument } }, - /* NTSTATUS NtFilterToken(HANDLE ExistingTokenHandle, ULONG Flags, PTOKEN_GROUPS SidsToDisable, - * PTOKEN_PRIVILEGES PrivilegesToDelete, PTOKEN_GROUPS SidsToRestricted, PHANDLE NewTokenHandle) */ - { &SsNtFilterToken, "NtFilterToken", 6, { HandleArgument, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtFindAtom(PWSTR String, ULONG StringLength, PUSHORT Atom) */ - { &SsNtFindAtom, "NtFindAtom", 3, { WStringArgument, 0, 0 } }, - /* NTSTATUS NtFlushBuffersFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock) */ - { &SsNtFlushBuffersFile, "NtFlushBuffersFile", 2, { HandleArgument, 0 } }, - /* NTSTATUS NtFlushInstructionCache(HANDLE ProcessHandle, PVOID BaseAddress, ULONG FlushSize) */ - { &SsNtFlushInstructionCache, "NtFlushInstructionCache", 3, { HandleArgument, 0, 0 } }, - /* NTSTATUS NtFlushKey(HANDLE KeyHandle) */ - { &SsNtFlushKey, "NtFlushKey", 1, { HandleArgument } }, - /* NTSTATUS NtFlushProcessWriteBuffers() */ - { &SsNtFlushProcessWriteBuffers, "NtFlushProcessWriteBuffers", 0 }, - /* NTSTATUS NtFlushVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PULONG FlushSize, - * PIO_STATUS_BLOCK IoStatusBlock) */ - { &SsNtFlushVirtualMemory, "NtFlushVirtualMemory", 4, { HandleArgument, Int32Argument, Int32Argument, 0 } }, - /* NTSTATUS NtFlushWriteBuffer() */ - { &SsNtFlushWriteBuffer, "NtFlushWriteBuffer", 0 }, - /* NTSTATUS NtFreeUserPhysicalPages(HANDLE ProcessHandle, PULONG NumberOfPages, PULONG PageFrameNumbers) */ - { &SsNtFreeUserPhysicalPages, "NtFreeUserPhysicalPages", 3, { HandleArgument, Int32Argument, 0 } }, - /* NTSTATUS NtFreeVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PULONG FreeSize, - * ULONG FreeType) */ - { &SsNtFreeVirtualMemory, "NtFreeVirtualMemory", 4, { HandleArgument, Int32Argument, Int32Argument, 0 } }, - /* NTSTATUS NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, - * PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, - * PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, - * ULONG OutputBufferLength) */ - { &SsNtFsControlFile, "NtFsControlFile", 10, { HandleArgument, HandleArgument, 0, 0, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtGetContextThread(HANDLE ThreadHandle, PCONTEXT Context) */ - { &SsNtGetContextThread, "NtGetContextThread", 2, { HandleArgument, ContextArgument } }, - /* NTSTATUS NtGetCurrentProcessorNumber() */ - { &SsNtGetCurrentProcessorNumber, "NtGetCurrentProcessorNumber", 0 }, - /* NTSTATUS NtGetDevicePowerState(HANDLE DeviceHandle, PDEVICE_POWER_STATE DevicePowerState) */ - { &SsNtGetDevicePowerState, "NtGetDevicePowerState", 2, { HandleArgument, 0 } }, - /* NTSTATUS NtGetNextProcess(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, ULONG HandleAttributes, - * ULONG Flags, PHANDLE NewProcessHandle) */ - { &SsNtGetNextProcess, "NtGetNextProcess", 5, { HandleArgument, 0, 0, 0, 0 } }, - /* NTSTATUS NtGetNextThread(HANDLE ProcessHandle, HANDLE ThreadHandle, ACCESS_MASK DesiredAccess, - * ULONG HandleAttributes, ULONG Flags, PHANDLE NewThreadHandle) */ - { &SsNtGetNextThread, "NtGetNextThread", 6, { HandleArgument, HandleArgument, 0, 0, 0, 0 } }, - /* NTSTATUS NtGetPlugPlayEvent(HANDLE EventHandle, PVOID Context, PVOID Buffer, - * ULONG BufferLength) */ - { &SsNtGetPlugPlayEvent, "NtGetPlugPlayEvent", 4, { HandleArgument, 0, 0, 0 } }, - /* NTSTATUS NtGetWriteWatch(HANDLE ProcessHandle, ULONG Flags, PVOID BaseAddress, - * ULONG RegionSize, PULONG Buffer, PULONG BufferEntries, - * PULONG Granularity) */ - { &SsNtGetWriteWatch, "NtGetWriteWatch", 7, { HandleArgument, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtImpersonateAnonymousToken(HANDLE ThreadHandle) */ - { &SsNtImpersonateAnonymousToken, "NtImpersonateAnonymousToken", 1, { HandleArgument } }, - /* NTSTATUS NtImpersonateClientOfPort(HANDLE PortHandle, PPORT_MESSAGE Message) */ - { &SsNtImpersonateClientOfPort, "SsNtImpersonateClientOfPort", 2, { HandleArgument, 0 } }, - /* NTSTATUS NtImpersonateThread(HANDLE ThreadHandle, HANDLE TargetThreadHandle, PSECURITY_QUALITY_OF_SERVICE SecurityQos) */ - { &SsNtImpersonateThread, "NtImpersonateThread", 3, { HandleArgument, HandleArgument, 0 } }, - /* NTSTATUS NtInitiatePowerAction(POWER_ACTION SystemAction, SYSTEM_POWER_STATE MinSystemState, ULONG Flags, - * BOOLEAN Asynchronous) */ - { &SsNtInitiatePowerAction, "NtInitiatePowerAction", 4, { 0, 0, 0, 0 } }, - /* NTSTATUS NtIsProcessInJob(HANDLE ProcessHandle, HANDLE JobHandle) */ - { &SsNtIsProcessInJob, "NtIsProcessInJob", 2, { HandleArgument, HandleArgument } }, - /* NTSTATUS NtIsSystemResumeAutomatic() */ - { &SsNtIsSystemResumeAutomatic, "NtIsSystemResumeAutomatic", 0 }, - /* NTSTATUS NtListenPort(HANDLE PortHandle, PPORT_MESSAGE Message) */ - { &SsNtListenPort, "NtListenPort", 2, { HandleArgument, 0 } }, - /* NTSTATUS NtLoadDriver(PUNICODE_STRING DriverServiceName) */ - { &SsNtLoadDriver, "NtLoadDriver", 1, { UnicodeStringArgument } }, - /* NTSTATUS NtLoadKey(POBJECT_ATTRIBUTES KeyObjectAttributes, POBJECT_ATTRIBUTES FileObjectAttributes) */ - { &SsNtLoadKey, "NtLoadKey", 2, { ObjectAttributesArgument, ObjectAttributesArgument } }, - /* NTSTATUS NtLoadKey2(POBJECT_ATTRIBUTES KeyObjectAttributes, POBJECT_ATTRIBUTES FileObjectAttributes, ULONG Flags) */ - { &SsNtLoadKey2, "NtLoadKey2", 3, { ObjectAttributesArgument, ObjectAttributesArgument, 0 } }, - /* NTSTATUS NtLockFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, - * PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PULARGE_INTEGER LockOffset, - * PULARGE_INTEGER LockLength, ULONG Key, BOOLEAN FailImmediately, - * BOOLEAN ExclusiveLock) */ - { &SsNtLockFile, "NtLockFile", 10, { HandleArgument, HandleArgument, 0, 0, 0, Int64Argument, Int64Argument, 0, 0, 0 } }, - /* NTSTATUS NtLockVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PULONG LockSize, - * ULONG LockType) */ - { &SsNtLockVirtualMemory, "NtLockVirtualMemory", 4, { HandleArgument, Int32Argument, Int32Argument, 0 } }, - /* NTSTATUS NtMakePermanentObject(HANDLE Handle) */ - { &SsNtMakePermanentObject, "NtMakePermanentObject", 1, { HandleArgument } }, - /* NTSTATUS NtMakeTemporaryObject(HANDLE Handle) */ - { &SsNtMakeTemporaryObject, "NtMakeTemporaryObject", 1, { HandleArgument } }, - /* NTSTATUS NtMapUserPhysicalPages(PVOID BaseAddress, PULONG NumberOfPages, PULONG PageFrameNumbers) */ - { &SsNtMapUserPhysicalPages, "NtMapUserPhysicalPages", 3, { 0, Int32Argument, 0 } }, - /* NTSTATUS NtMapUserPhysicalPagesScatter(PVOID BaseAddress, PULONG NumberOfPages, PULONG PageFrameNumbers) */ - { &SsNtMapUserPhysicalPagesScatter, "NtMapUserPhysicalPagesScatter", 3, { 0, Int32Argument, 0 } }, - /* NTSTATUS NtMapViewOfSection(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress, - * ULONG ZeroBits, ULONG CommitSize, PLARGE_INTEGER SectionOffset, - * PULONG ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, - * ULONG Protect) */ - { &SsNtMapViewOfSection, "NtMapViewOfSection", 10, { HandleArgument, HandleArgument, Int32Argument, 0, 0, Int64Argument, Int32Argument, 0, 0, 0 } }, - /* NTSTATUS NtModifyBootEntry(PBOOT_ENTRY BootEntry) */ - { &SsNtModifyBootEntry, "NtModifyBootEntry", 1, { 0 } }, - /* NTSTATUS NtModifyDriverEntry(PEFI_DRIVER_ENTRY DriverEntry) */ - { &SsNtModifyDriverEntry, "NtModifyDriverEntry", 1, { 0 } }, - /* NTSTATUS NtNotifyChangeDirectoryFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, - * PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PFILE_NOTIFY_INFORMATION Buffer, - * ULONG BufferLength, ULONG NotifyFilter, BOOLEAN WatchSubtree) */ - { &SsNtNotifyChangeDirectoryFile, "NtNotifyChangeDirectoryFile", 9, { HandleArgument, HandleArgument, 0, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtNotifyChangeKey(HANDLE KeyHandle, HANDLE EventHandle, PIO_APC_ROUTINE ApcRoutine, - * PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG NotifyFilter, - * BOOLEAN WatchSubtree, PVOID Buffer, ULONG BufferLength, - * BOOLEAN Asynchronous) */ - { &SsNtNotifyChangeKey, "NtNotifyChangeKey", 10, { HandleArgument, HandleArgument, 0, 0, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtNotifyChangeMultipleKeys(HANDLE KeyHandle, ULONG Flags, POBJECT_ATTRIBUTES KeyObjectAttributes, - * HANDLE EventHandle, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, - * PIO_STATUS_BLOCK IoStatusBlock, ULONG NotifyFilter, BOOLEAN WatchSubtree, - * PVOID Buffer, ULONG BufferLength, BOOLEAN Asynchronous) */ - { &SsNtNotifyChangeMultipleKeys, "NtNotifyChangeMultipleKeys", 12, { HandleArgument, 0, ObjectAttributesArgument, HandleArgument, 0, 0, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtOpenDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenDirectoryObject, "NtOpenDirectoryObject", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenEvent(PHANDLE EventHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenEvent, "NtOpenEvent", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenEventPair(PHANDLE EventPairHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenEventPair, "NtOpenEventPair", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions) */ - { &SsNtOpenFile, "NtOpenFile", 6, { 0, 0, ObjectAttributesArgument, 0, 0, 0 } }, - /* NTSTATUS NtOpenIoCompletion(PHANDLE IoCompletionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenIoCompletion, "NtOpenIoCompletion", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenJobObject(PHANDLE JobHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenJobObject, "NtOpenJobObject", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenKey, "NtOpenKey", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenKeyedEvent(PHANDLE KeyedEventHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenKeyedEvent, "NtOpenKeyedEvent", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenMutant(PHANDLE MutantHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenMutant, "NtOpenMutant", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenObjectAuditAlarm(PUNICODE_STRING SubsystemName, PVOID *HandleId, PUNICODE_STRING ObjectTypeName, - * PUNICODE_STRING ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, HANDLE TokenHandle, - * ACCESS_MASK DesiredAccess, ACCESS_MASK GrantedAccess, PPRIVILEGE_SET Privileges, - * BOOLEAN ObjectCreation, BOOLEAN AccessGranted, PBOOLEAN GenerateOnClose) */ - { &SsNtOpenObjectAuditAlarm, "NtOpenObjectAuditAlarm", 12, { UnicodeStringArgument, Int32Argument, UnicodeStringArgument, UnicodeStringArgument, 0, HandleArgument, 0, 0, 0, 0, 0, 0 } }, - /* NTSTATUS NtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PCLIENT_ID ClientId) */ - { &SsNtOpenProcess, "NtOpenProcess", 4, { 0, 0, ObjectAttributesArgument, ClientIdArgument } }, - /* NTSTATUS NtOpenProcessToken(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, PHANDLE TokenHandle) */ - { &SsNtOpenProcessToken, "NtOpenProcessToken", 3, { HandleArgument, 0, 0 } }, - /* NTSTATUS NtOpenProcessTokenEx(HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, ULONG HandleAttributes, - * PHANDLE TokenHandle) */ - { &SsNtOpenProcessTokenEx, "NtOpenProcessTokenEx", 4, { HandleArgument, 0, 0, 0 } }, - /* NTSTATUS NtOpenSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenSection, "NtOpenSection", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenSemaphore(PHANDLE SemaphoreHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenSemaphore, "NtOpenSemaphore", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenSymbolicLinkObject(PHANDLE SymbolicLinkHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenSymbolicLinkObject, "NtOpenSymbolicLinkObject", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtOpenThread(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, - * PCLIENT_ID ClientId) */ - { &SsNtOpenThread, "NtOpenThread", 4, { 0, 0, ObjectAttributesArgument, ClientIdArgument } }, - /* NTSTATUS NtOpenThreadToken(HANDLE ThreadHandle, ACCESS_MASK DesiredAccess, BOOLEAN OpenAsSelf, - * PHANDLE TokenHandle) */ - { &SsNtOpenThreadToken, "NtOpenThreadToken", 4, { HandleArgument, 0, 0, 0 } }, - /* NTSTATUS NtOpenThreadTokenEx(HANDLE ThreadHandle, ACCESS_MASK DesiredAccess, BOOLEAN OpenAsSelf, - * ULONG HandleAttributes, PHANDLE TokenHandle) */ - { &SsNtOpenThreadTokenEx, "NtOpenThreadTokenEx", 5, { HandleArgument, 0, 0, 0, 0 } }, - /* NTSTATUS NtOpenTimer(PHANDLE TimerHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) */ - { &SsNtOpenTimer, "NtOpenTimer", 3, { 0, 0, ObjectAttributesArgument } }, - /* NTSTATUS NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, - * PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, - * ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key) */ - { &SsNtReadFile, "NtReadFile", 9, { HandleArgument, HandleArgument, 0, 0, 0, 0, 0, Int64Argument, Int32Argument } }, - /* NTSTATUS NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, - * PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, - * ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key) */ - { &SsNtWriteFile, "NtWriteFile", 9, { HandleArgument, HandleArgument, 0, 0, 0, 0, 0, Int64Argument, Int32Argument } }, - - { NULL, "Dummy", 0 } -}; - -RTL_GENERIC_TABLE KphSsCallTable; -FAST_MUTEX KphSsCallTableMutex; - -/* KphSsDataInit - * - * Initializes all data structures so that system service entries - * can be looked up. - */ -VOID KphSsDataInit() -{ - ULONG i; - - RtlInitializeGenericTable( - &KphSsCallTable, - KphpSsCallEntryCompareRoutine, - KphpSsCallEntryAllocateRoutine, - KphpSsCallEntryFreeRoutine, - NULL - ); - - for (i = 0; i < sizeof(SsEntries) / sizeof(KPHSS_CALL_ENTRY); i++) - { - /* Ignore the dummy entry. */ - if (SsEntries[i].Number) - { - RtlInsertElementGenericTable( - &KphSsCallTable, - &SsEntries[i], - /* Save some space... */ - FIELD_OFFSET(KPHSS_CALL_ENTRY, Arguments) + - SsEntries[i].NumberOfArguments * sizeof(KPHSS_ARGUMENT_TYPE), - NULL - ); - } - } - - ExInitializeFastMutex(&KphSsCallTableMutex); -} - -/* KphSsDataDeinit - * - * Frees all memory associated with system service data. - */ -VOID KphSsDataDeinit() -{ - PKPHSS_CALL_ENTRY callEntry; - - while (callEntry = (PKPHSS_CALL_ENTRY)RtlGetElementGenericTable(&KphSsCallTable, 0)) - RtlDeleteElementGenericTable(&KphSsCallTable, callEntry); -} - -/* KphSsLookupCallEntry - * - * Lookups up a system service entry by system service number. - */ -PKPHSS_CALL_ENTRY KphSsLookupCallEntry( - __in ULONG Number - ) -{ - KPHSS_CALL_ENTRY callEntry; - PKPHSS_CALL_ENTRY foundEntry; - - callEntry.Number = &Number; - - ExAcquireFastMutex(&KphSsCallTableMutex); - foundEntry = (PKPHSS_CALL_ENTRY)RtlLookupElementGenericTable( - &KphSsCallTable, - &callEntry - ); - ExReleaseFastMutex(&KphSsCallTableMutex); - - return foundEntry; -} - -/* KphpSsCallEntryAllocateRoutine - * - * Allocates storage for a system service entry. - */ -PVOID KphpSsCallEntryAllocateRoutine( - __in PRTL_GENERIC_TABLE Table, - __in CLONG ByteSize - ) -{ - return ExAllocatePoolWithTag( - PagedPool, - ByteSize, - TAG_CALL_ENTRY - ); -} - -/* KphpSsCallEntryCompareRoutine - * - * Compares two system service entries. - */ -RTL_GENERIC_COMPARE_RESULTS KphpSsCallEntryCompareRoutine( - __in PRTL_GENERIC_TABLE Table, - __in PVOID FirstStruct, - __in PVOID SecondStruct - ) -{ - PKPHSS_CALL_ENTRY callEntry1, callEntry2; - - callEntry1 = (PKPHSS_CALL_ENTRY)FirstStruct; - callEntry2 = (PKPHSS_CALL_ENTRY)SecondStruct; - - if (*(callEntry1->Number) < *(callEntry2->Number)) - return GenericLessThan; - else if (*(callEntry1->Number) > *(callEntry2->Number)) - return GenericGreaterThan; - else - return GenericEqual; -} - -/* KphpSsCallEntryFreeRoutine - * - * Frees storage for a system service entry. - */ -VOID KphpSsCallEntryFreeRoutine( - __in PRTL_GENERIC_TABLE Table, - __in PVOID Buffer - ) -{ - ExFreePoolWithTag( - Buffer, - TAG_CALL_ENTRY - ); -} diff --git a/2.x/trunk/KProcessHacker/util.c b/2.x/trunk/KProcessHacker/util.c index 61e3b3ecf..545127095 100644 --- a/2.x/trunk/KProcessHacker/util.c +++ b/2.x/trunk/KProcessHacker/util.c @@ -20,7 +20,7 @@ * along with Process Hacker. If not, see . */ -#include "include/util.h" +#include "include/kph.h" /* KphInitializeStream * diff --git a/2.x/trunk/KProcessHacker/version.c b/2.x/trunk/KProcessHacker/version.c index ef2e9bb2b..d98f681b6 100644 --- a/2.x/trunk/KProcessHacker/version.c +++ b/2.x/trunk/KProcessHacker/version.c @@ -21,75 +21,13 @@ */ #define _VERSION_PRIVATE -#include "include/version.h" -#include "include/debug.h" +#include "include/kph.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, KvInit) #pragma alloc_text(PAGE, KvScanProc) -#pragma alloc_text(PAGE, KvVerifyPrologue) #endif -/* - * mov edi, edi - * push ebp - * mov ebp, esp - */ -static char StandardPrologue[] = { 0x8b, 0xff, 0x55, 0x8b, 0xec }; - -/* KiFastCallEntry */ -/* - * Note that this scan will get the address of - * mov esi, edx - * within KiFastCallEntry, not the start of KiFastCallEntry. - * We will then subtract 7 to get the address of - * inc dword ptr fs:PbSystemCalls - * See sysservice.c for more details. - */ -static char KiFastCallEntry51[] = -{ - 0x8b, 0xf2, 0x8b, 0x5f, 0x0c, 0x33, 0xc9, 0x8a, - 0x0c, 0x18, 0x8b, 0x3f, 0x8b, 0x1c, 0x87, 0x2b -}; -static char KiFastCallEntry52[] = -{ - 0x8b, 0xf2, 0x8b, 0x5f, 0x0c, 0x33, 0xc9, 0x8a, - 0x0c, 0x18, 0x8b, 0x3f, 0x8b, 0x1c, 0x87, 0x2b -}; /* same as 5.1 */ -static char KiFastCallEntry60[] = -{ - 0x8b, 0xf2, 0x33, 0xc9, 0x8b, 0x57, 0x0c, 0x8b, - 0x3f, 0x8a, 0x0c, 0x10, 0x8b, 0x14, 0x87, 0x2b -}; -static char KiFastCallEntry61[] = -{ - 0x8b, 0xf2, 0x33, 0xc9, 0x8b, 0x57, 0x0c, 0x8b, - 0x3f, 0x8a, 0x0c, 0x10, 0x8b, 0x14, 0x87, 0x2b -}; /* same as 6.0 */ -/* Below is the scan to find the start of KiFastCallEntry. */ -/* static char KiFastCallEntry[] = -{ - 0xb9, 0x23, 0x00, 0x00, 0x00, 0x6a, 0x30, 0x0f, - 0xa1, 0x8e, 0xd9, 0x8e, 0xc1, 0x64, 0x8b, 0x0d -}; */ - -/* PsExitSpecialApc */ -static char PsExitSpecialApc51[] = -{ - 0x8b, 0xff, 0x55, 0x8b, 0xec, 0x64, 0xa1, 0x24, - 0x01, 0x00, 0x00, 0x8b, 0x45, 0x08, 0xf6, 0x40 -}; -static char PsExitSpecialApc60[] = -{ - 0x8b, 0xff, 0x55, 0x8b, 0xec, 0x83, 0xe4, 0xf8, - 0x51, 0x8b, 0x45, 0x08, 0xf6, 0x40, 0x28, 0x01 -}; -static char PsExitSpecialApc61[] = -{ - 0x8b, 0xff, 0x55, 0x8b, 0xec, 0x83, 0xe4, 0xf8, - 0x51, 0x8b, 0x45, 0x08, 0xf6, 0x40, 0x28, 0x01 -}; /* same as 6.0 */ - /* PsTerminateProcess/PspTerminateProcess */ static char PspTerminateProcess51[] = { @@ -193,9 +131,6 @@ NTSTATUS KvInit() ThreadAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff; OffEtClientId = 0x1ec; - OffEtSpareByteForSs = 0x256; /* Padding, last */ - OffEtStartAddress = 0x224; - OffEtWin32StartAddress = 0x228; OffEpJob = 0x134; OffEpObjectTable = 0xc4; OffEpProtectedProcessOff = 0; @@ -204,17 +139,7 @@ NTSTATUS KvInit() OffOhBody = 0x18; OffOtName = 0x40; OffOtiGenericMapping = 0x60 + 0x8; - OffOtiOpenProcedure = 0x60 + 0x30; - SsNtContinue = 0x20; - - /* KiFastCallEntry isn't hooked properly yet. Disabled for now. */ - /* INIT_SCAN( - KiFastCallEntryScan, - KiFastCallEntry51, - sizeof(KiFastCallEntry51), - (ULONG_PTR)__ZwClose, SCAN_LENGTH, -6 - ); */ /* We are scanning for PspTerminateProcess which has the same signature as PsTerminateProcess because PsTerminateProcess is simply a wrapper on XP. @@ -264,9 +189,6 @@ NTSTATUS KvInit() ThreadAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff; OffEtClientId = 0x1e4; - OffEtSpareByteForSs = 0x24f; /* Padding, last */ - OffEtStartAddress = 0x21c; - OffEtWin32StartAddress = 0x220; OffEpJob = 0x120; OffEpObjectTable = 0xd4; OffEpProtectedProcessOff = 0; @@ -275,17 +197,7 @@ NTSTATUS KvInit() OffOhBody = 0x18; OffOtName = 0x40; OffOtiGenericMapping = 0x60 + 0x8; - OffOtiOpenProcedure = 0x60 + 0x30; - SsNtContinue = 0x22; - - /* Can't find on ntoskrnl *and* ntkrnlpa. Disabled for now. */ - /* INIT_SCAN( - KiFastCallEntryScan, - KiFastCallEntry52, - sizeof(KiFastCallEntry52), - (ULONG_PTR)__ZwClose, SCAN_LENGTH, -7 - ); */ /* We are scanning for PspTerminateProcess which has the same signature as PsTerminateProcess because PsTerminateProcess is simply a wrapper on Server 2003. @@ -329,9 +241,6 @@ NTSTATUS KvInit() ThreadAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xfff; OffEtClientId = 0x20c; - OffEtSpareByteForSs = 0x26f; /* Padding, second-last */ - OffEtStartAddress = 0x1f8; - OffEtWin32StartAddress = 0x240; OffEpJob = 0x10c; OffEpObjectTable = 0xdc; OffEpProtectedProcessOff = 0x224; @@ -339,12 +248,6 @@ NTSTATUS KvInit() OffEpRundownProtect = 0x98; OffOhBody = 0x18; - INIT_SCAN( - KiFastCallEntryScan, - KiFastCallEntry60, - sizeof(KiFastCallEntry60), - (ULONG_PTR)__ZwClose, SCAN_LENGTH, -7 - ); INIT_SCAN( PsTerminateProcessScan, PsTerminateProcess60, @@ -363,150 +266,18 @@ NTSTATUS KvInit() { OffOtName = 0x40; OffOtiGenericMapping = 0x60 + 0xc; - OffOtiOpenProcedure = 0x60 + 0x30; - - SsNtContinue = 0x36; } /* SP1 */ else if (servicePack == 1) { OffOtName = 0x8; OffOtiGenericMapping = 0x28 + 0xc; /* They got rid of the Mutex (an ERESOURCE) */ - OffOtiOpenProcedure = 0x28 + 0x34; - - SsNtContinue = 0x37; } /* SP2 */ else if (servicePack == 2) { OffOtName = 0x8; OffOtiGenericMapping = 0x28 + 0xc; - OffOtiOpenProcedure = 0x28 + 0x34; - - SsNtAddAtom = 0x8; - SsNtAlertResumeThread = 0xd; - SsNtAlertThread = 0xe; - SsNtAllocateLocallyUniqueId = 0xf; - SsNtAllocateUserPhysicalPages = 0x10; - SsNtAllocateUuids = 0x11; - SsNtAllocateVirtualMemory = 0x12; - SsNtApphelpCacheControl = 0x28; - SsNtAreMappedFilesTheSame = 0x29; - SsNtAssignProcessToJobObject = 0x2a; - SsNtCallbackReturn = 0x2b; - SsNtCancelDeviceWakeupRequest = 0x2c; - SsNtCancelIoFile = 0x2d; - SsNtCancelTimer = 0x2e; - SsNtClearEvent = 0x2f; - SsNtClose = 0x30; - SsNtContinue = 0x37; - SsNtCreateDebugObject = 0x38; - SsNtCreateDirectoryObject = 0x39; - SsNtCreateEvent = 0x3a; - SsNtCreateEventPair = 0x3b; - SsNtCreateFile = 0x3c; - SsNtCreateIoCompletion = 0x3d; - SsNtCreateJobObject = 0x3e; - SsNtCreateJobSet = 0x3f; - SsNtCreateKey = 0x40; - SsNtCreateKeyedEvent = 0x168; - SsNtCreateMailslotFile = 0x42; - SsNtCreateMutant = 0x43; - SsNtCreateNamedPipeFile = 0x44; - SsNtCreatePagingFile = 0x46; - SsNtCreatePort = 0x47; - SsNtCreatePrivateNamespace = 0x45; - SsNtCreateProcess = 0x48; - SsNtCreateProcessEx = 0x49; - SsNtCreateProfile = 0x4a; - SsNtCreateSection = 0x4b; - SsNtCreateSemaphore = 0x4c; - SsNtCreateSymbolicLinkObject = 0x4d; - SsNtCreateThread = 0x4e; - SsNtCreateTimer = 0x4f; - SsNtCreateToken = 0x50; - SsNtCreateUserProcess = 0x17f; - SsNtCreateWaitablePort = 0x73; - SsNtDebugActiveProcess = 0x74; - SsNtDebugContinue = 0x75; - SsNtDelayExecution = 0x76; - SsNtDeleteAtom = 0x77; - SsNtDeleteBootEntry = 0x78; - SsNtDeleteDriverEntry = 0x79; - SsNtDeleteFile = 0x7a; - SsNtDeleteKey = 0x7b; - SsNtDeletePrivateNamespace = 0x7c; - SsNtDeleteObjectAuditAlarm = 0x7d; - SsNtDeleteValueKey = 0x7e; - SsNtDeviceIoControlFile = 0x7f; - SsNtDisplayString = 0x80; - SsNtDuplicateObject = 0x81; - SsNtDuplicateToken = 0x82; - SsNtEnumerateBootEntries = 0x83; - SsNtEnumerateDriverEntries = 0x84; - SsNtEnumerateKey = 0x85; - SsNtEnumerateSystemEnvironmentValuesEx = 0x86; - SsNtEnumerateValueKey = 0x88; - SsNtExtendSection = 0x89; - SsNtFilterToken = 0x8a; - SsNtFindAtom = 0x8b; - SsNtFlushBuffersFile = 0x8c; - SsNtFlushInstructionCache = 0x8d; - SsNtFlushKey = 0x8e; - SsNtFlushProcessWriteBuffers = 0x8f; - SsNtFlushVirtualMemory = 0x90; - SsNtFlushWriteBuffer = 0x91; - SsNtFreeUserPhysicalPages = 0x92; - SsNtFreeVirtualMemory = 0x93; - SsNtFsControlFile = 0x96; - SsNtGetContextThread = 0x97; - SsNtGetDevicePowerState = 0x98; - SsNtGetPlugPlayEvent = 0x9a; - SsNtGetWriteWatch = 0x9b; - SsNtImpersonateAnonymousToken = 0x9c; - SsNtImpersonateClientOfPort = 0x9d; - SsNtImpersonateThread = 0x9e; - SsNtInitiatePowerAction = 0xa1; - SsNtIsProcessInJob = 0xa2; - SsNtIsSystemResumeAutomatic = 0xa3; - SsNtListenPort = 0xa4; - SsNtLoadDriver = 0xa5; - SsNtLoadKey = 0xa6; - SsNtLoadKey2 = 0xa7; - SsNtLockFile = 0xa9; - SsNtLockVirtualMemory = 0xac; - SsNtMakePermanentObject = 0xad; - SsNtMakeTemporaryObject = 0xae; - SsNtMapUserPhysicalPages = 0xaf; - SsNtMapUserPhysicalPagesScatter = 0xb0; - SsNtMapViewOfSection = 0xb1; - SsNtModifyBootEntry = 0xb2; - SsNtModifyDriverEntry = 0xb3; - SsNtNotifyChangeDirectoryFile = 0xb4; - SsNtNotifyChangeKey = 0xb5; - SsNtNotifyChangeMultipleKeys = 0xb6; - SsNtOpenDirectoryObject = 0xb7; - SsNtOpenEvent = 0xb8; - SsNtOpenEventPair = 0xb9; - SsNtOpenFile = 0xba; - SsNtOpenIoCompletion = 0xbb; - SsNtOpenJobObject = 0xbc; - SsNtOpenKey = 0xbd; - SsNtOpenKeyedEvent = 0x169; - SsNtOpenMutant = 0xbf; - SsNtOpenObjectAuditAlarm = 0xc1; - SsNtOpenProcess = 0xc2; - SsNtOpenProcessToken = 0xc3; - SsNtOpenProcessTokenEx = 0xc4; - SsNtOpenSection = 0xc5; - SsNtOpenSemaphore = 0xc6; - SsNtOpenSymbolicLinkObject = 0xc8; - SsNtOpenThread = 0xc9; - SsNtOpenThreadToken = 0xca; - SsNtOpenThreadTokenEx = 0xcb; - SsNtOpenTimer = 0xcc; - SsNtReadFile = 0x102; - SsNtWriteFile = 0x163; } else { @@ -529,9 +300,6 @@ NTSTATUS KvInit() ThreadAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xfff; OffEtClientId = 0x22c; - OffEtSpareByteForSs = 0x2b4; /* Padding, last */ - OffEtStartAddress = 0x218; - OffEtWin32StartAddress = 0x260; OffEpJob = 0x124; OffEpObjectTable = 0xf4; OffEpProtectedProcessOff = 0x26c; @@ -540,16 +308,7 @@ NTSTATUS KvInit() OffOhBody = 0x18; OffOtName = 0x8; OffOtiGenericMapping = 0x28 + 0xc; - OffOtiOpenProcedure = 0x28 + 0x34; - SsNtContinue = 0x3c; - - INIT_SCAN( - KiFastCallEntryScan, - KiFastCallEntry61, - sizeof(KiFastCallEntry61), - (ULONG_PTR)__ZwClose, SCAN_LENGTH, -7 - ); INIT_SCAN( PsTerminateProcessScan, PsTerminateProcess61, @@ -599,13 +358,3 @@ PVOID KvScanProc( return NULL; } - -PVOID KvVerifyPrologue( - PVOID Address - ) -{ - if (memcmp(Address, StandardPrologue, 5) == 0) - return Address; - else - return NULL; -} diff --git a/2.x/trunk/ProcessHacker/main.c b/2.x/trunk/ProcessHacker/main.c index ff88960bd..6b93f8845 100644 --- a/2.x/trunk/ProcessHacker/main.c +++ b/2.x/trunk/ProcessHacker/main.c @@ -363,7 +363,7 @@ VOID PhInitializeKph() // Append kprocesshacker.sys to the application directory. kprocesshackerFileName = PhConcatStrings2(PhApplicationDirectory->Buffer, kprocesshacker); - KphConnect2(&PhKphHandle, L"KProcessHacker", kprocesshackerFileName->Buffer); + KphConnect2(&PhKphHandle, L"KProcessHacker2", kprocesshackerFileName->Buffer); PhDereferenceObject(kprocesshackerFileName); #endif diff --git a/2.x/trunk/ProcessHacker/thrdprv.c b/2.x/trunk/ProcessHacker/thrdprv.c index cfc2e2716..d9c1420fb 100644 --- a/2.x/trunk/ProcessHacker/thrdprv.c +++ b/2.x/trunk/ProcessHacker/thrdprv.c @@ -802,25 +802,13 @@ VOID PhThreadProviderUpdate( if (threadItem->ThreadHandle) { - if (PhKphHandle) - { - KphGetThreadStartAddress( - PhKphHandle, - threadItem->ThreadHandle, - &startAddress - ); - } - - if (!startAddress) - { - NtQueryInformationThread( - threadItem->ThreadHandle, - ThreadQuerySetWin32StartAddress, - &startAddress, - sizeof(PVOID), - NULL - ); - } + NtQueryInformationThread( + threadItem->ThreadHandle, + ThreadQuerySetWin32StartAddress, + &startAddress, + sizeof(PVOID), + NULL + ); } if (!startAddress) diff --git a/2.x/trunk/phlib/include/kph.h b/2.x/trunk/phlib/include/kph.h index 74e869706..5a50fe30a 100644 --- a/2.x/trunk/phlib/include/kph.h +++ b/2.x/trunk/phlib/include/kph.h @@ -4,70 +4,62 @@ #include #define KPH_DEVICE_TYPE (0x9999) -#define KPH_DEVICE_NAME (L"\\Device\\KProcessHacker") +#define KPH_DEVICE_NAME (L"\\Device\\KProcessHacker2") #define KPHF_PSTERMINATEPROCESS 0x1 #define KPHF_PSPTERMINATETHREADBPYPOINTER 0x2 #define KPH_CTL_CODE(x) CTL_CODE(KPH_DEVICE_TYPE, 0x800 + x, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define KPH_CLOSEHANDLE KPH_CTL_CODE(0) -#define KPH_SSQUERYCLIENTENTRY KPH_CTL_CODE(1) -#define KPH_RESERVED1 KPH_CTL_CODE(2) -#define KPH_OPENPROCESS KPH_CTL_CODE(3) -#define KPH_OPENTHREAD KPH_CTL_CODE(4) -#define KPH_OPENPROCESSTOKEN KPH_CTL_CODE(5) -#define KPH_GETPROCESSPROTECTED KPH_CTL_CODE(6) -#define KPH_SETPROCESSPROTECTED KPH_CTL_CODE(7) -#define KPH_TERMINATEPROCESS KPH_CTL_CODE(8) -#define KPH_SUSPENDPROCESS KPH_CTL_CODE(9) -#define KPH_RESUMEPROCESS KPH_CTL_CODE(10) -#define KPH_READVIRTUALMEMORY KPH_CTL_CODE(11) -#define KPH_WRITEVIRTUALMEMORY KPH_CTL_CODE(12) -#define KPH_SETPROCESSTOKEN KPH_CTL_CODE(13) -#define KPH_GETTHREADSTARTADDRESS KPH_CTL_CODE(14) -#define KPH_SETHANDLEATTRIBUTES KPH_CTL_CODE(15) -#define KPH_GETHANDLEOBJECTNAME KPH_CTL_CODE(16) -#define KPH_OPENPROCESSJOB KPH_CTL_CODE(17) -#define KPH_GETCONTEXTTHREAD KPH_CTL_CODE(18) -#define KPH_SETCONTEXTTHREAD KPH_CTL_CODE(19) -#define KPH_GETTHREADWIN32THREAD KPH_CTL_CODE(20) -#define KPH_DUPLICATEOBJECT KPH_CTL_CODE(21) -#define KPH_ZWQUERYOBJECT KPH_CTL_CODE(22) -#define KPH_GETPROCESSID KPH_CTL_CODE(23) -#define KPH_GETTHREADID KPH_CTL_CODE(24) -#define KPH_TERMINATETHREAD KPH_CTL_CODE(25) -#define KPH_GETFEATURES KPH_CTL_CODE(26) -#define KPH_SETHANDLEGRANTEDACCESS KPH_CTL_CODE(27) -#define KPH_ASSIGNIMPERSONATIONTOKEN KPH_CTL_CODE(28) -#define KPH_PROTECTADD KPH_CTL_CODE(29) -#define KPH_PROTECTREMOVE KPH_CTL_CODE(30) -#define KPH_PROTECTQUERY KPH_CTL_CODE(31) -#define KPH_UNSAFEREADVIRTUALMEMORY KPH_CTL_CODE(32) -#define KPH_SETEXECUTEOPTIONS KPH_CTL_CODE(33) -#define KPH_QUERYPROCESSHANDLES KPH_CTL_CODE(34) -#define KPH_OPENTHREADPROCESS KPH_CTL_CODE(35) -#define KPH_CAPTURESTACKBACKTRACETHREAD KPH_CTL_CODE(36) -#define KPH_DANGEROUSTERMINATETHREAD KPH_CTL_CODE(37) -#define KPH_OPENTYPE KPH_CTL_CODE(38) -#define KPH_OPENDRIVER KPH_CTL_CODE(39) -#define KPH_QUERYINFORMATIONDRIVER KPH_CTL_CODE(40) -#define KPH_OPENDIRECTORYOBJECT KPH_CTL_CODE(41) -#define KPH_SSREF KPH_CTL_CODE(42) -#define KPH_SSUNREF KPH_CTL_CODE(43) -#define KPH_SSCREATECLIENTENTRY KPH_CTL_CODE(44) -#define KPH_SSCREATERULESETENTRY KPH_CTL_CODE(45) -#define KPH_SSREMOVERULE KPH_CTL_CODE(46) -#define KPH_SSADDPROCESSIDRULE KPH_CTL_CODE(47) -#define KPH_SSADDTHREADIDRULE KPH_CTL_CODE(48) -#define KPH_SSADDPREVIOUSMODERULE KPH_CTL_CODE(49) -#define KPH_SSADDNUMBERRULE KPH_CTL_CODE(50) -#define KPH_SSENABLECLIENTENTRY KPH_CTL_CODE(51) -#define KPH_OPENNAMEDOBJECT KPH_CTL_CODE(52) -#define KPH_QUERYINFORMATIONPROCESS KPH_CTL_CODE(53) -#define KPH_QUERYINFORMATIONTHREAD KPH_CTL_CODE(54) -#define KPH_SETINFORMATIONPROCESS KPH_CTL_CODE(55) -#define KPH_SETINFORMATIONTHREAD KPH_CTL_CODE(56) +/* General */ +#define KPH_GETFEATURES KPH_CTL_CODE(0) + +/* Processes */ +#define KPH_OPENPROCESS KPH_CTL_CODE(50) +#define KPH_OPENPROCESSTOKEN KPH_CTL_CODE(51) +#define KPH_OPENPROCESSJOB KPH_CTL_CODE(52) +#define KPH_SUSPENDPROCESS KPH_CTL_CODE(53) +#define KPH_RESUMEPROCESS KPH_CTL_CODE(54) +#define KPH_TERMINATEPROCESS KPH_CTL_CODE(55) +#define KPH_READVIRTUALMEMORY KPH_CTL_CODE(56) +#define KPH_WRITEVIRTUALMEMORY KPH_CTL_CODE(57) +#define KPH_UNSAFEREADVIRTUALMEMORY KPH_CTL_CODE(58) +#define KPH_GETPROCESSPROTECTED KPH_CTL_CODE(59) +#define KPH_SETPROCESSPROTECTED KPH_CTL_CODE(60) +#define KPH_SETEXECUTEOPTIONS KPH_CTL_CODE(61) +#define KPH_SETPROCESSTOKEN KPH_CTL_CODE(62) +#define KPH_QUERYINFORMATIONPROCESS KPH_CTL_CODE(63) +#define KPH_QUERYINFORMATIONTHREAD KPH_CTL_CODE(64) +#define KPH_SETINFORMATIONPROCESS KPH_CTL_CODE(65) +#define KPH_SETINFORMATIONTHREAD KPH_CTL_CODE(66) + +/* Threads */ +#define KPH_OPENTHREAD KPH_CTL_CODE(100) +#define KPH_OPENTHREADPROCESS KPH_CTL_CODE(101) +#define KPH_TERMINATETHREAD KPH_CTL_CODE(102) +#define KPH_DANGEROUSTERMINATETHREAD KPH_CTL_CODE(103) +#define KPH_GETCONTEXTTHREAD KPH_CTL_CODE(104) +#define KPH_SETCONTEXTTHREAD KPH_CTL_CODE(105) +#define KPH_CAPTURESTACKBACKTRACETHREAD KPH_CTL_CODE(106) +#define KPH_GETTHREADWIN32THREAD KPH_CTL_CODE(107) +#define KPH_ASSIGNIMPERSONATIONTOKEN KPH_CTL_CODE(108) + +/* Handles */ +#define KPH_QUERYPROCESSHANDLES KPH_CTL_CODE(150) +#define KPH_GETHANDLEOBJECTNAME KPH_CTL_CODE(151) +#define KPH_ZWQUERYOBJECT KPH_CTL_CODE(152) +#define KPH_DUPLICATEOBJECT KPH_CTL_CODE(153) +#define KPH_SETHANDLEATTRIBUTES KPH_CTL_CODE(154) +#define KPH_SETHANDLEGRANTEDACCESS KPH_CTL_CODE(155) +#define KPH_GETPROCESSID KPH_CTL_CODE(156) +#define KPH_GETTHREADID KPH_CTL_CODE(157) + +/* Objects */ +#define KPH_OPENNAMEDOBJECT KPH_CTL_CODE(200) +#define KPH_OPENDIRECTORYOBJECT KPH_CTL_CODE(201) +#define KPH_OPENDRIVER KPH_CTL_CODE(202) +#define KPH_QUERYINFORMATIONDRIVER KPH_CTL_CODE(203) +#define KPH_OPENTYPE KPH_CTL_CODE(204) // Process handle information @@ -85,18 +77,6 @@ typedef struct _PROCESS_HANDLE_INFORMATION PROCESS_HANDLE Handles[1]; } PROCESS_HANDLE_INFORMATION, *PPROCESS_HANDLE_INFORMATION; -// System service logging - -typedef struct _KPHSS_CLIENT_INFORMATION -{ - HANDLE ProcessId; - PVOID BufferBase; - ULONG BufferSize; - - ULONG NumberOfBlocksWritten; - ULONG NumberOfBlocksDropped; -} KPHSS_CLIENT_INFORMATION, *PKPHSS_CLIENT_INFORMATION; - // Driver information typedef enum _DRIVER_INFORMATION_CLASS @@ -146,19 +126,6 @@ NTSTATUS KphGetFeatures( __out PULONG Features ); -NTSTATUS KphCloseHandle( - __in HANDLE KphHandle, - __in HANDLE Handle - ); - -NTSTATUS KphSsQueryClientEntry( - __in HANDLE KphHandle, - __in HANDLE ClientEntryHandle, - __out PKPHSS_CLIENT_INFORMATION ClientInformation, - __in ULONG ClientInformationLength, - __out PULONG ReturnLength - ); - NTSTATUS KphOpenProcess( __in HANDLE KphHandle, __out PHANDLE ProcessHandle, @@ -166,13 +133,6 @@ NTSTATUS KphOpenProcess( __in ACCESS_MASK DesiredAccess ); -NTSTATUS KphOpenThread( - __in HANDLE KphHandle, - __out PHANDLE ThreadHandle, - __in HANDLE ThreadId, - __in ACCESS_MASK DesiredAccess - ); - NTSTATUS KphOpenProcessToken( __in HANDLE KphHandle, __out PHANDLE TokenHandle, @@ -180,22 +140,11 @@ NTSTATUS KphOpenProcessToken( __in ACCESS_MASK DesiredAccess ); -NTSTATUS KphGetProcessProtected( - __in HANDLE KphHandle, - __in HANDLE ProcessId, - __out PBOOLEAN IsProtected - ); - -NTSTATUS KphSetProcessProtected( - __in HANDLE KphHandle, - __in HANDLE ProcessId, - __in BOOLEAN IsProtected - ); - -NTSTATUS KphTerminateProcess( +NTSTATUS KphOpenProcessJob( __in HANDLE KphHandle, + __out PHANDLE JobHandle, __in HANDLE ProcessHandle, - __in NTSTATUS ExitStatus + __in ACCESS_MASK DesiredAccess ); NTSTATUS KphSuspendProcess( @@ -208,6 +157,12 @@ NTSTATUS KphResumeProcess( __in HANDLE ProcessHandle ); +NTSTATUS KphTerminateProcess( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in NTSTATUS ExitStatus + ); + NTSTATUS KphReadVirtualMemory( __in HANDLE KphHandle, __in HANDLE ProcessHandle, @@ -226,134 +181,6 @@ NTSTATUS KphWriteVirtualMemory( __out_opt PULONG ReturnLength ); -NTSTATUS KphSetProcessToken( - __in HANDLE KphHandle, - __in HANDLE SourceProcessId, - __in HANDLE TargetProcessId - ); - -NTSTATUS KphGetThreadStartAddress( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __out PPVOID StartAddress - ); - -NTSTATUS KphSetHandleAttributes( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __in ULONG Flags - ); - -NTSTATUS KphGetHandleObjectName( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __out_bcount_opt(BufferLength) PUNICODE_STRING Buffer, - __in ULONG BufferLength, - __out_opt PULONG ReturnLength - ); - -NTSTATUS KphOpenProcessJob( - __in HANDLE KphHandle, - __out PHANDLE JobHandle, - __in HANDLE ProcessHandle, - __in ACCESS_MASK DesiredAccess - ); - -NTSTATUS KphGetContextThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __inout PCONTEXT ThreadContext - ); - -NTSTATUS KphSetContextThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in PCONTEXT ThreadContext - ); - -NTSTATUS KphGetThreadWin32Thread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __out PPVOID Win32Thread - ); - -NTSTATUS KphDuplicateObject( - __in HANDLE KphHandle, - __in HANDLE SourceProcessHandle, - __in HANDLE SourceHandle, - __in_opt HANDLE TargetProcessHandle, - __out_opt PHANDLE TargetHandle, - __in ACCESS_MASK DesiredAccess, - __in ULONG HandleAttributes, - __in ULONG Options - ); - -NTSTATUS KphZwQueryObject( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __in OBJECT_INFORMATION_CLASS ObjectInformationClass, - __in_bcount_opt(BufferLength) PVOID Buffer, - __in ULONG BufferLength, - __out_opt PULONG ReturnLength - ); - -NTSTATUS KphGetProcessId( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __out PHANDLE ProcessId - ); - -NTSTATUS KphGetThreadId( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __out PHANDLE ThreadId, - __out_opt PHANDLE ProcessId - ); - -NTSTATUS KphTerminateThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in NTSTATUS ExitStatus - ); - -NTSTATUS KphSetHandleGrantedAccess( - __in HANDLE KphHandle, - __in HANDLE Handle, - __in ACCESS_MASK GrantedAccess - ); - -NTSTATUS KphAssignImpersonationToken( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in HANDLE TokenHandle - ); - -NTSTATUS KphProtectAdd( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in BOOLEAN AllowKernelMode, - __in ACCESS_MASK ProcessAllowMask, - __in ACCESS_MASK ThreadAllowMask - ); - -NTSTATUS KphProtectRemove( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle - ); - -NTSTATUS KphProtectQuery( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __out PBOOLEAN AllowKernelMode, - __out PACCESS_MASK ProcessAllowMask, - __out PACCESS_MASK ThreadAllowMask - ); - NTSTATUS KphUnsafeReadVirtualMemory( __in HANDLE KphHandle, __in HANDLE ProcessHandle, @@ -363,76 +190,28 @@ NTSTATUS KphUnsafeReadVirtualMemory( __out_opt PULONG ReturnLength ); +NTSTATUS KphGetProcessProtected( + __in HANDLE KphHandle, + __in HANDLE ProcessId, + __out PBOOLEAN IsProtected + ); + +NTSTATUS KphSetProcessProtected( + __in HANDLE KphHandle, + __in HANDLE ProcessId, + __in BOOLEAN IsProtected + ); + NTSTATUS KphSetExecuteOptions( __in HANDLE KphHandle, __in HANDLE ProcessHandle, __in ULONG ExecuteOptions ); -NTSTATUS KphQueryProcessHandles( +NTSTATUS KphSetProcessToken( __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __out_bcount_opt(BufferLength) PVOID Buffer, - __in_opt ULONG BufferLength, - __out_opt PULONG ReturnLength - ); - -NTSTATUS KphOpenThreadProcess( - __in HANDLE KphHandle, - __out PHANDLE ProcessHandle, - __in HANDLE ThreadHandle, - __in ACCESS_MASK DesiredAccess - ); - -NTSTATUS KphCaptureStackBackTraceThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in ULONG FramesToSkip, - __in ULONG FramesToCapture, - __out_ecount(FramesToCapture) PPVOID BackTrace, - __out_opt PULONG CapturedFrames, - __out_opt PULONG BackTraceHash - ); - -NTSTATUS KphDangerousTerminateThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in NTSTATUS ExitStatus - ); - -NTSTATUS KphOpenType( - __in HANDLE KphHandle, - __out PHANDLE TypeHandle, - __in POBJECT_ATTRIBUTES ObjectAttributes - ); - -NTSTATUS KphOpenDriver( - __in HANDLE KphHandle, - __out PHANDLE DriverHandle, - __in POBJECT_ATTRIBUTES ObjectAttributes - ); - -NTSTATUS KphQueryInformationDriver( - __in HANDLE KphHandle, - __in HANDLE DriverHandle, - __in DRIVER_INFORMATION_CLASS DriverInformationClass, - __out_bcount_opt(DriverInformationLength) PVOID DriverInformation, - __in ULONG DriverInformationLength, - __out_opt PULONG ReturnLength - ); - -NTSTATUS KphOpenDirectoryObject( - __in HANDLE KphHandle, - __out PHANDLE DirectoryHandle, - __in ACCESS_MASK DesiredAccess, - __in POBJECT_ATTRIBUTES ObjectAttributes - ); - -NTSTATUS KphOpenNamedObject( - __in HANDLE KphHandle, - __out PHANDLE Handle, - __in ACCESS_MASK DesiredAccess, - __in POBJECT_ATTRIBUTES ObjectAttributes + __in HANDLE SourceProcessId, + __in HANDLE TargetProcessId ); NTSTATUS KphQueryInformationProcess( @@ -469,4 +248,165 @@ NTSTATUS KphSetInformationThread( __in ULONG ThreadInformationLength ); +NTSTATUS KphOpenThread( + __in HANDLE KphHandle, + __out PHANDLE ThreadHandle, + __in HANDLE ThreadId, + __in ACCESS_MASK DesiredAccess + ); + +NTSTATUS KphOpenThreadProcess( + __in HANDLE KphHandle, + __out PHANDLE ProcessHandle, + __in HANDLE ThreadHandle, + __in ACCESS_MASK DesiredAccess + ); + +NTSTATUS KphTerminateThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in NTSTATUS ExitStatus + ); + +NTSTATUS KphDangerousTerminateThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in NTSTATUS ExitStatus + ); + +NTSTATUS KphGetContextThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __inout PCONTEXT ThreadContext + ); + +NTSTATUS KphSetContextThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in PCONTEXT ThreadContext + ); + +NTSTATUS KphCaptureStackBackTraceThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in ULONG FramesToSkip, + __in ULONG FramesToCapture, + __out_ecount(FramesToCapture) PPVOID BackTrace, + __out_opt PULONG CapturedFrames, + __out_opt PULONG BackTraceHash + ); + +NTSTATUS KphGetThreadWin32Thread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __out PPVOID Win32Thread + ); + +NTSTATUS KphAssignImpersonationToken( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in HANDLE TokenHandle + ); + +NTSTATUS KphQueryProcessHandles( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __out_bcount_opt(BufferLength) PVOID Buffer, + __in_opt ULONG BufferLength, + __out_opt PULONG ReturnLength + ); + +NTSTATUS KphGetHandleObjectName( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __out_bcount_opt(BufferLength) PUNICODE_STRING Buffer, + __in ULONG BufferLength, + __out_opt PULONG ReturnLength + ); + +NTSTATUS KphZwQueryObject( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __in OBJECT_INFORMATION_CLASS ObjectInformationClass, + __in_bcount_opt(BufferLength) PVOID Buffer, + __in ULONG BufferLength, + __out_opt PULONG ReturnLength + ); + +NTSTATUS KphDuplicateObject( + __in HANDLE KphHandle, + __in HANDLE SourceProcessHandle, + __in HANDLE SourceHandle, + __in_opt HANDLE TargetProcessHandle, + __out_opt PHANDLE TargetHandle, + __in ACCESS_MASK DesiredAccess, + __in ULONG HandleAttributes, + __in ULONG Options + ); + +NTSTATUS KphSetHandleAttributes( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __in ULONG Flags + ); + +NTSTATUS KphSetHandleGrantedAccess( + __in HANDLE KphHandle, + __in HANDLE Handle, + __in ACCESS_MASK GrantedAccess + ); + +NTSTATUS KphGetProcessId( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __out PHANDLE ProcessId + ); + +NTSTATUS KphGetThreadId( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __out PHANDLE ThreadId, + __out_opt PHANDLE ProcessId + ); + +NTSTATUS KphOpenNamedObject( + __in HANDLE KphHandle, + __out PHANDLE Handle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS KphOpenDirectoryObject( + __in HANDLE KphHandle, + __out PHANDLE DirectoryHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS KphOpenDriver( + __in HANDLE KphHandle, + __out PHANDLE DriverHandle, + __in POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS KphQueryInformationDriver( + __in HANDLE KphHandle, + __in HANDLE DriverHandle, + __in DRIVER_INFORMATION_CLASS DriverInformationClass, + __out_bcount_opt(DriverInformationLength) PVOID DriverInformation, + __in ULONG DriverInformationLength, + __out_opt PULONG ReturnLength + ); + +NTSTATUS KphOpenType( + __in HANDLE KphHandle, + __out PHANDLE TypeHandle, + __in POBJECT_ATTRIBUTES ObjectAttributes + ); + #endif diff --git a/2.x/trunk/phlib/kph.c b/2.x/trunk/phlib/kph.c index 995280610..2997f5121 100644 --- a/2.x/trunk/phlib/kph.c +++ b/2.x/trunk/phlib/kph.c @@ -109,7 +109,7 @@ NTSTATUS KphConnect2( BOOLEAN created = FALSE; if (!DeviceName) - DeviceName = L"KProcessHacker"; + DeviceName = L"KProcessHacker2"; _snwprintf(fullDeviceName, MAX_PATH, L"\\Device\\%s", DeviceName); @@ -271,61 +271,6 @@ NTSTATUS KphGetFeatures( return status; } -NTSTATUS KphCloseHandle( - __in HANDLE KphHandle, - __in HANDLE Handle - ) -{ - struct - { - HANDLE Handle; - } args; - - args.Handle = Handle; - - return KphpDeviceIoControl( - KphHandle, - KPH_CLOSEHANDLE, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphSsQueryClientEntry( - __in HANDLE KphHandle, - __in HANDLE ClientEntryHandle, - __out PKPHSS_CLIENT_INFORMATION ClientInformation, - __in ULONG ClientInformationLength, - __out PULONG ReturnLength - ) -{ - struct - { - HANDLE ClientEntryHandle; - PKPHSS_CLIENT_INFORMATION ClientInformation; - ULONG ClientInformationLength; - PULONG ReturnLength; - } args; - - args.ClientEntryHandle = ClientEntryHandle; - args.ClientInformation = ClientInformation; - args.ClientInformationLength = ClientInformationLength; - args.ReturnLength = ReturnLength; - - return KphpDeviceIoControl( - KphHandle, - KPH_SSQUERYCLIENTENTRY, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - NTSTATUS KphOpenProcess( __in HANDLE KphHandle, __out PHANDLE ProcessHandle, @@ -365,45 +310,6 @@ NTSTATUS KphOpenProcess( return status; } -NTSTATUS KphOpenThread( - __in HANDLE KphHandle, - __out PHANDLE ThreadHandle, - __in HANDLE ThreadId, - __in ACCESS_MASK DesiredAccess - ) -{ - NTSTATUS status; - struct - { - HANDLE ThreadId; - ACCESS_MASK DesiredAccess; - } args; - struct - { - HANDLE ThreadHandle; - } ret; - - args.ThreadId = ThreadId; - args.DesiredAccess = DesiredAccess; - - status = KphpDeviceIoControl( - KphHandle, - KPH_OPENTHREAD, - &args, - sizeof(args), - &ret, - sizeof(ret), - NULL - ); - - if (NT_SUCCESS(status)) - { - *ThreadHandle = ret.ThreadHandle; - } - - return status; -} - NTSTATUS KphOpenProcessToken( __in HANDLE KphHandle, __out PHANDLE TokenHandle, @@ -443,27 +349,30 @@ NTSTATUS KphOpenProcessToken( return status; } -NTSTATUS KphGetProcessProtected( +NTSTATUS KphOpenProcessJob( __in HANDLE KphHandle, - __in HANDLE ProcessId, - __out PBOOLEAN IsProtected + __out PHANDLE JobHandle, + __in HANDLE ProcessHandle, + __in ACCESS_MASK DesiredAccess ) { NTSTATUS status; struct { - HANDLE ProcessId; + HANDLE ProcessHandle; + ACCESS_MASK DesiredAccess; } args; struct { - BOOLEAN IsProtected; + HANDLE JobHandle; } ret; - args.ProcessId = ProcessId; + args.ProcessHandle = ProcessHandle; + args.DesiredAccess = DesiredAccess; status = KphpDeviceIoControl( KphHandle, - KPH_GETPROCESSPROTECTED, + KPH_OPENPROCESSJOB, &args, sizeof(args), &ret, @@ -473,69 +382,7 @@ NTSTATUS KphGetProcessProtected( if (NT_SUCCESS(status)) { - *IsProtected = ret.IsProtected; - } - - return status; -} - -NTSTATUS KphSetProcessProtected( - __in HANDLE KphHandle, - __in HANDLE ProcessId, - __in BOOLEAN IsProtected - ) -{ - struct - { - HANDLE ProcessId; - BOOLEAN IsProtected; - } args; - - args.ProcessId = ProcessId; - args.IsProtected = IsProtected; - - return KphpDeviceIoControl( - KphHandle, - KPH_SETPROCESSPROTECTED, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphTerminateProcess( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in NTSTATUS ExitStatus - ) -{ - NTSTATUS status = STATUS_SUCCESS; - struct - { - HANDLE ProcessHandle; - NTSTATUS ExitStatus; - } args; - - args.ProcessHandle = ProcessHandle; - args.ExitStatus = ExitStatus; - - status = KphpDeviceIoControl( - KphHandle, - KPH_TERMINATEPROCESS, - &args, - sizeof(args), - NULL, - 0, - NULL - ); - - /* Check if we were trying to terminate the current - * process and do it now. */ - if (status == STATUS_CANT_TERMINATE_SELF) - { - RtlExitUserProcess(ExitStatus); + *JobHandle = ret.JobHandle; } return status; @@ -587,6 +434,42 @@ NTSTATUS KphResumeProcess( ); } +NTSTATUS KphTerminateProcess( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in NTSTATUS ExitStatus + ) +{ + NTSTATUS status = STATUS_SUCCESS; + struct + { + HANDLE ProcessHandle; + NTSTATUS ExitStatus; + } args; + + args.ProcessHandle = ProcessHandle; + args.ExitStatus = ExitStatus; + + status = KphpDeviceIoControl( + KphHandle, + KPH_TERMINATEPROCESS, + &args, + sizeof(args), + NULL, + 0, + NULL + ); + + /* Check if we were trying to terminate the current + * process and do it now. */ + if (status == STATUS_CANT_TERMINATE_SELF) + { + RtlExitUserProcess(ExitStatus); + } + + return status; +} + NTSTATUS KphReadVirtualMemory( __in HANDLE KphHandle, __in HANDLE ProcessHandle, @@ -657,690 +540,6 @@ NTSTATUS KphWriteVirtualMemory( ); } -NTSTATUS KphSetProcessToken( - __in HANDLE KphHandle, - __in HANDLE SourceProcessId, - __in HANDLE TargetProcessId - ) -{ - struct - { - HANDLE SourceProcessId; - HANDLE TargetProcessId; - } args; - - args.SourceProcessId = SourceProcessId; - args.TargetProcessId = TargetProcessId; - - return KphpDeviceIoControl( - KphHandle, - KPH_SETPROCESSTOKEN, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphGetThreadStartAddress( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __out PPVOID StartAddress - ) -{ - NTSTATUS status; - struct - { - HANDLE ThreadHandle; - } args; - struct - { - PVOID StartAddress; - } ret; - - args.ThreadHandle = ThreadHandle; - - status = KphpDeviceIoControl( - KphHandle, - KPH_GETTHREADSTARTADDRESS, - &args, - sizeof(args), - &ret, - sizeof(ret), - NULL - ); - - if (NT_SUCCESS(status)) - { - *StartAddress = ret.StartAddress; - } - - return status; -} - -NTSTATUS KphSetHandleAttributes( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __in ULONG Flags - ) -{ - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - ULONG Flags; - } args; - - args.ProcessHandle = ProcessHandle; - args.Handle = Handle; - args.Flags = Flags; - - return KphpDeviceIoControl( - KphHandle, - KPH_SETHANDLEATTRIBUTES, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphGetHandleObjectName( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __out_bcount_opt(BufferLength) PUNICODE_STRING Buffer, - __in ULONG BufferLength, - __out_opt PULONG ReturnLength - ) -{ - NTSTATUS status; - UNICODE_STRING buffer; - ULONG returnLength; - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - } args; - - args.ProcessHandle = ProcessHandle; - args.Handle = Handle; - - if (Buffer && BufferLength >= sizeof(UNICODE_STRING)) - { - status = KphpDeviceIoControl( - KphHandle, - KPH_GETHANDLEOBJECTNAME, - &args, - sizeof(args), - Buffer, - BufferLength, - &returnLength - ); - - Buffer->Buffer = (PWSTR)PTR_ADD_OFFSET(Buffer, sizeof(UNICODE_STRING)); - - if (ReturnLength) - { - if (status == STATUS_BUFFER_TOO_SMALL) - *ReturnLength = Buffer->Length; - else - *ReturnLength = returnLength; - } - } - else - { - // User doesn't give us a buffer, or it was too small. - // Use our internal buffer. - status = KphpDeviceIoControl( - KphHandle, - KPH_GETHANDLEOBJECTNAME, - &args, - sizeof(args), - &buffer, - sizeof(UNICODE_STRING), - &returnLength - ); - - if (ReturnLength) - { - if (status == STATUS_BUFFER_TOO_SMALL) - *ReturnLength = buffer.Length; - else - *ReturnLength = returnLength; - } - } - - return status; -} - -NTSTATUS KphOpenProcessJob( - __in HANDLE KphHandle, - __out PHANDLE JobHandle, - __in HANDLE ProcessHandle, - __in ACCESS_MASK DesiredAccess - ) -{ - NTSTATUS status; - struct - { - HANDLE ProcessHandle; - ACCESS_MASK DesiredAccess; - } args; - struct - { - HANDLE JobHandle; - } ret; - - args.ProcessHandle = ProcessHandle; - args.DesiredAccess = DesiredAccess; - - status = KphpDeviceIoControl( - KphHandle, - KPH_OPENPROCESSJOB, - &args, - sizeof(args), - &ret, - sizeof(ret), - NULL - ); - - if (NT_SUCCESS(status)) - { - *JobHandle = ret.JobHandle; - } - - return status; -} - -NTSTATUS KphGetContextThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __inout PCONTEXT ThreadContext - ) -{ - struct - { - HANDLE ThreadHandle; - PCONTEXT ThreadContext; - } args; - - args.ThreadHandle = ThreadHandle; - args.ThreadContext = ThreadContext; - - return KphpDeviceIoControl( - KphHandle, - KPH_GETCONTEXTTHREAD, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphSetContextThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in PCONTEXT ThreadContext - ) -{ - struct - { - HANDLE ThreadHandle; - PCONTEXT ThreadContext; - } args; - - args.ThreadHandle = ThreadHandle; - args.ThreadContext = ThreadContext; - - return KphpDeviceIoControl( - KphHandle, - KPH_SETCONTEXTTHREAD, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphGetThreadWin32Thread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __out PPVOID Win32Thread - ) -{ - NTSTATUS status; - struct - { - HANDLE ThreadHandle; - } args; - struct - { - PVOID Win32Thread; - } ret; - - args.ThreadHandle = ThreadHandle; - - status = KphpDeviceIoControl( - KphHandle, - KPH_GETTHREADWIN32THREAD, - &args, - sizeof(args), - &ret, - sizeof(ret), - NULL - ); - - if (NT_SUCCESS(status)) - { - *Win32Thread = ret.Win32Thread; - } - - return status; -} - -NTSTATUS KphDuplicateObject( - __in HANDLE KphHandle, - __in HANDLE SourceProcessHandle, - __in HANDLE SourceHandle, - __in_opt HANDLE TargetProcessHandle, - __out_opt PHANDLE TargetHandle, - __in ACCESS_MASK DesiredAccess, - __in ULONG HandleAttributes, - __in ULONG Options - ) -{ - struct - { - HANDLE SourceProcessHandle; - HANDLE SourceHandle; - HANDLE TargetProcessHandle; - PHANDLE TargetHandle; - ACCESS_MASK DesiredAccess; - ULONG HandleAttributes; - ULONG Options; - } args; - - args.SourceProcessHandle = SourceProcessHandle; - args.SourceHandle = SourceHandle; - args.TargetProcessHandle = TargetProcessHandle; - args.TargetHandle = TargetHandle; - args.DesiredAccess = DesiredAccess; - args.HandleAttributes = HandleAttributes; - args.Options = Options; - - return KphpDeviceIoControl( - KphHandle, - KPH_DUPLICATEOBJECT, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphZwQueryObject( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __in OBJECT_INFORMATION_CLASS ObjectInformationClass, - __in_bcount_opt(BufferLength) PVOID Buffer, - __in ULONG BufferLength, - __out_opt PULONG ReturnLength - ) -{ - NTSTATUS status; - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - OBJECT_INFORMATION_CLASS ObjectInformationClass; - } args; - PKPH_ZWQUERYOBJECT_BUFFER ret; - ULONG retLength; - - // Make sure we understand the object information class - // because we will be fixing the buffer later. - if ( - ObjectInformationClass != ObjectBasicInformation && - ObjectInformationClass != ObjectNameInformation && - ObjectInformationClass != ObjectTypeInformation - ) - return STATUS_INVALID_INFO_CLASS; - - args.ProcessHandle = ProcessHandle; - args.Handle = Handle; - args.ObjectInformationClass = ObjectInformationClass; - - retLength = FIELD_OFFSET(KPH_ZWQUERYOBJECT_BUFFER, Buffer) + BufferLength; - ret = PhAllocate(retLength); - status = KphpDeviceIoControl( - KphHandle, - KPH_ZWQUERYOBJECT, - &args, - sizeof(args), - ret, - retLength, - NULL - ); - - // Make sure the actual I/O control request succeeded. - if (NT_SUCCESS(status)) - { - // Check if ZwQueryObject succeeded. - status = ret->Status; - - if (NT_SUCCESS(status)) - { - if (Buffer) - { - // Copy the buffer contents to the user buffer. - memcpy(Buffer, ret->Buffer, ret->ReturnLength); - - // Rebase pointers in the buffer. - if (ObjectInformationClass == ObjectNameInformation) - { - POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION)Buffer; - - nameInfo->Name.Buffer = (PWSTR)REBASE_ADDRESS( - nameInfo->Name.Buffer, - ret->BufferBase, - Buffer - ); - } - else if (ObjectInformationClass == ObjectTypeInformation) - { - POBJECT_TYPE_INFORMATION typeInfo = (POBJECT_TYPE_INFORMATION)Buffer; - - typeInfo->TypeName.Buffer = (PWSTR)REBASE_ADDRESS( - typeInfo->TypeName.Buffer, - ret->BufferBase, - Buffer - ); - } - } - } - - if (ReturnLength) - *ReturnLength = ret->ReturnLength; - } - - PhFree(ret); - - return status; -} - -NTSTATUS KphGetProcessId( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __out PHANDLE ProcessId - ) -{ - NTSTATUS status; - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - } args; - struct - { - HANDLE ProcessId; - } ret; - - args.ProcessHandle = ProcessHandle; - args.Handle = Handle; - - status = KphpDeviceIoControl( - KphHandle, - KPH_GETPROCESSID, - &args, - sizeof(args), - &ret, - sizeof(ret), - NULL - ); - - if (NT_SUCCESS(status)) - { - *ProcessId = ret.ProcessId; - } - - return status; -} - -NTSTATUS KphGetThreadId( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in HANDLE Handle, - __out PHANDLE ThreadId, - __out_opt PHANDLE ProcessId - ) -{ - NTSTATUS status; - struct - { - HANDLE ProcessHandle; - HANDLE Handle; - } args; - struct - { - HANDLE ThreadId; - HANDLE ProcessId; - } ret; - - args.ProcessHandle = ProcessHandle; - args.Handle = Handle; - - status = KphpDeviceIoControl( - KphHandle, - KPH_GETTHREADID, - &args, - sizeof(args), - &ret, - sizeof(ret), - NULL - ); - - if (NT_SUCCESS(status)) - { - *ThreadId = ret.ThreadId; - - if (ProcessId) - *ProcessId = ret.ProcessId; - } - - return status; -} - -NTSTATUS KphTerminateThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in NTSTATUS ExitStatus - ) -{ - NTSTATUS status = STATUS_SUCCESS; - struct - { - HANDLE ThreadHandle; - NTSTATUS ExitStatus; - } args; - - args.ThreadHandle = ThreadHandle; - args.ExitStatus = ExitStatus; - - status = KphpDeviceIoControl( - KphHandle, - KPH_TERMINATETHREAD, - &args, - sizeof(args), - NULL, - 0, - NULL - ); - - if (status == STATUS_CANT_TERMINATE_SELF) - { - RtlExitUserThread(ExitStatus); - } - - return status; -} - -NTSTATUS KphSetHandleGrantedAccess( - __in HANDLE KphHandle, - __in HANDLE Handle, - __in ACCESS_MASK GrantedAccess - ) -{ - struct - { - HANDLE Handle; - ACCESS_MASK GrantedAccess; - } args; - - args.Handle = Handle; - args.GrantedAccess = GrantedAccess; - - return KphpDeviceIoControl( - KphHandle, - KPH_SETHANDLEGRANTEDACCESS, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphAssignImpersonationToken( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in HANDLE TokenHandle - ) -{ - struct - { - HANDLE ThreadHandle; - HANDLE TokenHandle; - } args; - - args.ThreadHandle = ThreadHandle; - args.TokenHandle = TokenHandle; - - return KphpDeviceIoControl( - KphHandle, - KPH_ASSIGNIMPERSONATIONTOKEN, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphProtectAdd( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __in BOOLEAN AllowKernelMode, - __in ACCESS_MASK ProcessAllowMask, - __in ACCESS_MASK ThreadAllowMask - ) -{ - struct - { - HANDLE ProcessHandle; - LOGICAL AllowKernelMode; - ACCESS_MASK ProcessAllowMask; - ACCESS_MASK ThreadAllowMask; - } args; - - args.ProcessHandle = ProcessHandle; - args.AllowKernelMode = AllowKernelMode; - args.ProcessAllowMask = ProcessAllowMask; - args.ThreadAllowMask = ThreadAllowMask; - - return KphpDeviceIoControl( - KphHandle, - KPH_PROTECTADD, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphProtectRemove( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle - ) -{ - struct - { - HANDLE ProcessHandle; - } args; - - args.ProcessHandle = ProcessHandle; - - return KphpDeviceIoControl( - KphHandle, - KPH_PROTECTREMOVE, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphProtectQuery( - __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __out PBOOLEAN AllowKernelMode, - __out PACCESS_MASK ProcessAllowMask, - __out PACCESS_MASK ThreadAllowMask - ) -{ - NTSTATUS status = STATUS_SUCCESS; - struct - { - HANDLE ProcessHandle; - PLOGICAL AllowKernelMode; - PACCESS_MASK ProcessAllowMask; - PACCESS_MASK ThreadAllowMask; - } args; - LOGICAL allowKernelMode; - - args.ProcessHandle = ProcessHandle; - args.AllowKernelMode = &allowKernelMode; - args.ProcessAllowMask = ProcessAllowMask; - args.ThreadAllowMask = ThreadAllowMask; - - status = KphpDeviceIoControl( - KphHandle, - KPH_PROTECTQUERY, - &args, - sizeof(args), - NULL, - 0, - NULL - ); - - if (NT_SUCCESS(status)) - { - *AllowKernelMode = (BOOLEAN)allowKernelMode; - } - - return status; -} - NTSTATUS KphUnsafeReadVirtualMemory( __in HANDLE KphHandle, __in HANDLE ProcessHandle, @@ -1376,6 +575,68 @@ NTSTATUS KphUnsafeReadVirtualMemory( ); } +NTSTATUS KphGetProcessProtected( + __in HANDLE KphHandle, + __in HANDLE ProcessId, + __out PBOOLEAN IsProtected + ) +{ + NTSTATUS status; + struct + { + HANDLE ProcessId; + } args; + struct + { + BOOLEAN IsProtected; + } ret; + + args.ProcessId = ProcessId; + + status = KphpDeviceIoControl( + KphHandle, + KPH_GETPROCESSPROTECTED, + &args, + sizeof(args), + &ret, + sizeof(ret), + NULL + ); + + if (NT_SUCCESS(status)) + { + *IsProtected = ret.IsProtected; + } + + return status; +} + +NTSTATUS KphSetProcessProtected( + __in HANDLE KphHandle, + __in HANDLE ProcessId, + __in BOOLEAN IsProtected + ) +{ + struct + { + HANDLE ProcessId; + BOOLEAN IsProtected; + } args; + + args.ProcessId = ProcessId; + args.IsProtected = IsProtected; + + return KphpDeviceIoControl( + KphHandle, + KPH_SETPROCESSPROTECTED, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + NTSTATUS KphSetExecuteOptions( __in HANDLE KphHandle, __in HANDLE ProcessHandle, @@ -1402,279 +663,24 @@ NTSTATUS KphSetExecuteOptions( ); } -NTSTATUS KphQueryProcessHandles( +NTSTATUS KphSetProcessToken( __in HANDLE KphHandle, - __in HANDLE ProcessHandle, - __out_bcount_opt(BufferLength) PVOID Buffer, - __in_opt ULONG BufferLength, - __out_opt PULONG ReturnLength + __in HANDLE SourceProcessId, + __in HANDLE TargetProcessId ) { struct { - HANDLE ProcessHandle; - PVOID Buffer; - ULONG BufferLength; - PULONG ReturnLength; + HANDLE SourceProcessId; + HANDLE TargetProcessId; } args; - args.ProcessHandle = ProcessHandle; - args.Buffer = Buffer; - args.BufferLength = BufferLength; - args.ReturnLength = ReturnLength; + args.SourceProcessId = SourceProcessId; + args.TargetProcessId = TargetProcessId; return KphpDeviceIoControl( KphHandle, - KPH_QUERYPROCESSHANDLES, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphOpenThreadProcess( - __in HANDLE KphHandle, - __out PHANDLE ProcessHandle, - __in HANDLE ThreadHandle, - __in ACCESS_MASK DesiredAccess - ) -{ - NTSTATUS status; - - struct - { - HANDLE ThreadHandle; - ACCESS_MASK DesiredAccess; - } args; - struct - { - HANDLE ProcessHandle; - } ret; - - args.ThreadHandle = ThreadHandle; - args.DesiredAccess = DesiredAccess; - - status = KphpDeviceIoControl( - KphHandle, - KPH_OPENTHREADPROCESS, - &args, - sizeof(args), - &ret, - sizeof(ret), - NULL - ); - - if (NT_SUCCESS(status)) - { - *ProcessHandle = ret.ProcessHandle; - } - - return status; -} - -NTSTATUS KphCaptureStackBackTraceThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in ULONG FramesToSkip, - __in ULONG FramesToCapture, - __out_ecount(FramesToCapture) PPVOID BackTrace, - __out_opt PULONG CapturedFrames, - __out_opt PULONG BackTraceHash - ) -{ - struct - { - HANDLE ThreadHandle; - ULONG FramesToSkip; - ULONG FramesToCapture; - PPVOID BackTrace; - PULONG CapturedFrames; - PULONG BackTraceHash; - } args; - - args.ThreadHandle = ThreadHandle; - args.FramesToSkip = FramesToSkip; - args.FramesToCapture = FramesToCapture; - args.BackTrace = BackTrace; - args.CapturedFrames = CapturedFrames; - args.BackTraceHash = BackTraceHash; - - return KphpDeviceIoControl( - KphHandle, - KPH_CAPTURESTACKBACKTRACETHREAD, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphDangerousTerminateThread( - __in HANDLE KphHandle, - __in HANDLE ThreadHandle, - __in NTSTATUS ExitStatus - ) -{ - struct - { - HANDLE ThreadHandle; - NTSTATUS ExitStatus; - } args; - - args.ThreadHandle = ThreadHandle; - args.ExitStatus = ExitStatus; - - return KphpDeviceIoControl( - KphHandle, - KPH_DANGEROUSTERMINATETHREAD, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphOpenType( - __in HANDLE KphHandle, - __out PHANDLE TypeHandle, - __in POBJECT_ATTRIBUTES ObjectAttributes - ) -{ - struct - { - PHANDLE TypeHandle; - POBJECT_ATTRIBUTES ObjectAttributes; - } args; - - args.TypeHandle = TypeHandle; - args.ObjectAttributes = ObjectAttributes; - - return KphpDeviceIoControl( - KphHandle, - KPH_OPENTYPE, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphOpenDriver( - __in HANDLE KphHandle, - __out PHANDLE DriverHandle, - __in POBJECT_ATTRIBUTES ObjectAttributes - ) -{ - struct - { - PHANDLE DriverHandle; - POBJECT_ATTRIBUTES ObjectAttributes; - } args; - - args.DriverHandle = DriverHandle; - args.ObjectAttributes = ObjectAttributes; - - return KphpDeviceIoControl( - KphHandle, - KPH_OPENDRIVER, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphQueryInformationDriver( - __in HANDLE KphHandle, - __in HANDLE DriverHandle, - __in DRIVER_INFORMATION_CLASS DriverInformationClass, - __out_bcount_opt(DriverInformationLength) PVOID DriverInformation, - __in ULONG DriverInformationLength, - __out_opt PULONG ReturnLength - ) -{ - struct - { - HANDLE DriverHandle; - DRIVER_INFORMATION_CLASS DriverInformationClass; - PVOID DriverInformation; - ULONG DriverInformationLength; - PULONG ReturnLength; - } args; - - args.DriverHandle = DriverHandle; - args.DriverInformationClass = DriverInformationClass; - args.DriverInformation = DriverInformation; - args.DriverInformationLength = DriverInformationLength; - args.ReturnLength = ReturnLength; - - return KphpDeviceIoControl( - KphHandle, - KPH_QUERYINFORMATIONDRIVER, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphOpenDirectoryObject( - __in HANDLE KphHandle, - __out PHANDLE DirectoryHandle, - __in ACCESS_MASK DesiredAccess, - __in POBJECT_ATTRIBUTES ObjectAttributes - ) -{ - struct - { - PHANDLE DirectoryHandle; - ACCESS_MASK DesiredAccess; - POBJECT_ATTRIBUTES ObjectAttributes; - } args; - - args.DirectoryHandle = DirectoryHandle; - args.DesiredAccess = DesiredAccess; - args.ObjectAttributes = ObjectAttributes; - - return KphpDeviceIoControl( - KphHandle, - KPH_OPENDIRECTORYOBJECT, - &args, - sizeof(args), - NULL, - 0, - NULL - ); -} - -NTSTATUS KphOpenNamedObject( - __in HANDLE KphHandle, - __out PHANDLE Handle, - __in ACCESS_MASK DesiredAccess, - __in POBJECT_ATTRIBUTES ObjectAttributes - ) -{ - struct - { - PHANDLE Handle; - ACCESS_MASK DesiredAccess; - POBJECT_ATTRIBUTES ObjectAttributes; - } args; - - args.Handle = Handle; - args.DesiredAccess = DesiredAccess; - args.ObjectAttributes = ObjectAttributes; - - return KphpDeviceIoControl( - KphHandle, - KPH_OPENNAMEDOBJECT, + KPH_SETPROCESSTOKEN, &args, sizeof(args), NULL, @@ -1816,3 +822,820 @@ NTSTATUS KphSetInformationThread( NULL ); } + +NTSTATUS KphOpenThread( + __in HANDLE KphHandle, + __out PHANDLE ThreadHandle, + __in HANDLE ThreadId, + __in ACCESS_MASK DesiredAccess + ) +{ + NTSTATUS status; + struct + { + HANDLE ThreadId; + ACCESS_MASK DesiredAccess; + } args; + struct + { + HANDLE ThreadHandle; + } ret; + + args.ThreadId = ThreadId; + args.DesiredAccess = DesiredAccess; + + status = KphpDeviceIoControl( + KphHandle, + KPH_OPENTHREAD, + &args, + sizeof(args), + &ret, + sizeof(ret), + NULL + ); + + if (NT_SUCCESS(status)) + { + *ThreadHandle = ret.ThreadHandle; + } + + return status; +} + +NTSTATUS KphOpenThreadProcess( + __in HANDLE KphHandle, + __out PHANDLE ProcessHandle, + __in HANDLE ThreadHandle, + __in ACCESS_MASK DesiredAccess + ) +{ + NTSTATUS status; + + struct + { + HANDLE ThreadHandle; + ACCESS_MASK DesiredAccess; + } args; + struct + { + HANDLE ProcessHandle; + } ret; + + args.ThreadHandle = ThreadHandle; + args.DesiredAccess = DesiredAccess; + + status = KphpDeviceIoControl( + KphHandle, + KPH_OPENTHREADPROCESS, + &args, + sizeof(args), + &ret, + sizeof(ret), + NULL + ); + + if (NT_SUCCESS(status)) + { + *ProcessHandle = ret.ProcessHandle; + } + + return status; +} + +NTSTATUS KphTerminateThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in NTSTATUS ExitStatus + ) +{ + NTSTATUS status = STATUS_SUCCESS; + struct + { + HANDLE ThreadHandle; + NTSTATUS ExitStatus; + } args; + + args.ThreadHandle = ThreadHandle; + args.ExitStatus = ExitStatus; + + status = KphpDeviceIoControl( + KphHandle, + KPH_TERMINATETHREAD, + &args, + sizeof(args), + NULL, + 0, + NULL + ); + + if (status == STATUS_CANT_TERMINATE_SELF) + { + RtlExitUserThread(ExitStatus); + } + + return status; +} + +NTSTATUS KphDangerousTerminateThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in NTSTATUS ExitStatus + ) +{ + struct + { + HANDLE ThreadHandle; + NTSTATUS ExitStatus; + } args; + + args.ThreadHandle = ThreadHandle; + args.ExitStatus = ExitStatus; + + return KphpDeviceIoControl( + KphHandle, + KPH_DANGEROUSTERMINATETHREAD, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphGetContextThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __inout PCONTEXT ThreadContext + ) +{ + struct + { + HANDLE ThreadHandle; + PCONTEXT ThreadContext; + } args; + + args.ThreadHandle = ThreadHandle; + args.ThreadContext = ThreadContext; + + return KphpDeviceIoControl( + KphHandle, + KPH_GETCONTEXTTHREAD, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphSetContextThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in PCONTEXT ThreadContext + ) +{ + struct + { + HANDLE ThreadHandle; + PCONTEXT ThreadContext; + } args; + + args.ThreadHandle = ThreadHandle; + args.ThreadContext = ThreadContext; + + return KphpDeviceIoControl( + KphHandle, + KPH_SETCONTEXTTHREAD, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphCaptureStackBackTraceThread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in ULONG FramesToSkip, + __in ULONG FramesToCapture, + __out_ecount(FramesToCapture) PPVOID BackTrace, + __out_opt PULONG CapturedFrames, + __out_opt PULONG BackTraceHash + ) +{ + struct + { + HANDLE ThreadHandle; + ULONG FramesToSkip; + ULONG FramesToCapture; + PPVOID BackTrace; + PULONG CapturedFrames; + PULONG BackTraceHash; + } args; + + args.ThreadHandle = ThreadHandle; + args.FramesToSkip = FramesToSkip; + args.FramesToCapture = FramesToCapture; + args.BackTrace = BackTrace; + args.CapturedFrames = CapturedFrames; + args.BackTraceHash = BackTraceHash; + + return KphpDeviceIoControl( + KphHandle, + KPH_CAPTURESTACKBACKTRACETHREAD, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphGetThreadWin32Thread( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __out PPVOID Win32Thread + ) +{ + NTSTATUS status; + struct + { + HANDLE ThreadHandle; + } args; + struct + { + PVOID Win32Thread; + } ret; + + args.ThreadHandle = ThreadHandle; + + status = KphpDeviceIoControl( + KphHandle, + KPH_GETTHREADWIN32THREAD, + &args, + sizeof(args), + &ret, + sizeof(ret), + NULL + ); + + if (NT_SUCCESS(status)) + { + *Win32Thread = ret.Win32Thread; + } + + return status; +} + +NTSTATUS KphAssignImpersonationToken( + __in HANDLE KphHandle, + __in HANDLE ThreadHandle, + __in HANDLE TokenHandle + ) +{ + struct + { + HANDLE ThreadHandle; + HANDLE TokenHandle; + } args; + + args.ThreadHandle = ThreadHandle; + args.TokenHandle = TokenHandle; + + return KphpDeviceIoControl( + KphHandle, + KPH_ASSIGNIMPERSONATIONTOKEN, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphQueryProcessHandles( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __out_bcount_opt(BufferLength) PVOID Buffer, + __in_opt ULONG BufferLength, + __out_opt PULONG ReturnLength + ) +{ + struct + { + HANDLE ProcessHandle; + PVOID Buffer; + ULONG BufferLength; + PULONG ReturnLength; + } args; + + args.ProcessHandle = ProcessHandle; + args.Buffer = Buffer; + args.BufferLength = BufferLength; + args.ReturnLength = ReturnLength; + + return KphpDeviceIoControl( + KphHandle, + KPH_QUERYPROCESSHANDLES, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphGetHandleObjectName( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __out_bcount_opt(BufferLength) PUNICODE_STRING Buffer, + __in ULONG BufferLength, + __out_opt PULONG ReturnLength + ) +{ + NTSTATUS status; + UNICODE_STRING buffer; + ULONG returnLength; + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + } args; + + args.ProcessHandle = ProcessHandle; + args.Handle = Handle; + + if (Buffer && BufferLength >= sizeof(UNICODE_STRING)) + { + status = KphpDeviceIoControl( + KphHandle, + KPH_GETHANDLEOBJECTNAME, + &args, + sizeof(args), + Buffer, + BufferLength, + &returnLength + ); + + Buffer->Buffer = (PWSTR)PTR_ADD_OFFSET(Buffer, sizeof(UNICODE_STRING)); + + if (ReturnLength) + { + if (status == STATUS_BUFFER_TOO_SMALL) + *ReturnLength = Buffer->Length; + else + *ReturnLength = returnLength; + } + } + else + { + // User doesn't give us a buffer, or it was too small. + // Use our internal buffer. + status = KphpDeviceIoControl( + KphHandle, + KPH_GETHANDLEOBJECTNAME, + &args, + sizeof(args), + &buffer, + sizeof(UNICODE_STRING), + &returnLength + ); + + if (ReturnLength) + { + if (status == STATUS_BUFFER_TOO_SMALL) + *ReturnLength = buffer.Length; + else + *ReturnLength = returnLength; + } + } + + return status; +} + +NTSTATUS KphZwQueryObject( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __in OBJECT_INFORMATION_CLASS ObjectInformationClass, + __in_bcount_opt(BufferLength) PVOID Buffer, + __in ULONG BufferLength, + __out_opt PULONG ReturnLength + ) +{ + NTSTATUS status; + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + OBJECT_INFORMATION_CLASS ObjectInformationClass; + } args; + PKPH_ZWQUERYOBJECT_BUFFER ret; + ULONG retLength; + + // Make sure we understand the object information class + // because we will be fixing the buffer later. + if ( + ObjectInformationClass != ObjectBasicInformation && + ObjectInformationClass != ObjectNameInformation && + ObjectInformationClass != ObjectTypeInformation + ) + return STATUS_INVALID_INFO_CLASS; + + args.ProcessHandle = ProcessHandle; + args.Handle = Handle; + args.ObjectInformationClass = ObjectInformationClass; + + retLength = FIELD_OFFSET(KPH_ZWQUERYOBJECT_BUFFER, Buffer) + BufferLength; + ret = PhAllocate(retLength); + status = KphpDeviceIoControl( + KphHandle, + KPH_ZWQUERYOBJECT, + &args, + sizeof(args), + ret, + retLength, + NULL + ); + + // Make sure the actual I/O control request succeeded. + if (NT_SUCCESS(status)) + { + // Check if ZwQueryObject succeeded. + status = ret->Status; + + if (NT_SUCCESS(status)) + { + if (Buffer) + { + // Copy the buffer contents to the user buffer. + memcpy(Buffer, ret->Buffer, ret->ReturnLength); + + // Rebase pointers in the buffer. + if (ObjectInformationClass == ObjectNameInformation) + { + POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION)Buffer; + + nameInfo->Name.Buffer = (PWSTR)REBASE_ADDRESS( + nameInfo->Name.Buffer, + ret->BufferBase, + Buffer + ); + } + else if (ObjectInformationClass == ObjectTypeInformation) + { + POBJECT_TYPE_INFORMATION typeInfo = (POBJECT_TYPE_INFORMATION)Buffer; + + typeInfo->TypeName.Buffer = (PWSTR)REBASE_ADDRESS( + typeInfo->TypeName.Buffer, + ret->BufferBase, + Buffer + ); + } + } + } + + if (ReturnLength) + *ReturnLength = ret->ReturnLength; + } + + PhFree(ret); + + return status; +} + +NTSTATUS KphDuplicateObject( + __in HANDLE KphHandle, + __in HANDLE SourceProcessHandle, + __in HANDLE SourceHandle, + __in_opt HANDLE TargetProcessHandle, + __out_opt PHANDLE TargetHandle, + __in ACCESS_MASK DesiredAccess, + __in ULONG HandleAttributes, + __in ULONG Options + ) +{ + NTSTATUS status; + struct + { + HANDLE SourceProcessHandle; + HANDLE SourceHandle; + HANDLE TargetProcessHandle; + PHANDLE TargetHandle; + ACCESS_MASK DesiredAccess; + ULONG HandleAttributes; + ULONG Options; + } args; + + args.SourceProcessHandle = SourceProcessHandle; + args.SourceHandle = SourceHandle; + args.TargetProcessHandle = TargetProcessHandle; + args.TargetHandle = TargetHandle; + args.DesiredAccess = DesiredAccess; + args.HandleAttributes = HandleAttributes; + args.Options = Options; + + status = KphpDeviceIoControl( + KphHandle, + KPH_DUPLICATEOBJECT, + &args, + sizeof(args), + NULL, + 0, + NULL + ); + + if (status == STATUS_CANT_TERMINATE_SELF) + { + /* Means we tried to close a handle in the current process. + * Do it now. */ + status = NtClose(SourceHandle); + } + + return status; +} + +NTSTATUS KphSetHandleAttributes( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __in ULONG Flags + ) +{ + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + ULONG Flags; + } args; + + args.ProcessHandle = ProcessHandle; + args.Handle = Handle; + args.Flags = Flags; + + return KphpDeviceIoControl( + KphHandle, + KPH_SETHANDLEATTRIBUTES, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphSetHandleGrantedAccess( + __in HANDLE KphHandle, + __in HANDLE Handle, + __in ACCESS_MASK GrantedAccess + ) +{ + struct + { + HANDLE Handle; + ACCESS_MASK GrantedAccess; + } args; + + args.Handle = Handle; + args.GrantedAccess = GrantedAccess; + + return KphpDeviceIoControl( + KphHandle, + KPH_SETHANDLEGRANTEDACCESS, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphGetProcessId( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __out PHANDLE ProcessId + ) +{ + NTSTATUS status; + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + } args; + struct + { + HANDLE ProcessId; + } ret; + + args.ProcessHandle = ProcessHandle; + args.Handle = Handle; + + status = KphpDeviceIoControl( + KphHandle, + KPH_GETPROCESSID, + &args, + sizeof(args), + &ret, + sizeof(ret), + NULL + ); + + if (NT_SUCCESS(status)) + { + *ProcessId = ret.ProcessId; + } + + return status; +} + +NTSTATUS KphGetThreadId( + __in HANDLE KphHandle, + __in HANDLE ProcessHandle, + __in HANDLE Handle, + __out PHANDLE ThreadId, + __out_opt PHANDLE ProcessId + ) +{ + NTSTATUS status; + struct + { + HANDLE ProcessHandle; + HANDLE Handle; + } args; + struct + { + HANDLE ThreadId; + HANDLE ProcessId; + } ret; + + args.ProcessHandle = ProcessHandle; + args.Handle = Handle; + + status = KphpDeviceIoControl( + KphHandle, + KPH_GETTHREADID, + &args, + sizeof(args), + &ret, + sizeof(ret), + NULL + ); + + if (NT_SUCCESS(status)) + { + *ThreadId = ret.ThreadId; + + if (ProcessId) + *ProcessId = ret.ProcessId; + } + + return status; +} + +NTSTATUS KphOpenNamedObject( + __in HANDLE KphHandle, + __out PHANDLE Handle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes + ) +{ + struct + { + PHANDLE Handle; + ACCESS_MASK DesiredAccess; + POBJECT_ATTRIBUTES ObjectAttributes; + } args; + + args.Handle = Handle; + args.DesiredAccess = DesiredAccess; + args.ObjectAttributes = ObjectAttributes; + + return KphpDeviceIoControl( + KphHandle, + KPH_OPENNAMEDOBJECT, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphOpenDirectoryObject( + __in HANDLE KphHandle, + __out PHANDLE DirectoryHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes + ) +{ + struct + { + PHANDLE DirectoryHandle; + ACCESS_MASK DesiredAccess; + POBJECT_ATTRIBUTES ObjectAttributes; + } args; + + args.DirectoryHandle = DirectoryHandle; + args.DesiredAccess = DesiredAccess; + args.ObjectAttributes = ObjectAttributes; + + return KphpDeviceIoControl( + KphHandle, + KPH_OPENDIRECTORYOBJECT, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphOpenDriver( + __in HANDLE KphHandle, + __out PHANDLE DriverHandle, + __in POBJECT_ATTRIBUTES ObjectAttributes + ) +{ + struct + { + PHANDLE DriverHandle; + POBJECT_ATTRIBUTES ObjectAttributes; + } args; + + args.DriverHandle = DriverHandle; + args.ObjectAttributes = ObjectAttributes; + + return KphpDeviceIoControl( + KphHandle, + KPH_OPENDRIVER, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphQueryInformationDriver( + __in HANDLE KphHandle, + __in HANDLE DriverHandle, + __in DRIVER_INFORMATION_CLASS DriverInformationClass, + __out_bcount_opt(DriverInformationLength) PVOID DriverInformation, + __in ULONG DriverInformationLength, + __out_opt PULONG ReturnLength + ) +{ + struct + { + HANDLE DriverHandle; + DRIVER_INFORMATION_CLASS DriverInformationClass; + PVOID DriverInformation; + ULONG DriverInformationLength; + PULONG ReturnLength; + } args; + + args.DriverHandle = DriverHandle; + args.DriverInformationClass = DriverInformationClass; + args.DriverInformation = DriverInformation; + args.DriverInformationLength = DriverInformationLength; + args.ReturnLength = ReturnLength; + + return KphpDeviceIoControl( + KphHandle, + KPH_QUERYINFORMATIONDRIVER, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +} + +NTSTATUS KphOpenType( + __in HANDLE KphHandle, + __out PHANDLE TypeHandle, + __in POBJECT_ATTRIBUTES ObjectAttributes + ) +{ + struct + { + PHANDLE TypeHandle; + POBJECT_ATTRIBUTES ObjectAttributes; + } args; + + args.TypeHandle = TypeHandle; + args.ObjectAttributes = ObjectAttributes; + + return KphpDeviceIoControl( + KphHandle, + KPH_OPENTYPE, + &args, + sizeof(args), + NULL, + 0, + NULL + ); +}