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:
  1. Imports System.Runtime.InteropServices
  2. Public Class WindowsAPI
  3.     Public Const PROCESS_ALL_ACCESS = &H1F0FFF
  4.  
  5.     <DllImport("kernel32.dll")> _
  6.     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
  7.     End Function
  8.  
  9.     <DllImport("kernel32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto, SetLastError:=True)> _
  10.     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
  11.     End Function
  12.  
  13.     <DllImport("kernel32.dll", SetLastError:=True)> _
  14.     Public Shared Function OpenProcess(ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
  15.     End Function
  16.  
  17.     <DllImport("kernel32.dll", SetLastError:=True)> _
  18.     Public Shared Function CloseHandle(ByVal handle As IntPtr) As Boolean
  19.     End Function
  20. End Class

MemoryScanner Class
vb.net Code:
  1. Imports System.Runtime.InteropServices
  2.  
  3. Public Class MemoryReader
  4.     Public Shared Function GetStructure(Of T)(ByVal TargetProcess As Process, ByVal Address As Integer) As T
  5.         'Create a variable to store the number of bytes written
  6.         Dim lpBytesWritten As Integer = 0
  7.         'Allocate memory to hold the structure
  8.         Dim buffer As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(T)))
  9.         'Open the process for reading
  10.         Dim procPtr As IntPtr = WindowsAPI.OpenProcess(WindowsAPI.PROCESS_ALL_ACCESS, False, TargetProcess.Id)
  11.         'Read the data into the previously created buffer
  12.         WindowsAPI.ReadProcessMemory(procPtr, New IntPtr(Address), buffer, Marshal.SizeOf(GetType(T)), lpBytesWritten)
  13.         'Marshal the pointer to the return structure type
  14.         Dim retValue As T = CType(Marshal.PtrToStructure(buffer, GetType(T)), T)
  15.         'Free up the allocated memory
  16.         Marshal.FreeCoTaskMem(buffer)
  17.         'Close the process handle
  18.         WindowsAPI.CloseHandle(procPtr)
  19.         'Return the object
  20.         Return retValue
  21.     End Function
  22. End Class

Example usage
vb.net Code:
  1. Imports System.Runtime.InteropServices
  2. Public Class Class1
  3.     'This is an example structure.
  4.     <StructLayout(LayoutKind.Sequential)> _
  5.     Public Structure SomeStruct
  6.         Dim ID As Integer
  7.         <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=24)> _
  8.         Dim Name As String
  9.     End Structure
  10.  
  11.     Public Function GetStructure() As SomeStruct
  12.         'Get a process object
  13.         'Obviously this is not how it would be done, but for this
  14.         'example it will suffice
  15.         Dim p As Process = Process.GetProcessById(100)
  16.         'Now we will read the structure form memory address 1000000 in or fake process
  17.         Return MemoryReader.GetStructure(Of SomeStruct)(p, 1000000)
  18.     End Function
  19. End Class