diff --git a/trunk/KProcessHacker/i386/kprocesshacker.sys b/trunk/KProcessHacker/i386/kprocesshacker.sys index d164edc81..4c012daf2 100644 Binary files a/trunk/KProcessHacker/i386/kprocesshacker.sys and b/trunk/KProcessHacker/i386/kprocesshacker.sys differ diff --git a/trunk/KProcessHacker/kph_nt.c b/trunk/KProcessHacker/kph_nt.c index 5cf18306f..b24f7df8b 100644 --- a/trunk/KProcessHacker/kph_nt.c +++ b/trunk/KProcessHacker/kph_nt.c @@ -457,3 +457,41 @@ NTSTATUS KphTerminateProcess( return status; } + +NTSTATUS KphReadVirtualMemory( + HANDLE ProcessHandle, + PVOID BaseAddress, + PVOID Buffer, + ULONG BufferLength, + PULONG ReturnLength, + KPROCESSOR_MODE AccessMode + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS processObject; + ULONG returnLength = 0; + + if (BufferLength) + { + status = ObReferenceObjectByHandle(ProcessHandle, 0, *PsProcessType, KernelMode, &processObject, NULL); + + if (!NT_SUCCESS(status)) + return status; + + status = MmCopyVirtualMemory( + processObject, + BaseAddress, + PsGetCurrentProcess(), + Buffer, + BufferLength, + AccessMode, + &returnLength + ); + ObDereferenceObject(processObject); + } + + if (ReturnLength) + *ReturnLength = returnLength; + + return status; +} diff --git a/trunk/KProcessHacker/kph_nt.h b/trunk/KProcessHacker/kph_nt.h index ecef9dd5e..27d91799f 100644 --- a/trunk/KProcessHacker/kph_nt.h +++ b/trunk/KProcessHacker/kph_nt.h @@ -26,7 +26,6 @@ #include "kprocesshacker.h" #include "kernel_types.h" -/* Kernel API */ NTSTATUS NTAPI ObOpenObjectByName( POBJECT_ATTRIBUTES ObjectAttributes, POBJECT_TYPE ObjectType, @@ -37,6 +36,16 @@ NTSTATUS NTAPI ObOpenObjectByName( PHANDLE Handle ); +NTSTATUS NTAPI MmCopyVirtualMemory( + PEPROCESS FromProcess, + PVOID FromAddress, + PEPROCESS ToProcess, + PVOID ToAddress, + ULONG BufferLength, + KPROCESSOR_MODE AccessMode, + PULONG ReturnLength + ); + NTSTATUS NTAPI PsLookupProcessThreadByCid( PCLIENT_ID ClientId, PEPROCESS *Process, @@ -62,7 +71,7 @@ NTSTATUS PsResumeProcess( PEPROCESS Process ); -/* KProcessHacker versions */ +/* KProcessHacker */ NTSTATUS KphOpenProcess( PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, @@ -107,6 +116,15 @@ NTSTATUS KphTerminateProcess( NTSTATUS ExitStatus ); +NTSTATUS KphReadVirtualMemory( + HANDLE ProcessHandle, + PVOID BaseAddress, + PVOID Buffer, + ULONG BufferLength, + PULONG ReturnLength, + KPROCESSOR_MODE AccessMode + ); + NTSTATUS OpenProcess( PHANDLE ProcessHandle, int DesiredAccess, diff --git a/trunk/KProcessHacker/kprocesshacker.c b/trunk/KProcessHacker/kprocesshacker.c index 63804b19b..a502bfdb5 100644 --- a/trunk/KProcessHacker/kprocesshacker.c +++ b/trunk/KProcessHacker/kprocesshacker.c @@ -268,8 +268,8 @@ char *GetIoControlName(ULONG ControlCode) return "KphSuspendProcess"; else if (ControlCode == KPH_RESUMEPROCESS) return "KphResumeProcess"; - else if (ControlCode == KPH_READPROCESSMEMORY) - return "Read Process Memory"; + else if (ControlCode == KPH_READVIRTUALMEMORY) + return "KphReadVirtualMemory"; else if (ControlCode == KPH_SETPROCESSTOKEN) return "Set Process Token"; else if (ControlCode == KPH_GETTHREADWIN32STARTADDRESS) @@ -651,41 +651,26 @@ NTSTATUS KphIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } break; - case KPH_READPROCESSMEMORY: + case KPH_READVIRTUALMEMORY: { HANDLE processHandle; PVOID baseAddress; - PKPROCESS processObject; - KAPC_STATE apcState; + PVOID buffer; + ULONG bufferLength; - if (inLength < 8) + if (inLength < 8 || outLength < 4) { status = STATUS_BUFFER_TOO_SMALL; goto IoControlEnd; } processHandle = *(HANDLE *)dataBuffer; - baseAddress = *(PVOID *)(dataBuffer + 4); + baseAddress = *(PVOID *)(dataBuffer + 0x4); + buffer = *(PVOID *)(dataBuffer + 0x8); + bufferLength = *(PULONG)(dataBuffer + 0xc); - status = ObReferenceObjectByHandle(processHandle, 0, *PsProcessType, KernelMode, &processObject, 0); - - if (!NT_SUCCESS(status)) - goto IoControlEnd; - - KeStackAttachProcess(processObject, &apcState); - - __try - { - RtlCopyMemory(dataBuffer, baseAddress, outLength); - retLength = outLength; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - status = STATUS_ACCESS_VIOLATION; - } - - KeUnstackDetachProcess(&apcState); - ObDereferenceObject(processObject); + status = KphReadVirtualMemory(processHandle, baseAddress, buffer, bufferLength, (PULONG)dataBuffer, UserMode); + retLength = 4; } break; diff --git a/trunk/KProcessHacker/kprocesshacker.h b/trunk/KProcessHacker/kprocesshacker.h index b97fdd62c..b64ee3b4d 100644 --- a/trunk/KProcessHacker/kprocesshacker.h +++ b/trunk/KProcessHacker/kprocesshacker.h @@ -53,7 +53,7 @@ typedef struct _SYSTEM_HANDLE_INFORMATION #define KPH_TERMINATEPROCESS KPH_CTL_CODE(8) #define KPH_SUSPENDPROCESS KPH_CTL_CODE(9) #define KPH_RESUMEPROCESS KPH_CTL_CODE(10) -#define KPH_READPROCESSMEMORY KPH_CTL_CODE(11) +#define KPH_READVIRTUALMEMORY KPH_CTL_CODE(11) #define KPH_SETPROCESSTOKEN KPH_CTL_CODE(12) #define KPH_GETTHREADWIN32STARTADDRESS KPH_CTL_CODE(13) #define KPH_GETOBJECTNAME KPH_CTL_CODE(14) diff --git a/trunk/ProcessHacker/Forms/ThreadWindow.cs b/trunk/ProcessHacker/Forms/ThreadWindow.cs index 7d33b3758..2c87a7893 100644 --- a/trunk/ProcessHacker/Forms/ThreadWindow.cs +++ b/trunk/ProcessHacker/Forms/ThreadWindow.cs @@ -259,8 +259,8 @@ namespace ProcessHacker { try { - Array.Copy(Program.KPH.ReadProcessMemory(Win32.ProcessHandle.FromHandle(processHandle), - baseAddress, size), buffer, size); + Program.KPH.KphReadVirtualMemory(Win32.ProcessHandle.FromHandle(processHandle), + baseAddress, buffer, size, out bytesRead); bytesRead = size; return true; } diff --git a/trunk/ProcessHacker/KProcessHacker.cs b/trunk/ProcessHacker/KProcessHacker.cs index 315760c1e..4668d28ba 100644 --- a/trunk/ProcessHacker/KProcessHacker.cs +++ b/trunk/ProcessHacker/KProcessHacker.cs @@ -52,7 +52,7 @@ namespace ProcessHacker KphTerminateProcess, KphSuspendProcess, KphResumeProcess, - ReadProcessMemory, + KphReadVirtualMemory, SetProcessToken, GetThreadWin32StartAddress, GetObjectName, @@ -261,6 +261,24 @@ namespace ProcessHacker _fileHandle.IoControl(CtlCode(Control.KphOpenThread), inData, outData); return Misc.BytesToInt(outData, Misc.Endianness.Little); + } + + public unsafe void KphReadVirtualMemory(Win32.ProcessHandle processHandle, int baseAddress, byte[] buffer, int length, out int bytesRead) + { + byte[] data = new byte[16]; + byte[] result = new byte[4]; + + fixed (byte* bufferPointer = buffer) + { + Array.Copy(Misc.IntToBytes(processHandle, Misc.Endianness.Little), 0, data, 0, 4); + Array.Copy(Misc.IntToBytes(baseAddress, Misc.Endianness.Little), 0, data, 4, 4); + Array.Copy(Misc.IntToBytes((int)bufferPointer, Misc.Endianness.Little), 0, data, 8, 4); + Array.Copy(Misc.IntToBytes(length, Misc.Endianness.Little), 0, data, 12, 4); + + _fileHandle.IoControl(CtlCode(Control.KphReadVirtualMemory), data, result); + + bytesRead = Misc.BytesToInt(result, Misc.Endianness.Little); + } } public void KphResumeProcess(Win32.ProcessHandle processHandle) @@ -304,19 +322,6 @@ namespace ProcessHacker return buffer; } - public byte[] ReadProcessMemory(Win32.ProcessHandle processHandle, int baseAddress, int length) - { - byte[] data = new byte[8]; - byte[] readData = new byte[length]; - - Array.Copy(Misc.IntToBytes(processHandle, Misc.Endianness.Little), 0, data, 0, 4); - Array.Copy(Misc.IntToBytes(baseAddress, Misc.Endianness.Little), 0, data, 4, 4); - - _fileHandle.IoControl(CtlCode(Control.ReadProcessMemory), data, readData); - - return readData; - } - public void SetProcessProtected(int pid, bool protecte) { byte[] data = new byte[5]; diff --git a/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs b/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs index a19ded021..ab1b3db06 100644 --- a/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs +++ b/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs @@ -643,8 +643,15 @@ namespace ProcessHacker byte[] buf = new byte[length]; int readLen; - if (!ReadProcessMemory(this, offset, buf, length, out readLen)) - ThrowLastWin32Error(); + if (Program.KPH != null) + { + Program.KPH.KphReadVirtualMemory(this, offset, buf, length, out readLen); + } + else + { + if (!ReadProcessMemory(this, offset, buf, length, out readLen)) + ThrowLastWin32Error(); + } return buf; }