6

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

我在一个已知地址上具有已知值的进程上对此进行测试。当我查找该特定地址时,我得到了我期望的值。但是,当我扫描(我认为是)进程使用的所有地址空间时,我在任何地方都找不到该值。

我知道数值“4143000”存在于0x0CF8DC380x0CF8DDDC。当我调用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 < (Int64)module.BaseAddress + module.ModuleMemorySize; addr++)
{
    // Compare ints
    if (iVal > 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);
4

1 回答 1

1

The addresses you're getting are pointers to the managed (CLR) heap. They won't generally map to absolute memory addresses and they can move from call to call as the GC decides to run.

If you use "unsafe" code, you can get relative pointers as well as managing your own memory space. It's still on the heap but at least you're guaranteed the GC won't modify your address space.

Do not expect to be able to access things on the heap from non-CLR code without extensive wrapping. There are ways to do IPC between CLR-managed processes but you'd have to write access proxies to the "outside world" if you want a non-CLR process to get to your memory.

于 2011-08-26T14:01:21.607 回答