KphTerminateProcess now uses PsTerminateProcess where possible; if the wrong address is found it should not BSOD the system because the first 5 bytes are checked against the known standard function prologue.

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1099 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
wj32
2009-04-19 09:51:04 +00:00
parent fd240faf2a
commit 22bf8a798e
11 changed files with 189 additions and 45 deletions
+2
View File
@@ -2,6 +2,8 @@ Process Hacker
1.3.6.6
* NEW/IMPROVED:
* "Terminate process" now uses a special kernel-mode method to bypass
almost all anti-termination methods
* Basic support for Windows 7 in Process Hacker and KProcessHacker
* Proper symbol support with dbghelp.dll
* Private, Shared and Shareable Working Set columns
Binary file not shown.
+29 -9
View File
@@ -20,8 +20,8 @@
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _KPH_NT_H
#define _KPH_NT_H
#ifndef _KPH_H
#define _KPH_H
#include "kprocesshacker.h"
#include "debug.h"
@@ -31,10 +31,24 @@
#include "ps.h"
#include "zw.h"
extern _PsGetProcessJob PsGetProcessJob;
extern _PsSuspendProcess PsSuspendProcess;
extern _PsResumeProcess PsResumeProcess;
extern _MmCopyVirtualMemory MmCopyVirtualMemory;
#ifdef EXT
#undef EXT
#endif
#ifdef _KPH_PRIVATE
#define EXT
#define EQNULL = NULL
#else
#define EXT extern
#define EQNULL
#endif
EXT _MmCopyVirtualMemory MmCopyVirtualMemory EQNULL;
EXT _NtClose __NtClose EQNULL;
EXT _PsGetProcessJob PsGetProcessJob EQNULL;
EXT _PsResumeProcess PsResumeProcess EQNULL;
EXT _PsSuspendProcess PsSuspendProcess EQNULL;
EXT _PsTerminateProcess __PsTerminateProcess EQNULL;
typedef struct _KPH_ATTACH_STATE
{
@@ -191,7 +205,7 @@ NTSTATUS KphWriteVirtualMemory(
/* OB */
NTSTATUS KphObDuplicateObject(
NTSTATUS ObDuplicateObject(
PEPROCESS SourceProcess,
PEPROCESS TargetProcess,
HANDLE SourceHandle,
@@ -202,12 +216,18 @@ NTSTATUS KphObDuplicateObject(
KPROCESSOR_MODE AccessMode
);
PHANDLE_TABLE KphObReferenceProcessHandleTable(
PHANDLE_TABLE ObReferenceProcessHandleTable(
PEPROCESS Process
);
VOID KphObDereferenceProcessHandleTable(
VOID ObDereferenceProcessHandleTable(
PEPROCESS Process
);
/* PS */
NTSTATUS PsTerminateProcess(
PEPROCESS Process,
NTSTATUS ExitStatus
);
#endif
+5
View File
@@ -69,6 +69,11 @@ typedef NTSTATUS (NTAPI *_PsSuspendProcess)(
PEPROCESS Process
);
typedef NTSTATUS (__fastcall *_PsTerminateProcess)(
PEPROCESS Process,
NTSTATUS ExitStatus
);
/* STRUCTS */
typedef struct _KEXECUTE_OPTIONS
+15 -6
View File
@@ -25,16 +25,20 @@
#include "kprocesshacker.h"
#define WINDOWS_XP '0051'
#define WINDOWS_SERVER_2003 '0052'
#define WINDOWS_VISTA '0060'
#define WINDOWS_7 '0061'
#define WINDOWS_XP 51
#define WINDOWS_SERVER_2003 52
#define WINDOWS_VISTA 60
#define WINDOWS_7 61
#define KVOFF(object, offset) ((PCHAR)(object) + offset)
NTSTATUS KvInit();
#ifdef KPH_VERSION_PRIVATE
#ifdef EXT
#undef EXT
#endif
#ifdef _VERSION_PRIVATE
#define EXT
#else
#define EXT extern
@@ -46,7 +50,7 @@ EXT ACCESS_MASK ProcessAllAccess;
EXT ACCESS_MASK ThreadAllAccess;
/* Offsets */
/*
/* Structures
* Et: ETHREAD
* Ep: EPROCESS
* Ot: OBJECT_TYPE
@@ -62,4 +66,9 @@ EXT ULONG OffEpProtectedProcessBit;
EXT ULONG OffEpRundownProtect;
EXT ULONG OffOtiGenericMapping;
/* Functions
* These are all offsets from NtClose.
*/
EXT ULONG OffPsTerminateProcess;
#endif
+17
View File
@@ -54,6 +54,19 @@
#define JOB_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \
0x1F)
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
NTSTATUS NTAPI ZwOpenProcessToken(
HANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
@@ -67,4 +80,8 @@ NTSTATUS NTAPI ZwSetInformationProcess(
ULONG ProcessInformationLength
);
typedef NTSTATUS (NTAPI *_NtClose)(
HANDLE Handle
);
#endif
+21 -4
View File
@@ -20,12 +20,10 @@
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#define _KPH_PRIVATE
#include "include/kph.h"
_PsGetProcessJob PsGetProcessJob = NULL;
_PsSuspendProcess PsSuspendProcess = NULL;
_PsResumeProcess PsResumeProcess = NULL;
_MmCopyVirtualMemory MmCopyVirtualMemory = NULL;
static char StandardPrologue[] = { 0x8b, 0xff, 0x55, 0x8b, 0xec };
PVOID GetSystemRoutineAddress(WCHAR *Name)
{
@@ -50,11 +48,30 @@ NTSTATUS KphNtInit()
{
NTSTATUS status = STATUS_SUCCESS;
__NtClose = GetSystemRoutineAddress(L"NtClose");
/* NtClose is used as a reference point for any addresses
dependent on where the kernel is loaded. */
if (!__NtClose)
return STATUS_NOT_SUPPORTED;
MmCopyVirtualMemory = GetSystemRoutineAddress(L"MmCopyVirtualMemory");
PsGetProcessJob = GetSystemRoutineAddress(L"PsGetProcessJob");
PsResumeProcess = GetSystemRoutineAddress(L"PsResumeProcess");
PsSuspendProcess = GetSystemRoutineAddress(L"PsSuspendProcess");
/* Initialize function pointers */
if (OffPsTerminateProcess)
{
__PsTerminateProcess = (_PsTerminateProcess)((ULONG)__NtClose + OffPsTerminateProcess);
dprintf("PsTerminateProcess: 0x%08x\n", __PsTerminateProcess);
if (memcmp(__PsTerminateProcess, StandardPrologue, 5) != 0)
{
__PsTerminateProcess = NULL;
dprintf("PsTerminateProcess failed memory check\n");
}
}
return status;
}
+2 -2
View File
@@ -36,7 +36,7 @@ NTSTATUS KphReadVirtualMemory(
PEPROCESS processObject;
ULONG returnLength = 0;
if (MmCopyVirtualMemory == NULL)
if (!MmCopyVirtualMemory)
return STATUS_NOT_SUPPORTED;
if (AccessMode != KernelMode)
@@ -107,7 +107,7 @@ NTSTATUS KphWriteVirtualMemory(
PEPROCESS processObject;
ULONG returnLength = 0;
if (MmCopyVirtualMemory == NULL)
if (!MmCopyVirtualMemory)
return STATUS_NOT_SUPPORTED;
if (AccessMode != KernelMode)
+6 -6
View File
@@ -81,7 +81,7 @@ NTSTATUS KphDuplicateObject(
}
/* Call the internal function */
status = KphObDuplicateObject(
status = ObDuplicateObject(
sourceProcess,
targetProcess,
SourceHandle,
@@ -121,7 +121,7 @@ BOOLEAN KphEnumProcessHandleTable(
BOOLEAN result = FALSE;
PHANDLE_TABLE handleTable = NULL;
handleTable = KphObReferenceProcessHandleTable(Process);
handleTable = ObReferenceProcessHandleTable(Process);
if (!handleTable)
return FALSE;
@@ -131,18 +131,18 @@ BOOLEAN KphEnumProcessHandleTable(
EnumHandleProcedure,
Context,
Handle);
KphObDereferenceProcessHandleTable(Process);
ObDereferenceProcessHandleTable(Process);
return result;
}
VOID KphObDereferenceProcessHandleTable(
VOID ObDereferenceProcessHandleTable(
PEPROCESS Process
)
{
ExReleaseRundownProtection((PEX_RUNDOWN_REF)KVOFF(Process, OffEpRundownProtect));
}
NTSTATUS KphObDuplicateObject(
NTSTATUS ObDuplicateObject(
PEPROCESS SourceProcess,
PEPROCESS TargetProcess,
HANDLE SourceHandle,
@@ -257,7 +257,7 @@ OpenObjectEnd:
return status;
}
PHANDLE_TABLE KphObReferenceProcessHandleTable(
PHANDLE_TABLE ObReferenceProcessHandleTable(
PEPROCESS Process
)
{
+63 -12
View File
@@ -419,7 +419,7 @@ NTSTATUS KphResumeProcess(
NTSTATUS status = STATUS_SUCCESS;
PEPROCESS processObject;
if (PsResumeProcess == NULL)
if (!PsResumeProcess)
return STATUS_NOT_SUPPORTED;
status = ObReferenceObjectByHandle(
@@ -472,7 +472,7 @@ NTSTATUS KphSuspendProcess(
NTSTATUS status = STATUS_SUCCESS;
PEPROCESS processObject;
if (PsSuspendProcess == NULL)
if (!PsSuspendProcess)
return STATUS_NOT_SUPPORTED;
status = ObReferenceObjectByHandle(
@@ -515,22 +515,73 @@ NTSTATUS KphTerminateProcess(
return status;
/* Can't terminate ourself. Get user-mode to do it. */
if (PsGetProcessId(processObject) == PsGetCurrentProcessId())
if (processObject == PsGetCurrentProcess())
{
ObDereferenceObject(processObject);
return STATUS_DISK_FULL;
}
/* We have to open it again because ZwTerminateProcess only accepts kernel handles. */
clientId.UniqueThread = 0;
clientId.UniqueProcess = PsGetProcessId(processObject);
status = KphOpenProcess(&newProcessHandle, 0x1, &objectAttributes, &clientId, KernelMode);
ObDereferenceObject(processObject);
if (NT_SUCCESS(status))
if (__PsTerminateProcess)
{
status = ZwTerminateProcess(newProcessHandle, ExitStatus);
ZwClose(newProcessHandle);
status = PsTerminateProcess(processObject, ExitStatus);
}
else
{
/* We have to open it again because ZwTerminateProcess only accepts kernel handles. */
clientId.UniqueThread = 0;
clientId.UniqueProcess = PsGetProcessId(processObject);
status = KphOpenProcess(&newProcessHandle, 0x1, &objectAttributes, &clientId, KernelMode);
ObDereferenceObject(processObject);
if (NT_SUCCESS(status))
{
status = ZwTerminateProcess(newProcessHandle, ExitStatus);
ZwClose(newProcessHandle);
}
}
return status;
}
NTSTATUS PsTerminateProcess(
PEPROCESS Process,
NTSTATUS ExitStatus
)
{
PVOID psTerminateProcess = __PsTerminateProcess;
NTSTATUS status;
if (!psTerminateProcess)
return STATUS_NOT_SUPPORTED;
if (WindowsVersion == WINDOWS_XP)
{
/* PsTerminateProcess on XP is stdcall */
__asm
{
push [ExitStatus]
push [Process]
call [psTerminateProcess]
mov [status], eax
}
}
else if (
WindowsVersion == WINDOWS_VISTA ||
WindowsVersion == WINDOWS_7
)
{
/* PsTerminateProcess on Vista and above is thiscall */
__asm
{
push [ExitStatus]
mov ecx, [Process]
call [psTerminateProcess]
mov [status], eax
}
}
else
{
return STATUS_NOT_SUPPORTED;
}
return status;
+29 -6
View File
@@ -20,10 +20,15 @@
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#define KPH_VERSION_PRIVATE
#define _VERSION_PRIVATE
#include "include/version.h"
#include "include/debug.h"
/* The following offsets took me a long time to work out, so
please do not steal them. If you want to use them, please
license your project under the GNU GPL (although you are
not legally required to).
*/
NTSTATUS KvInit()
{
NTSTATUS status = STATUS_SUCCESS;
@@ -58,15 +63,26 @@ NTSTATUS KvInit()
/* Windows XP SP0 and 1 are not supported */
if (servicePack == 0)
{
return STATUS_NOT_SUPPORTED;
}
else if (servicePack == 1)
{
return STATUS_NOT_SUPPORTED;
}
else if (servicePack == 2)
;
{
/* Seems to be OK for both ntkrnlpa and ntkrpamp */
OffPsTerminateProcess = 0x16576;
}
else if (servicePack == 3)
;
{
OffPsTerminateProcess = 0x1676c;
}
else
{
return STATUS_NOT_SUPPORTED;
}
dprintf("Initialized version-specific data for Windows XP SP%d\n", servicePack);
}
@@ -97,12 +113,13 @@ NTSTATUS KvInit()
if (servicePack == 0)
{
OffOtiGenericMapping = 0x60 + 0xc;
OffPsTerminateProcess = 0x29b83;
}
/* SP1 */
else if (servicePack == 1)
{
/* They got rid of the Mutex (an ERESOURCE) */
OffOtiGenericMapping = 0x28 + 0xc;
OffOtiGenericMapping = 0x28 + 0xc; /* They got rid of the Mutex (an ERESOURCE) */
OffPsTerminateProcess = 0x7768a;
}
else
{
@@ -129,9 +146,15 @@ NTSTATUS KvInit()
/* SP0 */
if (servicePack == 0)
;
{
/* In Windows 7 PsTerminateProcess is before
NtClose, so we have a negative number here. */
OffPsTerminateProcess = 0xfff80dc2;
}
else
{
return STATUS_NOT_SUPPORTED;
}
dprintf("Initialized version-specific data for Windows 7 SP%d\n", servicePack);
}