如何获取进程使用的所有内存地址空间?

我需要知道进程使用的所有内存地址空间。 稍后将扫描存储空间以定位过程中的值并识别它们的位置/地址。 我目前的过程是通过其(基址+内存大小)获取每个模块的基址。

我正在一个已知地址已知值的进程上测试它。 当我查找该特定地址时,我得到了我期望的值。 但是,当我扫描(我相信是)进程使用的所有地址空间时,我无法在任何地方找到该值。

我知道在0x0CF8DC380x0CF8DDDC处存在数值“4143000”。 当我调用ReadMemoryBytes(module,module.BaseAddress,4,(IntPtr)(0x0CF8DC38))时,我返回字节( 152,55,63,0 )。 当我调用BitConverter.GetBytes(4143000)时,我得到了相同的字节集。 当我在该进程上使用不同的内存扫描程序时,我会在这些地址处找到该值。

但是,当我扫描“已知地址”时,我在任何地方都找不到这个值。 看起来我的代码甚至找不到进程使用的那些地址。

因此,我的问题是双重的:

  • 如何在此过程中找到这些地址?
  • 我担心我可能正在处理系统内存中的绝对地址与进程中的相对地址。 我这样做了吗?

// (in the calling method) foreach (ProcessModule module in process.Modules) { ParameterizedThreadStart pst = new ParameterizedThreadStart(p => SearchModule(module, value)); Thread t = new Thread(pst); t.Start(); } private unsafe void SearchModule(ProcessModule module, string value) { Process process = getProcess; int iVal; double dVal; int.TryParse(value, out iVal); double.TryParse(value, out dVal); for (Int64 addr = (Int64)module.BaseAddress; addr + value.Length  0) { byte[] ExpectedBytes = BitConverter.GetBytes(iVal); byte[] ActualBytes = ReadMemoryBytes(module, (IntPtr)addr, (uint)ExpectedBytes.Length, (IntPtr)addr); bool isMatch = true; for (int i = 0; i < ExpectedBytes.Length; i++) if (ExpectedBytes[i] != ActualBytes[i]) isMatch = false; if (isMatch) PossibleAddresses.Add((IntPtr)addr); } } private byte[] ReadMemoryBytes(ProcessModule mod, IntPtr memAddress, uint size, IntPtr BaseAddress) { byte[] buffer = new byte[size]; IntPtr bytesRead; unsafe { ReadProcessMemory(processPointer, BaseAddress, buffer, size, out bytesRead); return buffer; } } [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId); [DllImport("kernel32.dll")] public static extern Int32 CloseHandle(IntPtr hObject); [DllImport("kernel32.dll")] public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead); 

您获得的地址是托管(CLR)堆的指针。 它们通常不会映射到绝对内存地址,并且它们可以在GC决定运行时从一个调用移动到另一个调用。

如果使用“不安全”代码,您可以获得相对指针以及管理自己的内存空间。 它仍然在堆上,但至少你保证GC不会修改你的地址空间。

不要期望能够在没有大量包装的情况下从非CLR代码访问堆上的东西。 有一些方法可以在CLR管理的进程之间进行IPC,但如果您希望非CLR进程到达您的内存,则必须将访问代理写入“外部世界”。