Search code examples
vb.netreadprocessmemory

VB.NET ReadProcessMemory string


So i have the following code

Imports System.Diagnostics
Imports System.IO
Imports System.Runtime.InteropServices    
Public Class Form1    
    <StructLayout(LayoutKind.Sequential)> _
    Structure OSVERSIONINFO
        Dim dwOSVersionInfoSize As Integer
        Dim dwMajorVersion As Integer
        Dim dwMinorVersion As Integer
        Dim dwBuildNumber As Integer
        Dim dwPlatformId As Integer
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128), VBFixedString(128)> Dim szCSDVersion As String
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
    Structure MEMORY_BASIC_INFORMATION
        Dim BaseAddress As Integer
        Dim AllocationBase As Integer
        Dim AllocationProtect As Integer
        Dim RegionSize As Integer
        Dim State As Integer
        Dim Protect As Integer
        Dim lType As Integer
    End Structure    
    <StructLayout(LayoutKind.Sequential)> _
    Structure SYSTEM_INFO ' 36 Bytes
        Dim dwOemID As Integer
        Dim dwPageSize As Integer
        Dim lpMinimumApplicationAddress As Integer
        Dim lpMaximumApplicationAddress As Integer
        Dim dwActiveProcessorMask As Integer
        Dim dwNumberOrfProcessors As Integer
        Dim dwProcessorType As Integer
        Dim dwAllocationGranularity As Integer
        Dim wProcessorLevel As Short
        Dim wProcessorRevision As Short
    End Structure
    Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (ByRef LpVersionInformation As OSVERSIONINFO) As Integer
    Private Declare Function VirtualQueryEx Lib "kernel32.dll" (ByVal hProcess As IntPtr, ByVal lpAddress As UInteger, ByRef lpBuffer As MEMORY_BASIC_INFORMATION, ByVal dwLength As Integer) As Integer
    Private Declare Sub GetSystemInfo Lib "kernel32" (ByRef lpSystemInfo As SYSTEM_INFO)
    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal blnheritHandle As Integer, ByVal dwAppProcessId As Integer) As Integer
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByRef lpBaseAddress As Integer, ByRef lpBuffer As Long, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
    Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByRef lpBaseAddress As Integer, ByRef lpBuffer As String, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
    Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Integer, ByRef lpdwProcessId As Integer) As Integer
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Integer, ByVal lpWindowName As Integer) As Integer
    Private Declare Function GetParent Lib "user32" (ByVal hWnd As Integer) As Integer
    Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Integer, ByVal wCmd As Integer) As Integer
    Private Const PROCESS_VM_READ = (&H10)
    Private Const PROCESS_VM_OPERATION = (&H8)
    Private Const PROCESS_QUERY_INFORMATION = (&H400)
    Public Const PROCESS_READ_WRITE_QUERY = PROCESS_VM_READ + PROCESS_VM_OPERATION + PROCESS_QUERY_INFORMATION
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click    
        Dim pid As Integer, hProcess As Integer
        Dim lpMem As Integer, ret As DialogResult, lLenMBI As Integer
        Dim lWritten As Integer
        Dim sBuffer As String
        Dim sSearchString As String = "", sReplaceString As String = ""
        Dim si As SYSTEM_INFO
        Dim mbi As MEMORY_BASIC_INFORMATION
        For Each p As Process In Process.GetProcesses
            If p.ProcessName = "notepad" Then
                pid = p.Id
            End If
        Next
        hProcess = OpenProcess(PROCESS_READ_WRITE_QUERY, False, pid)
        lLenMBI = Len(mbi)
        'Determine applications memory addresses range
        GetSystemInfo(si)
        lpMem = si.lpMinimumApplicationAddress
         Do While lpMem < si.lpMaximumApplicationAddress
            mbi.RegionSize = 0
            ret = VirtualQueryEx(hProcess, lpMem, mbi, lLenMBI)
            If ret = lLenMBI Then
                If ((mbi.lType = &H20000) And (mbi.State = &H1000)) Then
                    If mbi.RegionSize > 0 Then
                        Dim stringinmemory As Long
                        sBuffer = mbi.RegionSize
                        ReadProcessMemory(hProcess, mbi.BaseAddress, stringinmemory, mbi.RegionSize, lWritten)
                        Debug.WriteLine(sBuffer)
                    End If
                End If
                lpMem = mbi.BaseAddress + mbi.RegionSize
            Else
                Exit Do
            End If
        Loop
        CloseHandle(hProcess)
    End Sub
End Class

And it should read all notepad memory (step by step like). I get no errors when i run it , but it returns


    4096
    4096
    4096
    8192
    90112
    4096
    344064
    131072
    8192
    45056
    172032
    4096
    155648
    4096

This code works well in VB6, but i converted it to VB.NET. What am I doing wrong ? Can you help me please ? Thanks in advance. Nicu


Solution

  • You are printing the value of sBuffer which is an integer which explains the results you are seeing. Besides, sBuffer does not contain the data which is read from memory. I think your lpBuffer parameter (and also stringinmemory as well) should not be a Long but instead be an Byte array. Something like this:

    Const PROCESS_WM_READ As Integer = &H10
    
    <DllImport("kernel32.dll")> _
    Public Shared Function OpenProcess(dwDesiredAccess As Integer, bInheritHandle As Boolean, dwProcessId As Integer) As IntPtr
    End Function
    
    <DllImport("kernel32.dll")> _
    Public Shared Function ReadProcessMemory(hProcess As Integer, lpBaseAddress As Integer, lpBuffer As Byte(), dwSize As Integer, ByRef lpNumberOfBytesRead As Integer) As Boolean
    End Function
    
    Public Shared Sub Main()
        Dim notepadProcess As Process = Process.GetProcessesByName("notepad")(0)
        Dim processHandle As IntPtr = OpenProcess(PROCESS_WM_READ, False, notepadProcess.Id)
    
        Dim bytesRead As Integer = 0
        Dim buffer As Byte() = New Byte(23) {}
    
        'The address in this line is hard-coded.  Use whatever is appropriate for your situation.
        ReadProcessMemory(CInt(processHandle), &H36B9D0, buffer, buffer.Length, bytesRead)
    
        Console.WriteLine(Encoding.Unicode.GetString(buffer))
        Console.ReadLine()
    End Sub