[2005/2008] Reading a structure from an external processes memory
I have a few projects that deal with external processes and reading their data from memory. I wrote this function to read a structure from memory at a given address in any external process. It is generic so that any structure can be read. To use this function you must know the structure layout and the proper address in the remote process. I have not gotten into how to find the proper address to read or how to search for the process to use. This example is merely to show how to read any structure from any process with a single function.
WindowsAPI Class
vb.net Code:
Imports System.Runtime.InteropServices
Public Class WindowsAPI
Public Const PROCESS_ALL_ACCESS = &H1F0FFF
<DllImport("kernel32.dll")> _
Public Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, <Out()> ByVal lpBuffer As Byte(), ByVal nSize As UIntPtr, ByVal lpNumberOfBytesRead As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As IntPtr, ByVal iSize As Integer, ByRef lpNumberOfBytesRead As Integer) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Shared Function OpenProcess(ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Shared Function CloseHandle(ByVal handle As IntPtr) As Boolean
End Function
End Class
MemoryScanner Class
vb.net Code:
Imports System.Runtime.InteropServices
Public Class MemoryReader
Public Shared Function GetStructure(Of T)(ByVal TargetProcess As Process, ByVal Address As Integer) As T
'Create a variable to store the number of bytes written
Dim lpBytesWritten As Integer = 0
'Allocate memory to hold the structure
Dim buffer As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(T)))
'Open the process for reading
Dim procPtr As IntPtr = WindowsAPI.OpenProcess(WindowsAPI.PROCESS_ALL_ACCESS, False, TargetProcess.Id)
'Read the data into the previously created buffer
WindowsAPI.ReadProcessMemory(procPtr, New IntPtr(Address), buffer, Marshal.SizeOf(GetType(T)), lpBytesWritten)
'Marshal the pointer to the return structure type
Dim retValue As T = CType(Marshal.PtrToStructure(buffer, GetType(T)), T)
'Free up the allocated memory
Marshal.FreeCoTaskMem(buffer)
'Close the process handle
WindowsAPI.CloseHandle(procPtr)
'Return the object
Return retValue
End Function
End Class
Example usage
vb.net Code:
Imports System.Runtime.InteropServices
Public Class Class1
'This is an example structure.
<StructLayout(LayoutKind.Sequential)> _
Public Structure SomeStruct
Dim ID As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=24)> _
Dim Name As String
End Structure
Public Function GetStructure() As SomeStruct
'Get a process object
'Obviously this is not how it would be done, but for this
'example it will suffice
Dim p As Process = Process.GetProcessById(100)
'Now we will read the structure form memory address 1000000 in or fake process
Return MemoryReader.GetStructure(Of SomeStruct)(p, 1000000)
End Function
End Class