ReadProcessMemory sigue devolviendo 0
-
19-08-2019 - |
Pregunta
Actualmente estoy desarrollando un pequeño proyecto de pasatiempo para mostrar información de salud en un juego en mi teclado G15 a través de VB.NET.
Cuando uso ReadProcessMemory a través de una llamada API, sigue devolviendo cero. La documentación de MSDN me refirió a usar la llamada Marshal.GetLastWin32Error () para averiguar qué está mal y devuelve 1400: MANGO DE VENTANA NO VÁLIDO.
Ahora estoy confundido acerca de si el primer argumento de la función quiere un identificador de ventana o una identificación de proceso. De todos modos, he intentado con FindWindow y codificar la identificación del proceso mientras la aplicación se está ejecutando (obteniéndola del administrador de tareas).
He probado tres juegos diferentes, Urban Terror, Grand Theft Auto: SA y 3D pinball para Windows, obteniendo las direcciones de memoria de una aplicación llamada Cheat Engine; todos parecen fallar.
Aquí está el código que estoy usando para hacerlo:
Llamada API:
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
Método:
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))
¿Podría alguien explicarme por qué no funciona? Gracias de antemano.
Solución
Primero, la firma de su método es incorrecta, Single = Float mientras el parámetro original es del tipo LPBUF.
Utilice la firma de este método:
<DllImport("kernel32.dll", SetLastError=true)> _
Public Shared Function ReadProcessMemory( _
ByVal hProcess As IntPtr, _
ByVal lpBaseAddress As IntPtr, _
<Out()>ByVal lpBuffer() As Byte, _
ByVal dwSize as Integer, _
ByRef lpNumberOfBytesRead as Integer
) As Boolean
End Function
Segundo, creo que el identificador hProcess espera un identificador abierto por la función OpenProcess, no el identificador de ventana.
Otros consejos
Gracias Arul, he solucionado mi problema.
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
Ahora cree que el identificador es válido e intenta leer la memoria de procesos, pero recibo el mensaje de error 299: solo se completó parte de una solicitud ReadProcessMemory o WriteProcessMemory.
¿Alguien tiene alguna idea de cómo debo proceder para solucionar este problema?
mensaje 299: solo una parte de una solicitud ReadProcessMemory o WriteProcessMemory se completó significaba que la memoria que intentaba leer estaba protegida.
Gracias por toda su ayuda, voy a marcar la respuesta de arul como la respuesta.