Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Instead of dumping memory to disk and reading every iteration, scan the target process' memory in chunks, and then marshal the data to leverage the efficiency of pointer arithmetic.</p> <pre><code>using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; namespace MemoryScan { internal class Program { [DllImport("kernel32.dll", SetLastError = true)] private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead); private static unsafe void Main(string[] args) { Process process = Process.GetProcessesByName("notepad")[0]; //example target process int search = 100; //search value int segment = 0x10000; //avoid the large object heap (&gt; 84k) int range = 0x7FFFFFFF - segment; ; //32-bit example int bytesRead; List&lt;int&gt; addresses = new List&lt;int&gt;(); DateTime start = DateTime.Now; for (int i = 0; i &lt; range; i += segment) { byte[] buffer = new byte[segment]; if (!ReadProcessMemory(process.Handle, new IntPtr(i), buffer, segment, out bytesRead)) { continue; } IntPtr data = Marshal.AllocHGlobal(bytesRead); Marshal.Copy(buffer, 0, data, bytesRead); for (int j = 0; j &lt; bytesRead; j++) { int current = *(int*)(data + j); if (current == search) { addresses.Add(i + j); } } Marshal.FreeHGlobal(data); } Console.WriteLine("Duration: {0} seconds", (DateTime.Now - start).TotalSeconds); Console.WriteLine("Found: {0}", addresses.Count); Console.ReadLine(); } } } </code></pre> <p>Test Results </p> <p>Duration: 1.142 seconds<br> Found: 3204</p> <p>Create a generic class to make type marshaling easier, like so:</p> <pre><code>public static class MarshalHelper { public unsafe static T Read&lt;T&gt;(IntPtr address) { object value; switch (Type.GetTypeCode(typeof(T))) { case TypeCode.Int16: value = *(short*)address; break; case TypeCode.Int32: value = *(int*)address; break; case TypeCode.Int64: value = *(long*)address; break; default: throw new ArgumentOutOfRangeException(); } return (T)value; } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload