ReadProcessMemory continua a restituire 0
-
19-08-2019 - |
Domanda
Attualmente sto sviluppando un piccolo progetto hobby per visualizzare informazioni sulla salute in un gioco sulla mia tastiera G15 tramite VB.NET.
Quando utilizzo ReadProcessMemory tramite una chiamata API, continua a restituire zero. La documentazione MSDN mi ha fatto riferimento per utilizzare la chiamata Marshal.GetLastWin32Error () per scoprire cosa non va e restituisce 1400: MANIGLIA FINESTRA NON VALIDA.
Ora sono confuso sul fatto che il primo argomento della funzione voglia un handle di finestra o un ID processo. Indipendentemente da ciò, ho provato sia con FindWindow sia a codificare l'ID del processo mentre l'applicazione è in esecuzione (ottenerlo dal task manager).
Ho provato tre diversi giochi, Urban Terror, Grand Theft Auto: SA e 3D flipper per Windows, ottenendo gli indirizzi di memoria da un'applicazione chiamata Cheat Engine; sembrano tutti fallire.
Ecco il codice che sto usando per farlo:
Chiamata 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
Metodo:
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))
Qualcuno potrebbe spiegarmi perché non funziona? Grazie in anticipo.
Soluzione
Innanzitutto, la firma del metodo è errata, Single = Float mentre il parametro originale è del tipo LPBUF.
Usa questa firma del metodo:
<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
In secondo luogo, credo che l'handle hProcess prevede un handle aperto dalla funzione OpenProcess, non l'handle della finestra.
Altri suggerimenti
Grazie arul, ho risolto il mio 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
Ora ritiene che l'handle sia valido e tenta di leggere la memoria dei processi, ma viene visualizzato il messaggio di errore 299: È stata completata solo una parte di una richiesta ReadProcessMemory o WriteProcessMemory.
Qualcuno ha qualche idea su come dovrei procedere per risolvere questo problema?
messaggio 299: solo una parte di una richiesta ReadProcessMemory o WriteProcessMemory è stata completata significa che la memoria che stavo cercando di leggere era protetta.
Grazie per tutto il tuo aiuto, segnerò la risposta di Arul come risposta.