ReadProcessMemory 查找字符串

ReadProcessMemory to find Strings

我有一个程序旨在从进程中扫描字符串。它旨在输出进程内的所有可读字符串,至少 4 个字节长。 (我实际上是在扫描 Minecraft 的 java 进程)。出于某种原因,默认游戏有时会完成扫描,一旦我让它坐了一会儿。一旦添加了最小的 mod,扫描就会挂起。有什么办法可以解决这个问题吗?

以下是我用于扫描的方法。

    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

已解决!我发现问题是由我的编译器在需要设置为 x64 时设置为 x86 引起的。不再挂起!