title: ReadProcessMemory to find Strings
body: <p>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?</p>
  
  <p>Here are the methods I am using for the scan.</p>
  
  <pre><code>    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) &amp; Chr(0) &amp; 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 &amp;= c
                          Else
                              If tmp1.Length &gt;= minLength Then output.Add(tmp1)
                              tmp1 = ""
                          End If
  
                      Next
  
                      If tmp1.Length &gt;= 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) &gt; -1 Then Return True
  
              If input &lt; 32 Then Return False
              If input &gt; 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 &lt; 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 = &amp;H20000 AndAlso mbi.State = &amp;H1000 AndAlso mbi.RegionSize &gt; 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: " &amp; MakeNiceSize(si.lpMinimumApplicationAddress) &amp; vbNewLine &amp; _
          '                        "MaximumApplicationAddress: " &amp; MakeNiceSize(si.lpMaximumApplicationAddress) &amp; " / " &amp; MakeNiceSize(UInteger.MaxValue)
  
          Try
  
              'Scan memory
              Do While lpMem &lt; 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 &amp; ".exe - " &amp; D.ID
          '7ffe1000
      End Sub
  </code></pre>