From d02af780650263eb012012d8aee59dc815c99d7e Mon Sep 17 00:00:00 2001 From: wj32 Date: Wed, 9 Mar 2011 07:15:21 +0000 Subject: [PATCH] reverted to buildable state git-svn-id: svn://svn.code.sf.net/p/processhacker/code@4132 21ef857c-d57f-4fe0-8362-d861dc6d29cd --- .../ProcessHacker.Native/KProcessHacker.cs | 1187 +++++++++++++---- .../Objects/ProcessHandle.cs | 6 +- .../ProcessHacker.Native.csproj | 2 +- 3 files changed, 949 insertions(+), 246 deletions(-) diff --git a/1.x/trunk/ProcessHacker.Native/KProcessHacker.cs b/1.x/trunk/ProcessHacker.Native/KProcessHacker.cs index 79650b406..2d3d6b06c 100644 --- a/1.x/trunk/ProcessHacker.Native/KProcessHacker.cs +++ b/1.x/trunk/ProcessHacker.Native/KProcessHacker.cs @@ -2,7 +2,7 @@ * Process Hacker - * KProcessHacker interfacing code * - * Copyright (C) 2009-2011 wj32 + * Copyright (C) 2009 wj32 * * This file is part of Process Hacker. * @@ -48,55 +48,87 @@ namespace ProcessHacker.Native set { _instance = value; } } - public static int KphCtlCode(int x) + /// + /// A control code used by KProcessHacker to represent a specific function. + /// + private enum Control : uint { - return Win32.CtlCode(KphDeviceType, 0x800 + x, DeviceControlMethod.Neither, DeviceControlAccess.Any); + ClientCloseHandle = 0, + SsQueryClientEntry, + Reserved1, + KphOpenProcess, + KphOpenThread, + KphOpenProcessToken, + GetProcessProtected, + SetProcessProtected, + KphTerminateProcess, + KphSuspendProcess, + KphResumeProcess, + KphReadVirtualMemory, + KphWriteVirtualMemory, + SetProcessToken, + GetThreadStartAddress, + SetHandleAttributes, + GetHandleObjectName, + KphOpenProcessJob, + KphGetContextThread, + KphSetContextThread, + KphGetThreadWin32Thread, + KphDuplicateObject, + ZwQueryObject, + KphGetProcessId, + KphGetThreadId, + KphTerminateThread, + GetFeatures, + KphSetHandleGrantedAccess, + KphAssignImpersonationToken, + ProtectAdd, + ProtectRemove, + ProtectQuery, + KphUnsafeReadVirtualMemory, + SetExecuteOptions, + KphQueryProcessHandles, + KphOpenThreadProcess, + KphCaptureStackBackTraceThread, + KphDangerousTerminateThread, + KphOpenType, + KphOpenDriver, + KphQueryInformationDriver, + KphOpenDirectoryObject, + SsRef, + SsUnref, + SsCreateClientEntry, + SsCreateRuleSetEntry, + SsRemoveRule, + SsAddProcessIdRule, + SsAddThreadIdRule, + SsAddPreviousModeRule, + SsAddNumberRule, + SsEnableClientEntry, + KphOpenNamedObject, + KphQueryInformationProcess, + KphQueryInformationThread, + KphSetInformationProcess, + KphSetInformationThread, } - public const int KphDeviceType = 0x9999; - public static readonly int IoCtlGetFeatures = KphCtlCode(0); - public static readonly int IoCtlOpenProcess = KphCtlCode(50); - public static readonly int IoCtlOpenProcessToken = KphCtlCode(51); - public static readonly int IoCtlOpenProcessJob = KphCtlCode(52); - public static readonly int IoCtlSuspendProcess = KphCtlCode(53); - public static readonly int IoCtlResumeProcess = KphCtlCode(54); - public static readonly int IoCtlTerminateProcess = KphCtlCode(55); - public static readonly int IoCtlReadVirtualMemory = KphCtlCode(56); - public static readonly int IoCtlWriteVirtualMemory = KphCtlCode(57); - public static readonly int IoCtlReadVirtualMemoryUnsafe = KphCtlCode(58); - public static readonly int IoCtlQueryInformationProcess = KphCtlCode(59); - public static readonly int IoCtlSetInformationProcess = KphCtlCode(60); - public static readonly int IoCtlOpenThread = KphCtlCode(100); - public static readonly int IoCtlOpenThreadProcess = KphCtlCode(101); - public static readonly int IoCtlTerminateThread = KphCtlCode(102); - public static readonly int IoCtlTerminateThreadUnsafe = KphCtlCode(103); - public static readonly int IoCtlGetContextThread = KphCtlCode(104); - public static readonly int IoCtlSetContextThread = KphCtlCode(105); - public static readonly int IoCtlCaptureStackBackTraceThread = KphCtlCode(106); - public static readonly int IoCtlQueryInformationThread = KphCtlCode(107); - public static readonly int IoCtlSetInformationThread = KphCtlCode(108); - public static readonly int IoCtlEnumerateProcessHandles = KphCtlCode(150); - public static readonly int IoCtlQueryInformationObject = KphCtlCode(151); - public static readonly int IoCtlSetInformationObject = KphCtlCode(152); - public static readonly int IoCtlDuplicateObject = KphCtlCode(153); - public static readonly int IoCtlOpenDriver = KphCtlCode(200); - public static readonly int IoCtlQueryInformationDriver = KphCtlCode(201); - [Flags] public enum KphFeatures : int { - None = 0 // none so far + PsTerminateProcess = 0x1, + PspTerminateThreadByPointer = 0x2 } private string _deviceName; private FileHandle _fileHandle; + private uint _baseControlNumber; private KphFeatures _features; /// /// Creates a connection to KProcessHacker. /// public KProcessHacker() - : this("KProcessHacker2") + : this("KProcessHacker") { } /// @@ -116,6 +148,9 @@ namespace ProcessHacker.Native { _deviceName = deviceName; + if (OSVersion.Architecture != OSArch.I386) + throw new NotSupportedException("KProcessHacker does not support 64-bit Windows."); + try { _fileHandle = new FileHandle( @@ -138,7 +173,7 @@ namespace ProcessHacker.Native try { - using (shandle = new ServiceHandle(deviceName, ServiceAccess.Start)) + using (shandle = new ServiceHandle("KProcessHacker", ServiceAccess.Start)) { shandle.Start(); } @@ -187,7 +222,18 @@ namespace ProcessHacker.Native } _fileHandle.SetHandleFlags(Win32HandleFlags.ProtectFromClose, Win32HandleFlags.ProtectFromClose); - _features = this.KphGetFeatures(); + + byte[] bytes = _fileHandle.Read(4); + + fixed (byte* bytesPtr = bytes) + _baseControlNumber = *(uint*)bytesPtr; + + try + { + _features = this.GetFeatures(); + } + catch + { } } public string DeviceName @@ -200,6 +246,11 @@ namespace ProcessHacker.Native get { return _features; } } + private int CtlCode(Control ctl) + { + return (int)(_baseControlNumber + ((uint)ctl * 4)); + } + /// /// Closes the connection to KProcessHacker. /// @@ -209,292 +260,946 @@ namespace ProcessHacker.Native _fileHandle.Dispose(); } - [StructLayout(LayoutKind.Sequential)] - private struct KphGetFeaturesInput + public void ClientCloseHandle(IntPtr handle) { - public int* Features; + byte* inData = stackalloc byte[4]; + + *(int*)inData = handle.ToInt32(); + + _fileHandle.IoControl(CtlCode(Control.ClientCloseHandle), inData, 4, null, 0); } - public KphFeatures KphGetFeatures() + public KphFeatures GetFeatures() { - KphGetFeaturesInput input; - int features; + byte* outData = stackalloc byte[4]; - input.Features = &features; - _fileHandle.IoControl(IoCtlGetFeatures, &input, sizeof(KphGetFeaturesInput), null, 0); + _fileHandle.IoControl(CtlCode(Control.GetFeatures), null, 0, outData, 4); - return (KphFeatures)features; + return (KphFeatures)(*(int*)outData); } - [StructLayout(LayoutKind.Sequential)] - private struct KphOpenProcessInput + public string GetHandleObjectName(ProcessHandle processHandle, IntPtr handle) { - public IntPtr* ProcessHandle; - public int DesiredAccess; - public ClientId* ClientId; + byte* inData = stackalloc byte[8]; + byte[] outData = new byte[2048]; + + *(int*)inData = processHandle; + *(int*)(inData + 4) = handle.ToInt32(); + + try + { + int len = _fileHandle.IoControl(CtlCode(Control.GetHandleObjectName), + inData, 8, outData); + + return Encoding.Unicode.GetString(outData, 8, len - 8).TrimEnd('\0'); + } + catch + { } + + return null; } - public IntPtr KphOpenProcess(int pid, ProcessAccess desiredAccess) + public bool GetProcessProtected(int pid) { - KphOpenProcessInput input; - IntPtr processHandle; - ClientId clientId; + byte[] result = new byte[1]; - clientId.ProcessId = pid; - clientId.ThreadId = 0; + _fileHandle.IoControl(CtlCode(Control.GetProcessProtected), + (byte*)&pid, 4, result); - input.ProcessHandle = &processHandle; - input.DesiredAccess = (int)desiredAccess; - input.ClientId = &clientId; - _fileHandle.IoControl(IoCtlOpenProcess, &input, sizeof(KphOpenProcessInput), null, 0); - - return processHandle; + return result[0] != 0; } - [StructLayout(LayoutKind.Sequential)] - private struct KphOpenProcessTokenInput + public uint GetThreadStartAddress(ThreadHandle threadHandle) { - public IntPtr ProcessHandle; - public int DesiredAccess; - public IntPtr* TokenHandle; + byte* outData = stackalloc byte[4]; + int threadHandleInt = threadHandle; + + _fileHandle.IoControl(CtlCode(Control.GetThreadStartAddress), + (byte*)&threadHandleInt, 4, outData, 4); + + return *(uint*)outData; } - public IntPtr KphOpenProcessToken(ProcessHandle processHandle, TokenAccess desiredAccess) + public void KphAssignImpersonationToken(ThreadHandle threadHandle, TokenHandle tokenHandle) { - KphOpenProcessTokenInput input; - IntPtr tokenHandle; + byte* inData = stackalloc byte[8]; - input.ProcessHandle = processHandle; - input.DesiredAccess = (int)desiredAccess; - input.TokenHandle = &tokenHandle; - _fileHandle.IoControl(IoCtlOpenProcessToken, &input, sizeof(KphOpenProcessTokenInput), null, 0); + *(int*)inData = threadHandle; + *(int*)(inData + 4) = tokenHandle; - return tokenHandle; + _fileHandle.IoControl(CtlCode(Control.KphAssignImpersonationToken), inData, 8, null, 0); } - [StructLayout(LayoutKind.Sequential)] - private struct KphOpenProcessJobInput + public unsafe int KphCaptureStackBackTraceThread( + ThreadHandle threadHandle, + int framesToSkip, + int framesToCapture, + IntPtr[] backTrace, + out int backTraceHash + ) { - public IntPtr ProcessHandle; - public int DesiredAccess; - public IntPtr* JobHandle; + byte* inData = stackalloc byte[6 * sizeof(int)]; + int capturedFramesLocal; + int backTraceHashLocal; + + if (framesToCapture > backTrace.Length) + throw new ArgumentOutOfRangeException("Back trace buffer is too small."); + + fixed (IntPtr* backTracePtr = backTrace) + { + *(int*)inData = threadHandle; + *(int*)(inData + 0x4) = framesToSkip; + *(int*)(inData + 0x8) = framesToCapture; + *(int*)(inData + 0xc) = (int)backTracePtr; + *(int*)(inData + 0x10) = (int)&capturedFramesLocal; + *(int*)(inData + 0x14) = (int)&backTraceHashLocal; + + _fileHandle.IoControl(CtlCode(Control.KphCaptureStackBackTraceThread), inData, 6 * sizeof(int), null, 0); + backTraceHash = backTraceHashLocal; + + return capturedFramesLocal; + } } - public IntPtr KphOpenProcessJob(ProcessHandle processHandle, TokenAccess desiredAccess) + public void KphDangerousTerminateThread(ThreadHandle threadHandle, NtStatus exitStatus) { - KphOpenProcessJobInput input; - IntPtr jobHandle; + byte* inData = stackalloc byte[8]; - input.ProcessHandle = processHandle; - input.DesiredAccess = (int)desiredAccess; - input.JobHandle = &jobHandle; - _fileHandle.IoControl(IoCtlOpenProcessJob, &input, sizeof(KphOpenProcessJobInput), null, 0); + *(int*)inData = threadHandle; + *(int*)(inData + 4) = (int)exitStatus; - return jobHandle; + _fileHandle.IoControl(CtlCode(Control.KphDangerousTerminateThread), inData, 8, null, 0); } - [StructLayout(LayoutKind.Sequential)] - private struct KphSuspendProcessInput + public void KphDuplicateObject( + int sourceProcessHandle, + int sourceHandle, + int targetProcessHandle, + out int targetHandle, + int desiredAccess, + HandleFlags handleAttributes, + DuplicateOptions options + ) { - public IntPtr ProcessHandle; + int handle; + + KphDuplicateObject( + sourceProcessHandle, + sourceHandle, + targetProcessHandle, + (int)&handle, + desiredAccess, + handleAttributes, + options + ); + + targetHandle = handle; } - public void KphSuspendProcess(ProcessHandle processHandle) + public void KphDuplicateObject( + int sourceProcessHandle, + int sourceHandle, + int targetProcessHandle, + int targetHandle, + int desiredAccess, + HandleFlags handleAttributes, + DuplicateOptions options + ) { - KphSuspendProcessInput input; + byte[] data = new byte[7 * sizeof(int)]; - input.ProcessHandle = processHandle; - _fileHandle.IoControl(IoCtlSuspendProcess, &input, sizeof(KphSuspendProcessInput), null, 0); + fixed (byte* dataPtr = data) + { + *(int*)(dataPtr + 0x0) = sourceProcessHandle; + *(int*)(dataPtr + 0x4) = sourceHandle; + *(int*)(dataPtr + 0x8) = targetProcessHandle; + *(int*)(dataPtr + 0xc) = targetHandle; + *(int*)(dataPtr + 0x10) = desiredAccess; + *(int*)(dataPtr + 0x14) = (int)handleAttributes; + *(int*)(dataPtr + 0x18) = (int)options; + + _fileHandle.IoControl(CtlCode(Control.KphDuplicateObject), data, null); + } } - [StructLayout(LayoutKind.Sequential)] - private struct KphResumeProcessInput + public void KphGetContextThread(ThreadHandle threadHandle, Context* context) { - public IntPtr ProcessHandle; + byte* inData = stackalloc byte[8]; + + *(int*)inData = threadHandle; + *(int*)(inData + 4) = (int)context; + + _fileHandle.IoControl(CtlCode(Control.KphGetContextThread), inData, 8, null, 0); + } + + public int KphGetProcessId(ProcessHandle processHandle, IntPtr handle) + { + byte* inData = stackalloc byte[8]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = processHandle; + *(int*)(inData + 4) = handle.ToInt32(); + + _fileHandle.IoControl(CtlCode(Control.KphGetProcessId), inData, 8, outData, 4); + + return *(int*)outData; + } + + public int KphGetThreadId(ProcessHandle processHandle, IntPtr handle, out int processId) + { + byte* inData = stackalloc byte[8]; + byte* outData = stackalloc byte[8]; + + *(int*)inData = processHandle; + *(int*)(inData + 4) = handle.ToInt32(); + + _fileHandle.IoControl(CtlCode(Control.KphGetThreadId), inData, 8, outData, 8); + processId = *(int*)(outData + 4); + + return *(int*)outData; + } + + public int KphGetThreadWin32Thread(ThreadHandle threadHandle) + { + int threadHandleInt = threadHandle; + byte* outData = stackalloc byte[4]; + + _fileHandle.IoControl(CtlCode(Control.KphGetThreadWin32Thread), (byte*)&threadHandleInt, 4, outData, 4); + + return *(int*)outData; + } + + public int KphOpenDirectoryObject(DirectoryAccess access, ObjectAttributes objectAttributes) + { + byte* inData = stackalloc byte[0xc]; + int directoryObjectHandle; + + *(int*)inData = (int)&directoryObjectHandle; + *(int*)(inData + 0x4) = (int)access; + *(int*)(inData + 0x8) = (int)&objectAttributes; + + _fileHandle.IoControl(CtlCode(Control.KphOpenDirectoryObject), inData, 0xc, null, 0); + + return directoryObjectHandle; + } + + public int KphOpenDriver(ObjectAttributes objectAttributes) + { + byte* inData = stackalloc byte[8]; + int driverHandle; + + *(int*)inData = (int)&driverHandle; + *(int*)(inData + 4) = (int)&objectAttributes; + + _fileHandle.IoControl(CtlCode(Control.KphOpenDriver), inData, 8, null, 0); + + return driverHandle; + } + + public int KphOpenNamedObject(int access, ObjectAttributes objectAttributes) + { + byte* inData = stackalloc byte[0xc]; + int handle; + + *(int*)inData = (int)&handle; + *(int*)(inData + 4) = access; + *(int*)(inData + 8) = (int)&objectAttributes; + + _fileHandle.IoControl(CtlCode(Control.KphOpenNamedObject), inData, 0xc, null, 0); + + return handle; + } + + public int KphOpenProcess(int pid, ProcessAccess desiredAccess) + { + byte* inData = stackalloc byte[8]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = pid; + *(uint*)(inData + 4) = (uint)desiredAccess; + + _fileHandle.IoControl(CtlCode(Control.KphOpenProcess), inData, 8, outData, 4); + + return *(int*)outData; + } + + public int KphOpenProcessJob(ProcessHandle processHandle, JobObjectAccess desiredAccess) + { + byte* inData = stackalloc byte[8]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = processHandle; + *(uint*)(inData + 4) = (uint)desiredAccess; + + _fileHandle.IoControl(CtlCode(Control.KphOpenProcessJob), inData, 8, outData, 4); + + return *(int*)outData; + } + + public int KphOpenProcessToken(ProcessHandle processHandle, TokenAccess desiredAccess) + { + byte* inData = stackalloc byte[8]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = processHandle; + *(uint*)(inData + 4) = (uint)desiredAccess; + + _fileHandle.IoControl(CtlCode(Control.KphOpenProcessToken), inData, 8, outData, 4); + + return *(int*)outData; + } + + public int KphOpenThread(int tid, ThreadAccess desiredAccess) + { + byte* inData = stackalloc byte[8]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = tid; + *(uint*)(inData + 4) = (uint)desiredAccess; + + _fileHandle.IoControl(CtlCode(Control.KphOpenThread), inData, 8, outData, 4); + + return *(int*)outData; + } + + public int KphOpenThreadProcess(ThreadHandle threadHandle, ProcessAccess desiredAccess) + { + byte* inData = stackalloc byte[8]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = threadHandle; + *(uint*)(inData + 4) = (uint)desiredAccess; + + _fileHandle.IoControl(CtlCode(Control.KphOpenThreadProcess), inData, 8, outData, 4); + + return *(int*)outData; + } + + public int KphOpenType(ObjectAttributes objectAttributes) + { + byte* inData = stackalloc byte[8]; + int typeHandle; + + *(int*)inData = (int)&typeHandle; + *(int*)(inData + 4) = (int)&objectAttributes; + + _fileHandle.IoControl(CtlCode(Control.KphOpenType), inData, 8, null, 0); + + return typeHandle; + } + + public void KphQueryInformationDriver( + DriverHandle driverHandle, + DriverInformationClass driverInformationClass, + IntPtr driverInformation, + int driverInformationLength, + out int returnLength + ) + { + byte* inData = stackalloc byte[0x14]; + int returnLengthLocal; + + *(int*)inData = driverHandle; + *(int*)(inData + 0x4) = (int)driverInformationClass; + *(int*)(inData + 0x8) = driverInformation.ToInt32(); + *(int*)(inData + 0xc) = driverInformationLength; + *(int*)(inData + 0x10) = (int)&returnLengthLocal; + + try + { + _fileHandle.IoControl(CtlCode(Control.KphQueryInformationDriver), inData, 0x14, null, 0); + } + finally + { + returnLength = returnLengthLocal; + } + } + + public void KphQueryInformationProcess( + ProcessHandle processHandle, + ProcessInformationClass processInformationClass, + IntPtr processInformation, + int processInformationLength, + out int returnLength + ) + { + byte* inData = stackalloc byte[0x14]; + int returnLengthLocal; + + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = (int)processInformationClass; + *(int*)(inData + 0x8) = processInformation.ToInt32(); + *(int*)(inData + 0xc) = processInformationLength; + *(int*)(inData + 0x10) = (int)&returnLengthLocal; + + try + { + _fileHandle.IoControl(CtlCode(Control.KphQueryInformationProcess), inData, 0x14, null, 0); + } + finally + { + returnLength = returnLengthLocal; + } + } + + public void KphQueryInformationThread( + ThreadHandle threadHandle, + ThreadInformationClass threadInformationClass, + IntPtr threadInformation, + int threadInformationLength, + out int returnLength + ) + { + byte* inData = stackalloc byte[0x14]; + int returnLengthLocal; + + *(int*)inData = threadHandle; + *(int*)(inData + 0x4) = (int)threadInformationClass; + *(int*)(inData + 0x8) = threadInformation.ToInt32(); + *(int*)(inData + 0xc) = threadInformationLength; + *(int*)(inData + 0x10) = (int)&returnLengthLocal; + + try + { + _fileHandle.IoControl(CtlCode(Control.KphQueryInformationThread), inData, 0x14, null, 0); + } + finally + { + returnLength = returnLengthLocal; + } + } + + public void KphQueryProcessHandles(ProcessHandle processHandle, IntPtr buffer, int bufferLength, out int returnLength) + { + byte* inData = stackalloc byte[0x10]; + int returnLengthLocal; + + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = buffer.ToInt32(); + *(int*)(inData + 0x8) = bufferLength; + *(int*)(inData + 0xc) = (int)&returnLengthLocal; + + try + { + _fileHandle.IoControl(CtlCode(Control.KphQueryProcessHandles), inData, 0x10, null, 0); + } + finally + { + returnLength = returnLengthLocal; + } + } + + public void KphReadVirtualMemory(ProcessHandle processHandle, int baseAddress, byte[] buffer, int length, out int bytesRead) + { + fixed (byte* bufferPtr = buffer) + { + this.KphReadVirtualMemory(processHandle, baseAddress, new IntPtr(bufferPtr), length, out bytesRead); + } + } + + public void KphReadVirtualMemory(ProcessHandle processHandle, int baseAddress, IntPtr buffer, int length, out int bytesRead) + { + NtStatus status; + + status = KphReadVirtualMemorySafe(processHandle, baseAddress, buffer, length, out bytesRead); + + if (status >= NtStatus.Error) + Win32.Throw(status); + } + + public NtStatus KphReadVirtualMemorySafe(ProcessHandle processHandle, int baseAddress, IntPtr buffer, int length, out int bytesRead) + { + NtStatus status; + byte* inData = stackalloc byte[0x14]; + int returnLength; + int br; + + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = baseAddress; + *(int*)(inData + 0x8) = (int)buffer; + *(int*)(inData + 0xc) = length; + *(int*)(inData + 0x10) = (int)&br; + + status = _fileHandle.IoControl(CtlCode(Control.KphReadVirtualMemory), (IntPtr)inData, 0x14, IntPtr.Zero, 0, out returnLength); + + bytesRead = br; + + return status; + } + + public NtStatus KphReadVirtualMemoryUnsafe(ProcessHandle processHandle, int baseAddress, void* buffer, int length, out int bytesRead) + { + return KphReadVirtualMemoryUnsafe(processHandle, baseAddress, new IntPtr(buffer), length, out bytesRead); + } + + public NtStatus KphReadVirtualMemoryUnsafe(ProcessHandle processHandle, int baseAddress, IntPtr buffer, int length, out int bytesRead) + { + NtStatus status; + byte* inData = stackalloc byte[0x14]; + int returnLength; + int br; + + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = baseAddress; + *(int*)(inData + 0x8) = (int)buffer; + *(int*)(inData + 0xc) = length; + *(int*)(inData + 0x10) = (int)&br; + + status = _fileHandle.IoControl(CtlCode(Control.KphUnsafeReadVirtualMemory), (IntPtr)inData, 0x14, IntPtr.Zero, 0, out returnLength); + + bytesRead = br; + + return status; } public void KphResumeProcess(ProcessHandle processHandle) { - KphResumeProcessInput input; + int processHandleInt = processHandle; - input.ProcessHandle = processHandle; - _fileHandle.IoControl(IoCtlResumeProcess, &input, sizeof(KphResumeProcessInput), null, 0); + _fileHandle.IoControl(CtlCode(Control.KphResumeProcess), + (byte*)&processHandleInt, 4, null, 0); } - [StructLayout(LayoutKind.Sequential)] - private struct KphTerminateProcessInput + public void KphSetContextThread(ThreadHandle threadHandle, Context* context) { - public IntPtr ProcessHandle; - public NtStatus ExitStatus; + byte* inData = stackalloc byte[8]; + + *(int*)inData = threadHandle; + *(int*)(inData + 4) = (int)context; + + _fileHandle.IoControl(CtlCode(Control.KphSetContextThread), inData, 8, null, 0); + } + + public void KphSetHandleGrantedAccess(IntPtr handle, int grantedAccess) + { + byte* inData = stackalloc byte[8]; + + *(int*)inData = handle.ToInt32(); + *(int*)(inData + 4) = grantedAccess; + + _fileHandle.IoControl(CtlCode(Control.KphSetHandleGrantedAccess), inData, 8, null, 0); + } + + public void KphSetInformationProcess( + ProcessHandle processHandle, + ProcessInformationClass processInformationClass, + IntPtr processInformation, + int processInformationLength + ) + { + byte* inData = stackalloc byte[0x10]; + + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = (int)processInformationClass; + *(int*)(inData + 0x8) = processInformation.ToInt32(); + *(int*)(inData + 0xc) = processInformationLength; + + _fileHandle.IoControl(CtlCode(Control.KphSetInformationProcess), inData, 0x10, null, 0); + } + + public void KphSetInformationThread( + ThreadHandle threadHandle, + ThreadInformationClass threadInformationClass, + IntPtr threadInformation, + int threadInformationLength + ) + { + byte* inData = stackalloc byte[0x10]; + + *(int*)inData = threadHandle; + *(int*)(inData + 0x4) = (int)threadInformationClass; + *(int*)(inData + 0x8) = threadInformation.ToInt32(); + *(int*)(inData + 0xc) = threadInformationLength; + + _fileHandle.IoControl(CtlCode(Control.KphSetInformationThread), inData, 0x10, null, 0); + } + + public void KphSuspendProcess(ProcessHandle processHandle) + { + int processHandleInt = processHandle; + + _fileHandle.IoControl(CtlCode(Control.KphSuspendProcess), + (byte*)&processHandleInt, 4, null, 0); } public void KphTerminateProcess(ProcessHandle processHandle, NtStatus exitStatus) { - KphTerminateProcessInput input; + byte* inData = stackalloc byte[8]; - input.ProcessHandle = processHandle; - input.ExitStatus = exitStatus; - _fileHandle.IoControl(IoCtlTerminateProcess, &input, sizeof(KphTerminateProcessInput), null, 0); + *(int*)inData = processHandle; + *(int*)(inData + 4) = (int)exitStatus; + + try + { + _fileHandle.IoControl(CtlCode(Control.KphTerminateProcess), inData, 8, null, 0); + } + catch (WindowsException ex) + { + // STATUS_CANT_TERMINATE_SELF means we tried to terminate ourself. Kernel-mode can't do it, + // so we do it now. + if (ex.Status == NtStatus.CantTerminateSelf) + Win32.TerminateProcess(new IntPtr(-1), (int)exitStatus); + else + throw ex; + } } - [StructLayout(LayoutKind.Sequential)] - private struct KphReadVirtualMemoryInput + public void KphTerminateThread(ThreadHandle threadHandle, NtStatus exitStatus) { - public IntPtr ProcessHandle; - public IntPtr BaseAddress; - public IntPtr Buffer; - public IntPtr BufferSize; - public IntPtr* NumberOfBytesRead; + byte* inData = stackalloc byte[8]; + + *(int*)inData = threadHandle; + *(int*)(inData + 4) = (int)exitStatus; + + try + { + _fileHandle.IoControl(CtlCode(Control.KphTerminateThread), inData, 8, null, 0); + } + catch (WindowsException ex) + { + if (ex.Status == NtStatus.CantTerminateSelf) + Win32.TerminateThread(new IntPtr(-2), (int)exitStatus); + else + throw ex; + } } - public void KphReadVirtualMemory(ProcessHandle processHandle, IntPtr baseAddress, IntPtr buffer, IntPtr bufferSize, out IntPtr numberOfBytesRead) + public void KphWriteVirtualMemory(ProcessHandle processHandle, int baseAddress, byte[] buffer, int length, out int bytesWritten) { - KphReadVirtualMemoryInput input; - - input.ProcessHandle = processHandle; - input.BaseAddress = baseAddress; - input.Buffer = buffer; - input.BufferSize = bufferSize; - input.NumberOfBytesRead = &numberOfBytesRead; - _fileHandle.IoControl(IoCtlReadVirtualMemory, &input, sizeof(KphReadVirtualMemoryInput), null, 0); + fixed (byte* bufferPtr = buffer) + this.KphWriteVirtualMemory(processHandle, baseAddress, new IntPtr(bufferPtr), length, out bytesWritten); } - [StructLayout(LayoutKind.Sequential)] - private struct KphWriteVirtualMemoryInput + public void KphWriteVirtualMemory(ProcessHandle processHandle, int baseAddress, IntPtr buffer, int length, out int bytesWritten) { - public IntPtr ProcessHandle; - public IntPtr BaseAddress; - public IntPtr Buffer; - public IntPtr BufferSize; - public IntPtr* NumberOfBytesWritten; + byte* inData = stackalloc byte[0x14]; + int returnLength; + + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = baseAddress; + *(int*)(inData + 0x8) = (int)buffer; + *(int*)(inData + 0xc) = length; + *(int*)(inData + 0x10) = (int)&returnLength; + + try + { + _fileHandle.IoControl(CtlCode(Control.KphWriteVirtualMemory), inData, 0x14, null, 0); + } + finally + { + bytesWritten = returnLength; + } } - public void KphWriteVirtualMemory(ProcessHandle processHandle, IntPtr baseAddress, IntPtr buffer, IntPtr bufferSize, out IntPtr numberOfBytesWritten) + public void ProtectAdd(ProcessHandle processHandle, bool allowKernelMode, ProcessAccess ProcessAllowMask, ThreadAccess ThreadAllowMask) { - KphWriteVirtualMemoryInput input; + byte* inData = stackalloc byte[16]; - input.ProcessHandle = processHandle; - input.BaseAddress = baseAddress; - input.Buffer = buffer; - input.BufferSize = bufferSize; - input.NumberOfBytesWritten = &numberOfBytesWritten; - _fileHandle.IoControl(IoCtlWriteVirtualMemory, &input, sizeof(KphWriteVirtualMemoryInput), null, 0); + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = allowKernelMode ? 1 : 0; + *(int*)(inData + 0x8) = (int)ProcessAllowMask; + *(int*)(inData + 0xc) = (int)ThreadAllowMask; + + _fileHandle.IoControl(CtlCode(Control.ProtectAdd), inData, 16, null, 0); } - [StructLayout(LayoutKind.Sequential)] - private struct KphReadVirtualMemoryUnsafeInput + public void ProtectQuery(ProcessHandle processHandle, out bool AllowKernelMode, out ProcessAccess ProcessAllowMask, out ThreadAccess ThreadAllowMask) { - public IntPtr ProcessHandle; - public IntPtr BaseAddress; - public IntPtr Buffer; - public IntPtr BufferSize; - public IntPtr* NumberOfBytesRead; + byte* inData = stackalloc byte[16]; + int allowKernelMode; + ProcessAccess processAllowMask; + ThreadAccess threadAllowMask; + + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = (int)&allowKernelMode; + *(int*)(inData + 0x8) = (int)&processAllowMask; + *(int*)(inData + 0xc) = (int)&threadAllowMask; + + _fileHandle.IoControl(CtlCode(Control.ProtectQuery), inData, 16, null, 0); + + AllowKernelMode = allowKernelMode != 0; + ProcessAllowMask = processAllowMask; + ThreadAllowMask = threadAllowMask; } - public void KphReadVirtualMemoryUnsafe(ProcessHandle processHandle, IntPtr baseAddress, IntPtr buffer, IntPtr bufferSize, out IntPtr numberOfBytesRead) + public void ProtectRemove(ProcessHandle processHandle) { - KphReadVirtualMemoryUnsafeInput input; + int processHandleInt = processHandle; - input.ProcessHandle = processHandle; - input.BaseAddress = baseAddress; - input.Buffer = buffer; - input.BufferSize = bufferSize; - input.NumberOfBytesRead = &numberOfBytesRead; - _fileHandle.IoControl(IoCtlReadVirtualMemoryUnsafe, &input, sizeof(KphReadVirtualMemoryUnsafeInput), null, 0); + _fileHandle.IoControl(CtlCode(Control.ProtectRemove), + (byte*)&processHandleInt, 4, null, 0); } - [StructLayout(LayoutKind.Sequential)] - private struct KphQueryInformationProcessInput + public void SetExecuteOptions(ProcessHandle processHandle, MemExecuteOptions executeOptions) { - public IntPtr ProcessHandle; - public KphProcessInformationClass ProcessInformationClass; - public IntPtr ProcessInformation; - public int ProcessInformationLength; - public int* ReturnLength; + byte* inData = stackalloc byte[8]; + + *(int*)inData = processHandle; + *(int*)(inData + 4) = (int)executeOptions; + + _fileHandle.IoControl(CtlCode(Control.SetExecuteOptions), inData, 8, null, 0); } - public void KphQueryInformationProcess(ProcessHandle processHandle, KphProcessInformationClass processInformationClass, IntPtr processInformation, int processInformationLength, out int returnLength) + public void SetHandleAttributes(ProcessHandle processHandle, IntPtr handle, HandleFlags flags) { - KphQueryInformationProcessInput input; + byte* inData = stackalloc byte[12]; - input.ProcessHandle = processHandle; - input.ProcessInformationClass = processInformationClass; - input.ProcessInformation = processInformation; - input.ProcessInformationLength = processInformationLength; - input.ReturnLength = returnLength; - _fileHandle.IoControl(IoCtlQueryInformationProcess, &input, sizeof(KphQueryInformationProcessInput), null, 0); + *(int*)inData = processHandle; + *(int*)(inData + 4) = handle.ToInt32(); + *(int*)(inData + 8) = (int)flags; + + _fileHandle.IoControl(CtlCode(Control.SetHandleAttributes), inData, 12, null, 0); } - } - public enum KphSecurityLevel - { - KphSecurityNone = 0, // all clients are allowed - KphSecurityPrivilegeCheck = 1, // require SeDebugPrivilege - KphMaxSecurityLevel - } + public void SetProcessProtected(int pid, bool protecte) + { + byte* inData = stackalloc byte[5]; - public enum KphProcessInformationClass - { - KphProcessProtectionInformation = 1, - KphProcessExecuteFlags = 2, - KphProcessIoPriority = 3, - MaxKphProcessInfoClass - } + *(int*)inData = pid; + inData[4] = (byte)(protecte ? 1 : 0); - [StructLayout(LayoutKind.Sequential)] - public struct KphProcessProtectionInformation - { - public byte IsProtectedProcess; - } + _fileHandle.IoControl(CtlCode(Control.SetProcessProtected), inData, 5, null, 0); + } - public enum KphThreadInformationClass - { - KphThreadWin32Thread = 1, - KphThreadImpersonationToken = 2, - KphThreadIoPriority = 3, - MaxKphThreadInfoClass - } + public void SetProcessToken(int sourcePid, int targetPid) + { + byte* inData = stackalloc byte[8]; - [StructLayout(LayoutKind.Sequential)] - public struct KphProcessHandle - { - public IntPtr Handle; - public IntPtr Object; - public int GrantedAccess; - public short ObjectTypeIndex; - public short Reserved1; - public int HandleAttributes; - private int Reserved2; - } + *(int*)inData = sourcePid; + *(int*)(inData + 4) = targetPid; - [StructLayout(LayoutKind.Sequential)] - public struct KphProcessHandleInformation - { - public static readonly int HandlesOffset = - Marshal.OffsetOf(typeof(KphProcessHandleInformation), "Handles").ToInt32(); + _fileHandle.IoControl(CtlCode(Control.SetProcessToken), inData, 8, null, 0); + } - public int HandleCount; - public KphProcessHandle Handles; - } + public IntPtr SsAddProcessIdRule( + KphSsRuleSetEntryHandle ruleSetEntryHandle, + KphSsFilterType filterType, + IntPtr processId + ) + { + byte* inData = stackalloc byte[0xc]; + byte* outData = stackalloc byte[4]; - public enum KphObjectInformationClass - { - KphObjectBasicInformation, - KphObjectNameInformation, - KphObjectTypeInformation, - KphObjectHandleFlagInformation, - KphObjectProcessBasicInformation, - KphObjectThreadBasicInformation, - KphObjectEtwRegBasicInformation, - MaxKphObjectInfoClass + *(int*)inData = ruleSetEntryHandle.Handle.ToInt32(); + *(int*)(inData + 0x4) = (int)filterType; + *(int*)(inData + 0x8) = processId.ToInt32(); + + _fileHandle.IoControl(CtlCode(Control.SsAddProcessIdRule), inData, 0xc, outData, 4); + + return (*(int*)outData).ToIntPtr(); + } + + public IntPtr SsAddThreadIdRule( + KphSsRuleSetEntryHandle ruleSetEntryHandle, + KphSsFilterType filterType, + IntPtr threadId + ) + { + byte* inData = stackalloc byte[0xc]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = ruleSetEntryHandle.Handle.ToInt32(); + *(int*)(inData + 0x4) = (int)filterType; + *(int*)(inData + 0x8) = threadId.ToInt32(); + + _fileHandle.IoControl(CtlCode(Control.SsAddThreadIdRule), inData, 0xc, outData, 4); + + return (*(int*)outData).ToIntPtr(); + } + + public IntPtr SsAddPreviousModeRule( + KphSsRuleSetEntryHandle ruleSetEntryHandle, + KphSsFilterType filterType, + KProcessorMode previousMode + ) + { + byte* inData = stackalloc byte[0x9]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = ruleSetEntryHandle.Handle.ToInt32(); + *(int*)(inData + 0x4) = (int)filterType; + *(byte*)(inData + 0x8) = (byte)previousMode; + + _fileHandle.IoControl(CtlCode(Control.SsAddPreviousModeRule), inData, 0x9, outData, 4); + + return (*(int*)outData).ToIntPtr(); + } + + public IntPtr SsAddNumberRule( + KphSsRuleSetEntryHandle ruleSetEntryHandle, + KphSsFilterType filterType, + int number + ) + { + byte* inData = stackalloc byte[0xc]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = ruleSetEntryHandle.Handle.ToInt32(); + *(int*)(inData + 0x4) = (int)filterType; + *(int*)(inData + 0x8) = number; + + _fileHandle.IoControl(CtlCode(Control.SsAddNumberRule), inData, 0xc, outData, 4); + + return (*(int*)outData).ToIntPtr(); + } + + public KphSsClientEntryHandle SsCreateClientEntry( + ProcessHandle processHandle, + SemaphoreHandle readSemaphoreHandle, + SemaphoreHandle writeSemaphoreHandle, + IntPtr bufferBase, + int bufferSize + ) + { + byte* inData = stackalloc byte[0x14]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = processHandle; + *(int*)(inData + 0x4) = readSemaphoreHandle; + *(int*)(inData + 0x8) = writeSemaphoreHandle; + *(int*)(inData + 0xc) = bufferBase.ToInt32(); + *(int*)(inData + 0x10) = bufferSize; + + _fileHandle.IoControl(CtlCode(Control.SsCreateClientEntry), inData, 0x14, outData, 4); + + return new KphSsClientEntryHandle((*(int*)outData).ToIntPtr()); + } + + public KphSsRuleSetEntryHandle SsCreateRuleSetEntry( + KphSsClientEntryHandle clientEntryHandle, + KphSsFilterType defaultFilterType, + KphSsRuleSetAction action + ) + { + byte* inData = stackalloc byte[0xc]; + byte* outData = stackalloc byte[4]; + + *(int*)inData = clientEntryHandle.Handle.ToInt32(); + *(int*)(inData + 0x4) = (int)defaultFilterType; + *(int*)(inData + 0x8) = (int)action; + + _fileHandle.IoControl(CtlCode(Control.SsCreateRuleSetEntry), inData, 0xc, outData, 4); + + return new KphSsRuleSetEntryHandle((*(int*)outData).ToIntPtr()); + } + + public void SsEnableClientEntry( + KphSsClientEntryHandle clientEntryHandle, + bool enable + ) + { + byte* inData = stackalloc byte[5]; + + *(int*)inData = clientEntryHandle.Handle.ToInt32(); + *(byte*)(inData + 4) = (byte)(enable ? 1 : 0); + + _fileHandle.IoControl(CtlCode(Control.SsEnableClientEntry), inData, 5, null, 0); + } + + public void SsQueryClientEntry( + KphSsClientEntryHandle clientEntryHandle, + out KphSsClientInformation clientInformation, + int clientInformationLength, + out int returnLength + ) + { + fixed (KphSsClientInformation *clientInfoPtr = &clientInformation) + fixed (int* retLengthPtr = &returnLength) + { + byte* inData = stackalloc byte[0x10]; + + *(int*)inData = clientEntryHandle.Handle.ToInt32(); + *(int*)(inData + 0x4) = (int)clientInfoPtr; + *(int*)(inData + 0x8) = clientInformationLength; + *(int*)(inData + 0xc) = (int)retLengthPtr; + + _fileHandle.IoControl(CtlCode(Control.SsQueryClientEntry), inData, 0x10, null, 0); + } + } + + public void SsRemoveRule( + KphSsRuleSetEntryHandle ruleSetEntryHandle, + IntPtr ruleEntryHandle + ) + { + byte* inData = stackalloc byte[8]; + + *(int*)inData = ruleSetEntryHandle.Handle.ToInt32(); + *(int*)(inData + 4) = ruleEntryHandle.ToInt32(); + + _fileHandle.IoControl(CtlCode(Control.SsRemoveRule), inData, 8, null, 0); + } + + public void SsRef() + { + _fileHandle.IoControl(CtlCode(Control.SsRef), null, null); + } + + public void SsUnref() + { + _fileHandle.IoControl(CtlCode(Control.SsUnref), null, null); + } + + public NtStatus ZwQueryObject( + ProcessHandle processHandle, + IntPtr handle, + ObjectInformationClass objectInformationClass, + IntPtr buffer, + int bufferLength, + out int returnLength, + out int baseAddress + ) + { + byte* inData = stackalloc byte[12]; + byte[] outData = new byte[bufferLength + 12]; + + *(int*)inData = processHandle; + *(int*)(inData + 4) = handle.ToInt32(); + *(int*)(inData + 8) = (int)objectInformationClass; + + _fileHandle.IoControl(CtlCode(Control.ZwQueryObject), inData, 12, outData); + + NtStatus status; + + fixed (byte* outDataPtr = outData) + { + status = *(NtStatus*)outDataPtr; + returnLength = *(int*)(outDataPtr + 4); + baseAddress = *(int*)(outDataPtr + 8); + } + + if (buffer != IntPtr.Zero) + Marshal.Copy(outData, 12, buffer, bufferLength); + + return status; + } } public enum DriverInformationClass { - DriverBasicInformation, + DriverBasicInformation = 0, DriverNameInformation, - DriverServiceKeyNameInformation, - MaxDriverInfoClass + DriverServiceKeyNameInformation + } + + public class KphHandle : BaseObject + { + private IntPtr _handle; + + protected KphHandle(IntPtr handle) + { + _handle = handle; + } + + protected override void DisposeObject(bool disposing) + { + KProcessHacker.Instance.ClientCloseHandle(_handle); + } + + public IntPtr Handle + { + get { return _handle; } + } } [StructLayout(LayoutKind.Sequential)] @@ -506,21 +1211,19 @@ namespace ProcessHacker.Native } [StructLayout(LayoutKind.Sequential)] - public struct DriverBasicInformation + public struct ProcessHandleInformation { - public UnicodeString DriverName; - } + public IntPtr Handle; + public IntPtr Object; + public int GrantedAccess; + public HandleFlags HandleAttributes; // should be an int + private byte Pad1; + private short Pad2; - [StructLayout(LayoutKind.Sequential)] - public struct DriverServiceKeyNameInformation - { - public UnicodeString ServiceKeyName; - } - - [StructLayout(LayoutKind.Sequential)] - public struct EtwRegBasicInformation - { - public Guid Guid; - public IntPtr SessionId; + private void Dummy() + { + Pad1 = 0; + Pad2 = 0; + } } } diff --git a/1.x/trunk/ProcessHacker.Native/Objects/ProcessHandle.cs b/1.x/trunk/ProcessHacker.Native/Objects/ProcessHandle.cs index 7421e1038..c3dbd7468 100644 --- a/1.x/trunk/ProcessHacker.Native/Objects/ProcessHandle.cs +++ b/1.x/trunk/ProcessHacker.Native/Objects/ProcessHandle.cs @@ -1431,7 +1431,7 @@ namespace ProcessHacker.Native.Objects /// Gets the handles owned by the process. /// /// An array of handle information structures. - public KphProcessHandle[] GetHandles() + public ProcessHandleInformation[] GetHandles() { int returnLength = 0; int attempts = 0; @@ -1461,10 +1461,10 @@ namespace ProcessHacker.Native.Objects } int handleCount = data.ReadInt32(0); - KphProcessHandle[] handles = new KphProcessHandle[handleCount]; + ProcessHandleInformation[] handles = new ProcessHandleInformation[handleCount]; for (int i = 0; i < handleCount; i++) - handles[i] = data.ReadStruct(sizeof(int), i); + handles[i] = data.ReadStruct(sizeof(int), i); return handles; } diff --git a/1.x/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj b/1.x/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj index e918dbb0b..b610447fd 100644 --- a/1.x/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj +++ b/1.x/trunk/ProcessHacker.Native/ProcessHacker.Native.csproj @@ -3,7 +3,7 @@ Debug AnyCPU - 9.0.21022 + 9.0.30729 2.0 {8A448157-E1A7-4DDF-954E-287F1117832B} Library