Here is the code I'm using, as culled from other messages on this forum:

Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As String, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Const PROCESS_VM_READ = &H10
Sub Main()
x = RPMEM("WarBirds", &H5171D0, 1)
Debug.Print Asc(x)
Stop
End Sub

Public Function RPMEM(wndTitle As String, lAddress As Long, lLength As Long) As String
Dim hWnd As Long
Dim pID As Long
Dim pHandle As Long
Dim strBuffer As String
Dim succeed As Boolean

hWnd = FindWindow(vbNullString, wndTitle) ' get the handle of the window ...
If (hWnd = 0) Then Exit Function 'no handle & exit =)
GetWindowThreadProcessId hWnd, pID 'we need to get the proccess id to get the proccess handle .. *uuuummm*
pHandle = OpenProcess(PROCESS_VM_READ, False, pID) ' no comment ... =)
If (pHandle = 0) Then Exit Function 'mh. no handle. maybe we have no access to open this proccess with VM_READ
strBuffer = String(lLength, vbNullChar) 'fill the buffer
succeed = ReadProcessMemory(pHandle, lAddress, strBuffer, Len(strBuffer), 0&) 'read it out !
If Err.LastDllError = 998 Then Debug.Print "no acceess."
CloseHandle pHandle 'what we have opened we must(?) close ..
If succeed = True Then 'function succeed
RPMEM = strBuffer
Else
RPMEM = ""
End If
End Function