Clase: MemoryManager
Esta clase sirve para leer una determinada dirección de memoria en un proceso basado en el nombre de la ventana.
Código:
Public Class MemoryManager Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAcess As UInt32, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Int32) As IntPtr Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer() As Byte, ByVal iSize As Integer, ByRef lpNumberOfBytesRead As Integer) As Boolean Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As IntPtr) As Boolean Private _targetProcess As Process = Nothing Private _targetProcessHandle As IntPtr = IntPtr.Zero Private PROCESS_ALL_ACCESS As UInt32 = &H1F0FFF Private PROCESS_VM_READ As UInt32 = &H10 Public Function TryAttachToProcess(ByVal windowCaption As String) As Boolean Dim _allProcesses() As Process = Process.GetProcesses For Each pp As Process In _allProcesses If pp.MainWindowTitle.ToLower.Contains(windowCaption.ToLower) Then Return TryAttachToProcess(pp) End If Next MessageBox.Show("Imposible encontrar el proceso: '" & windowCaption & ".") Return False End Function Public Function TryAttachToProcess(ByVal proc As Process) As Boolean If _targetProcessHandle = IntPtr.Zero Then _targetProcess = proc _targetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, False, _targetProcess.Id) If _targetProcessHandle = 0 Then TryAttachToProcess = False MessageBox.Show("Error al abrir el proceso") Else TryAttachToProcess = True ' MessageBox.Show("Proceso abierto correctamente") End If Else MessageBox.Show("Proceso ya abierto! (Por favor cierrelo primero)") TryAttachToProcess = False End If End Function Public Sub DetachFromProcess() If Not (_targetProcessHandle = IntPtr.Zero) Then _targetProcess = Nothing Try CloseHandle(_targetProcessHandle) _targetProcessHandle = IntPtr.Zero 'MessageBox.Show("MemReader::Detach() OK") Catch ex As Exception MessageBox.Show("MemoryManager::DetachFromProcess::CloseHandle error " & Environment.NewLine & ex.Message) End Try End If End Sub Public Function ReadInt16(ByVal addr As IntPtr) As Int16 Dim _rtnBytes(1) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, 2, vbNull) Return BitConverter.ToInt16(_rtnBytes, 0) End Function Public Function ReadInt32(ByVal addr As IntPtr) As Int32 Dim _rtnBytes(3) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, 4, vbNull) Return BitConverter.ToInt32(_rtnBytes, 0) End Function Public Function ReadInt64(ByVal addr As IntPtr) As Int64 Dim _rtnBytes(7) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, 8, vbNull) Return BitConverter.ToInt64(_rtnBytes, 0) End Function Public Function ReadUInt16(ByVal addr As IntPtr) As UInt16 Dim _rtnBytes(1) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, 2, vbNull) Return BitConverter.ToUInt16(_rtnBytes, 0) End Function Public Function ReadUInt32(ByVal addr As IntPtr) As UInt32 Dim _rtnBytes(3) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, 4, vbNull) Return BitConverter.ToUInt32(_rtnBytes, 0) End Function Public Function ReadUInt64(ByVal addr As IntPtr) As UInt64 Dim _rtnBytes(7) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, 8, vbNull) Return BitConverter.ToUInt64(_rtnBytes, 0) End Function Public Function ReadFloat(ByVal addr As IntPtr) As Single Dim _rtnBytes(3) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, 4, vbNull) Return BitConverter.ToSingle(_rtnBytes, 0) End Function Public Function ReadDouble(ByVal addr As IntPtr) As Double Dim _rtnBytes(7) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, 8, vbNull) Return BitConverter.ToDouble(_rtnBytes, 0) End Function Public Function ReadIntPtr(ByVal addr As IntPtr) As IntPtr Dim _rtnBytes(IntPtr.Size - 1) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, IntPtr.Size, Nothing) If IntPtr.Size = 4 Then Return New IntPtr(BitConverter.ToUInt32(_rtnBytes, 0)) Else Return New IntPtr(BitConverter.ToInt64(_rtnBytes, 0)) End If End Function Public Function ReadBytes(ByVal addr As IntPtr, ByVal size As Int32) As Byte() Dim _rtnBytes(size - 1) As Byte ReadProcessMemory(_targetProcessHandle, addr, _rtnBytes, size, vbNull) Return _rtnBytes End Function End Class
Ejemplo de uso:
Public Class Form1 Private _memManager As New MemoryManager Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click If _memManager.TryAttachToProcess(TextBox1.Text) Then Dim _myScore As Int32 Dim CorrijeDireccion As String = "&H" & TextBox2.Text _myScore = _memManager.ReadInt32(CorrijeDireccion) _memManager.DetachFromProcess() MessageBox.Show(_myScore.ToString()) Else MessageBox.Show("MemoryManager: Imposible leer el proceso.") End If End Sub End Class
Descarga del ejemplo: lectormemoria.rar
Nota: Para obtener la dirección de memoria existen programas como el Cheat Engine, que al introducirle el valor actual en diferentes situaciones (según va cambiando el valor), este detecta los cambios hasta dar con la dirección.
