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 引起的。不再挂起!
我有一个程序旨在从进程中扫描字符串。它旨在输出进程内的所有可读字符串,至少 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 引起的。不再挂起!