Search code examples
vb.netprocessreadprocessmemory

ReadProcessMemory to find Strings


I have a program designed to scan strings from a process. It is designed to output all of the readable strings within the process, at least 4 bytes long. (I am actually scanning Minecraft's java process). For some reason, the default game will SOMETIMES complete its scan, once I let it sit a while. Once you add even the smallest mod, the scan will hang. Is there any way I can fix this?

Here are the methods I am using for the scan.

    Private Function FindStrings(input() As Byte, minLength As Integer) As List(Of String)

            Dim arr() As String = System.Text.Encoding.Default.GetString(input).Split({Chr(0) & Chr(0) & Chr(0)}, StringSplitOptions.RemoveEmptyEntries)
                Dim output As New List(Of String)
                Dim tmp As String = ""
                Dim tmp1 As String = ""

            For Each item As String In arr
                    tmp = item.Replace(Chr(0), "")

                    For Each c As Char In tmp.ToCharArray

                        If isReadable(Asc(c)) = True Then
                            tmp1 &= c
                        Else
                            If tmp1.Length >= minLength Then output.Add(tmp1)
                            tmp1 = ""
                        End If

                    Next

                    If tmp1.Length >= minLength Then output.Add(tmp1)
                    tmp1 = ""

                Next


                Return output
        End Function

    Private Function isReadable(input As Integer) As Boolean
            Dim whitelist() As String = {"196,214,220,223,228,246,252"}

            If Array.IndexOf(whitelist, input) > -1 Then Return True

            If input < 32 Then Return False
            If input > 126 Then Return False

            Return True
        End Function

Private Sub BGW_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BGW.DoWork

        Dim hProcess As IntPtr
        Dim lpMem As UInt32, ret As UInt32, lLenMBI As UInt32
        Dim si As SYSTEM_INFO
        Dim mbi As MEMORY_BASIC_INFORMATION
        Dim Prozess As Process = Process.GetProcessById(D.ID)

        'Open process with required access
        hProcess = OpenProcess(PROCESS_READ_WRITE_QUERY, False, Prozess.Id)

        If hProcess = 0 Then
            MsgBox("Can't open process!")
            Exit Sub
        End If


        'Determine applications memory addresses range
        'Call GetNativeSystemInfo(si)
        Call GetSystemInfo(si)
        lpMem = 0 'si.lpMinimumApplicationAddress
        lLenMBI = Marshal.SizeOf(mbi)

        'Try
        'Scan memory
        Do While lpMem < si.lpMaximumApplicationAddress

            BGW.ReportProgress(1)
            If BGW.CancellationPending = True Then Exit Sub

            ret = VirtualQueryEx(hProcess, lpMem, mbi, lLenMBI)

            If ret = lLenMBI Then

                If mbi.lType = &H20000 AndAlso mbi.State = &H1000 AndAlso mbi.RegionSize > 0 Then

                    Dim sBuffer As Byte() = New Byte(mbi.RegionSize - 1) {}
                    ReadProcessMemory(hProcess, mbi.BaseAddress, sBuffer, mbi.RegionSize, 0)

                    strings.AddRange(FindStrings(sBuffer, 4))
                End If

            Else
                Exit Do
            End If

            'Increase base address for next searching cicle. Last address may overhead max Long value (Windows use 2GB memory, which is near max long value), so add Error checking
            lpMem = mbi.BaseAddress + mbi.RegionSize

        Loop

        'Catch ex As Exception
        'System.Console.WriteLine("ERROR: " + ex.Message)
        'End Try

        CloseHandle(hProcess)

        BGW.ReportProgress(2, strings)

        '7ffe1000
    End Sub

    Private Sub BGW_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BGW.RunWorkerCompleted

        lblStatus.Text = "Complete"
        Progress.Value = D.Pages
        System.Threading.Thread.Sleep(150)
        Dim thread As New Thread(
  Sub()
      strings = strings.Distinct.ToList
      lblStatus.Text = "Collecting Results..."

      For Each item As String In strings
          System.Console.WriteLine(item)
          Exit For
      Next

      System.Console.WriteLine("DONE")
      strings = Nothing

      System.GC.Collect()
      System.GC.WaitForPendingFinalizers()

      Application.Exit()
  End Sub)
        thread.Start()

    End Sub

    Public Sub EnumeratePages()
        Dim hProcess As IntPtr
        Dim lpMem As UInt32, ret As UInt32, lLenMBI As UInt32
        Dim si As SYSTEM_INFO
        Dim mbi As MEMORY_BASIC_INFORMATION
        Dim MBIitems() As String


        Dim Prozess As Process = Process.GetProcessById(D.ID)
        LV.Items.Clear()
        LV.BeginUpdate()
        'Open process with required access
        hProcess = OpenProcess(PROCESS_READ_WRITE_QUERY, False, Prozess.Id)

        If hProcess = 0 Then
            MsgBox("Can't open process!")
            Exit Sub
        End If

        'Determine applications memory addresses range
        'Call GetNativeSystemInfo(si)
        Call GetSystemInfo(si)
        lpMem = 0 'si.lpMinimumApplicationAddress
        lLenMBI = Marshal.SizeOf(mbi)


        'Label1.Text = "MinimumApplicationAddress: " & MakeNiceSize(si.lpMinimumApplicationAddress) & vbNewLine & _
        '                        "MaximumApplicationAddress: " & MakeNiceSize(si.lpMaximumApplicationAddress) & " / " & MakeNiceSize(UInteger.MaxValue)

        Try

            'Scan memory
            Do While lpMem < si.lpMaximumApplicationAddress

                ret = VirtualQueryEx(hProcess, lpMem, mbi, lLenMBI)

                If ret = lLenMBI Then

                    With mbi
                        MBIitems = New String() { .AllocationBase.ToString("X").ToLower, Protection2String(.AllocationProtect), MakeNiceSize(.RegionSize), State2String(.State), Protection2String(.Protect), Type2String(.lType)}
                        LV.Items.Add(.BaseAddress.ToString("X").ToLower).SubItems.AddRange(MBIitems)
                    End With

                Else
                    Exit Do
                End If

                'Increase base address for next searching cicle. Last address may overhead max Long value (Windows use 2GB memory, which is near max long value), so add Error checking
                lpMem = mbi.BaseAddress + mbi.RegionSize

            Loop

        Catch ex As Exception
            System.Console.WriteLine(ex.Message)

        End Try
        CloseHandle(hProcess)


        LV.EndUpdate()

        D.Pages = LV.Items.Count - 1
        Progress.Value = 0
        Progress.Maximum = D.Pages

        BGW.RunWorkerAsync()
        System.Console.WriteLine("Done enumerating!")
        Me.Text = D.Name & ".exe - " & D.ID
        '7ffe1000
    End Sub

Solution

  • Solved! I have discovered the issue was caused by my compiler being set to x86 when it needed to be set to x64. No longer hangs!