Share via

Memory Reader 32 to 64bit

Jean Carlo 0 Reputation points
2024-01-22T20:33:52.76+00:00

Hi, i'm having trouble with a memory reader, it doesn't work with a address bigger than a INTEGER, i tried to change a lot of things to LONG but none works.
How to update the code to work with 64bit address?

Module

Option Strict On

Imports System.Runtime.InteropServices
Imports System.Text

Module MemoryModule
    <DllImport("kernel32.dll")>
    Private Function OpenProcess(ByVal dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)>
    Private Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As Byte(), ByVal nSize As IntPtr, <Out()> ByRef lpNumberOfBytesWritten As IntPtr) As Boolean
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)>
    Private Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, <Out()> ByVal lpBuffer() As Byte, ByVal dwSize As IntPtr, ByRef lpNumberOfBytesRead As IntPtr) As Boolean
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)>
    Private Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    Private Const PROCESS_VM_WRITE As UInteger = &H20
    Private Const PROCESS_VM_READ As UInteger = &H10
    Private Const PROCESS_VM_OPERATION As UInteger = &H8
    'Target process name
    Public TargetProcess As String = "XXXXXXXXXXX"
    Public TargetIdd As Integer = 0
    Public ProcessHandle As IntPtr = IntPtr.Zero
    Public LastKnownPID As Integer = -1
    Public handle_s As System.Diagnostics.Process
    Public bAddress As Int64
    Public ic As Int64
    Public ch As Int64
    Public AdrPrincipal As String = "2787AE0"
    Public AdrCharN As String = "2787AE0"

    Private Declare Function ReadMemoryByte Lib "kernel32" Alias "ReadProcessMemory" (ByVal Handle As Integer, ByVal Address As Integer, ByRef Value As Byte, Optional ByVal Size As Integer = 2, Optional ByRef Bytes As Integer = 0) As Byte
    Private Declare Function ReadMemoryInteger Lib "kernel32" Alias "ReadProcessMemory" (ByVal Handle As Integer, ByVal Address As Integer, ByRef Value As Integer, Optional ByVal Size As Integer = 4, Optional ByRef Bytes As Integer = 0) As Integer
    Private Declare Function ReadMemoryFloat Lib "kernel32" Alias "ReadProcessMemory" (ByVal Handle As Integer, ByVal Address As Integer, ByRef Value As Single, Optional ByVal Size As Integer = 4, Optional ByRef Bytes As Integer = 0) As Single
    Private Declare Function ReadMemoryDouble Lib "kernel32" Alias "ReadProcessMemory" (ByVal Handle As Integer, ByVal Address As Integer, ByRef Value As Double, Optional ByVal Size As Integer = 8, Optional ByRef Bytes As Integer = 0) As Double

    Private Declare Function WriteMemoryByte Lib "kernel32" Alias "WriteProcessMemory" (ByVal Handle As Integer, ByVal Address As Integer, ByRef Value As Byte, Optional ByVal Size As Integer = 2, Optional ByRef Bytes As Integer = 0) As Byte
    Private Declare Function WriteMemoryInteger Lib "kernel32" Alias "WriteProcessMemory" (ByVal Handle As Integer, ByVal Address As Integer, ByRef Value As Integer, Optional ByVal Size As Integer = 4, Optional ByRef Bytes As Integer = 0) As Integer
    Private Declare Function WriteMemoryFloat Lib "kernel32" Alias "WriteProcessMemory" (ByVal Handle As Integer, ByVal Address As Integer, ByRef Value As Single, Optional ByVal Size As Integer = 2, Optional ByRef Bytes As Integer = 0) As Single
    Private Declare Function WriteMemoryDouble Lib "kernel32" Alias "WriteProcessMemory" (ByVal Handle As Integer, ByVal Address As Integer, ByRef Value As Double, Optional ByVal Size As Integer = 2, Optional ByRef Bytes As Integer = 0) As Double

    Public Function ReadMemory(Of T)(ByVal address As Integer) As T
        Return ReadMemory(Of T)(address, 0, False)
    End Function

    Public Function ReadMemory(ByVal address As Integer, ByVal length As Integer) As Byte()
        Return ReadMemory(Of Byte())(address, length, False)
    End Function

    Private Function ProcessIDExists(ByVal pID As Integer) As Boolean
        For Each p As Process In Process.GetProcessesByName(TargetProcess)
            If p.Id = pID Then Return True
        Next
        Return False
    End Function

    Public Function ReadInteger(ByVal TargetIdd As Integer, ByVal Address As Integer) As Integer
        Dim Value As Integer
        Dim Handle As Integer = CInt(Process.GetProcessById(TargetIdd).Handle)
        If Handle <> 0 Then
            ReadMemoryInteger(Handle, Address, Value)
        End If
        Return Value
    End Function

    Public Function UpdateProcessHandle() As Boolean
        If LastKnownPID = -1 OrElse Not ProcessIDExists(LastKnownPID) Then
            If ProcessHandle <> IntPtr.Zero Then CloseHandle(ProcessHandle)
            Dim p() As Process = Process.GetProcessesByName(TargetProcess)
            If p.Length = 0 Then Return False
            LastKnownPID = CInt(Form1.ComboBox1.Text)
            ProcessHandle = OpenProcess(PROCESS_VM_READ Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, False, CInt(Form1.ComboBox1.Text))
            If ProcessHandle = IntPtr.Zero Then Return False
        End If
        Return True
    End Function

    Public Function ReadMemory(Of T)(ByVal address As Integer, ByVal length As Integer, ByVal unicodeString As Boolean) As T
        Dim buffer() As Byte
        If GetType(T) Is GetType(String) Then
            If unicodeString Then buffer = New Byte(length * 2 - 1) {} Else buffer = New Byte(length - 1) {}
        ElseIf GetType(T) Is GetType(Byte()) Then
            buffer = New Byte(length - 1) {}
        Else
            buffer = New Byte(Marshal.SizeOf(GetType(T)) - 1) {}
        End If
        If Not UpdateProcessHandle() Then Return Nothing
        Dim success As Boolean = ReadProcessMemory(ProcessHandle, New IntPtr(address), buffer, New IntPtr(buffer.Length), IntPtr.Zero)
        If Not success Then Return Nothing
        If GetType(T) Is GetType(Byte()) Then Return CType(CType(buffer, Object), T)
        If GetType(T) Is GetType(String) Then
            If unicodeString Then Return CType(CType(Encoding.Unicode.GetString(buffer), Object), T)
            Return CType(CType(Encoding.ASCII.GetString(buffer), Object), T)
        End If
        Dim gcHandle As GCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned)
        Dim returnObject As T
        returnObject = CType(Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject, GetType(T)), T)
        gcHandle.Free()
        Return returnObject
    End Function

    Private Function GetObjectBytes(ByVal value As Object) As Byte()
        If value.GetType() Is GetType(Byte()) Then Return CType(value, Byte())
        Dim buffer(Marshal.SizeOf(value) - 1) As Byte
        Dim ptr As IntPtr = Marshal.AllocHGlobal(buffer.Length)
        Marshal.StructureToPtr(value, ptr, True)
        Marshal.Copy(ptr, buffer, 0, buffer.Length)
        Marshal.FreeHGlobal(ptr)
        Return buffer
    End Function

    Public Function WriteMemory(ByVal address As Integer, ByVal value As Object) As Boolean
        Return WriteMemory(address, value, False)
    End Function

    Public Function WriteMemory(ByVal address As Integer, ByVal value As Object, ByVal unicode As Boolean) As Boolean
        If Not UpdateProcessHandle() Then Return False
        Dim buffer() As Byte
        If TypeOf value Is String Then
            If unicode Then buffer = Encoding.Unicode.GetBytes(value.ToString()) Else buffer = Encoding.ASCII.GetBytes(value.ToString())
        Else
            buffer = GetObjectBytes(value)
        End If
        Dim result As Boolean = WriteProcessMemory(ProcessHandle, New IntPtr(address), buffer, New IntPtr(buffer.Length), IntPtr.Zero)
        Return result
    End Function
End Module


Using

        If Not ComboBox1.Text = "Lista de Clientes" Then
            If UpdateProcessHandle() Then
                Button1.Text = "Selecionado!"
                ComboBox1.Enabled = False
                ProcID = ComboBox1.Text
                'Here when it will read, show error that the address is not integer
                '&H19A07B80080
                Dim myhp() As Byte = ReadMemory(CType(ReadInteger(ProcID, &H19A07B80080), String), 8)
                Label16.Text = BitConverter.ToDouble(myhp, 0)
            End If
        End If
Developer technologies | VB

3 answers

Sort by: Most helpful
  1. RLWA32 52,546 Reputation points
    2024-01-25T09:18:46.73+00:00

    If you are trying to read/write the memory of a 64-bit process from a 32-bit process then your code will need to use two undocumented functions from the 32-bit version of ntdll.dll. They are NtWow64ReadVirtualMemory64 and NtWow64WriteVirtualMemory64.

    0 comments No comments

  2. Jean Carlo 0 Reputation points
    2024-01-23T11:09:21.1466667+00:00

    yes, with integer get overflow, long gets null, i think maybe something in buffers


  3. Jiachen Li-MSFT 34,241 Reputation points Microsoft External Staff
    2024-01-23T03:31:20.75+00:00

    Hi @Jean Carlo ,

    Have you already tried changing the type of "Address" in the ReadMemory, ReadInteger, and WriteMemory functions to Long.

    And when using, use Dim myhp() As Byte = ReadMemory(CLng(ReadInteger(ProcID, &H19A07B80080)), 8) for type conversion.

    Best Regards.

    Jiachen Li


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.