views:

1416

answers:

4

I'm currently developing a little hobby project to display health information in a game on my G15 keyboard through VB.NET.

When I use ReadProcessMemory via an API call, it keeps returning zero. The MSDN documentation referred me to use the Marshal.GetLastWin32Error() call to find out what is wrong and it returns 1400: INVALID WINDOW HANDLE.

I am now confused about whether the first argument of the function wants a window handle or a process id. Regardless, I have tried both with FindWindow and hardcoding the process id while the application is running (getting it from task manager).

I have tried three different games, Urban Terror, Grand Theft Auto: SA and 3D pinball for windows, getting the memory addresses from an application called Cheat Engine; they all seem to fail.

Here is the code I'm using to do it:

API Call:

Private Declare Function ReadProcessMemory Lib "kernel32" ( _
ByVal hProcess As Integer, _
ByVal lpBaseAddress As Integer, _
ByRef lpBuffer As Single, _
ByVal nSize As Integer, _
ByRef lpNumberOfBytesWritten As Integer _
) As Integer

Method:

Dim address As Integer
address = &HA90C62&
Dim valueinmemory As Integer

Dim proc As Process = Process.GetCurrentProcess
For Each proc In Process.GetProcesses
    If proc.MainWindowTitle = "3D Pinball for Windows - Space Cadet" Then
        If ReadProcessMemory(proc.Handle.ToInt32, address, valueinmemory, 4, 0) = 0 Then
            MsgBox("aww")
        Else
            MsgBox(CStr(valueinmemory))
        End If
    End If
Next

Dim lastError As Integer
lastError = Marshal.GetLastWin32Error()
MessageBox.Show(CStr(lastError))

Could somebody please explain to me why it is not working? Thanks in advance.

+2  A: 

First, your method signature is wrong, Single=Float while the original parameter is of the LPBUF type.

Use this method signature:

_ Public Shared Function ReadProcessMemory( _ ByVal hProcess As IntPtr, _ ByVal lpBaseAddress As IntPtr, _ ByVal lpBuffer() As Byte, _ ByVal dwSize as Integer, _ ByRef lpNumberOfBytesRead as Integer ) As Boolean End Function

Second, I believe that the hProcess handle expects a handle opened by OpenProcess function, not the window handle.

arul
I will try this, thanks.
RodgerB
A: 

Thank you arul, I have sort of fixed my problem.

Dim address As Integer
address = &HA90C62&
Dim floatvalueinmemory() As Byte

Dim proc As Process = Process.GetCurrentProcess
For Each proc In Process.GetProcesses
    If proc.MainWindowTitle = "3D Pinball for Windows - Space Cadet" Then
        Dim winhandle As IntPtr = OpenProcess(PROCESS_ACCESS.PROCESS_VM_READ, True, proc.Id)

        If ReadProcessMemory(winhandle, address, floatvalueinmemory, 4, 0) = 0 Then
            Dim lastError As Integer
            lastError = Marshal.GetLastWin32Error()
            MessageBox.Show(CStr(lastError))
            MsgBox("aww")
        Else
            MsgBox("woo")
        End If

        CloseHandle(winhandle)
    End If
Next

Now it believes the handle is valid and attempts to read the processes memory, but I get the error message 299 : Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

Does anyone have any ideas as to how I should proceed to fix this issue?

RodgerB
A: 

message 299 : Only part of a ReadProcessMemory or WriteProcessMemory request was completed meant the memory I was trying to read was protected.

Thanks for all your help, I'm going to mark arul's answer as the answer.

RodgerB
A: 

How get the address (&HA90C62&) ???