内存如何在Windows中运行?

时间:2013-06-05 10:11:29

标签: c# memory handle readprocessmemory base-address

所以我一直在争论外部进程内存读取问题(阅读我无法访问的进程的内存。)我对几件事情的理解已经改变,但那里是一件我无法理解的事情。

win32api函数ReadProcessMemory()接受几个参数,如下所示:

    public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
        [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

我正在传递这样的论点:

    public byte[] ReadBytes(IntPtr Handle, Int64 Address, uint BytesToRead)
    {
        IntPtr ptrBytesRead;
        byte[] buffer = new byte[BytesToRead];
        ReadProcessMemory(Handle, new IntPtr(Address), buffer, BytesToRead, out ptrBytesRead);
        return buffer;
    }

直到最近,我的理解是这里列出的地址是读取内存唯一真正重要的东西,这就是我在内存中找到正确值的原因。不幸的是,这似乎是tosh的负担,似乎实际上句柄控制着我正在与哪个窗口进行交互。例如:

我正在运行2个版本的Process“Notepad.exe”。

进程的每个实例都有一个整数,第一个包含数字12345,第二个包含54321。

我正在寻找那个整数,让我们说(虽然我没有证实这一点,所以它可能是不真实的)该程序存储空间内的内存地址是0x1000。

如果我跑的例子:

ReadProcessMemory(NP.Handle, NP.MainModule.BaseAddress + 0x1000, buffer, 32, bread);

这将使用该句柄读取进程,该基址添加到该偏移量。但是,此代码将读取完全相同的值:

ReadProcessMemory(NP.Handle, NP2.MainModule.BaseAddress + 0x1000, buffer, 32, bread);

请注意,NP2应该是第二个记事本窗口,NP是第一个。除此之外,这将读取不同的值(尽管我们正在阅读的地址与第一个示例相同):

ReadProcessMemory(NP2.Handle, NP.MainModule.BaseAddress + 0x1000, buffer, 32, bread);

当然这意味着句柄控制着内存的读取位置,而不是地址,实际上地址与我实际尝试的内容完全无关?任何人都可以向我解释为什么会这样吗?

道歉,如果这个问题过于具体,但是这个问题已经让我的大脑长期存在,虽然我每天都和很多程序员交谈,但是他们都没有能够(或者更多的是他们不愿意帮助我。

我完全清楚这只适用于同一个exe的2个运行实例,所以如果你要阅读Firefox和Notepad(我认为)它将无法工作。我只是想知道为什么它是改变的句柄,而不是地址。

由于

1 个答案:

答案 0 :(得分:2)

  

直到最近,我的理解是这里列出的地址是读取内存唯一真正重要的东西,这就是我在内存中找到正确值的原因。不幸的是,这似乎是tosh的负担,似乎实际上句柄控制着我正在与哪个窗口进行交互。

在这一段中,对于你正在做的事情存在多种错误理解,我不知道从哪里开始。

但是这里(假设这是不完整的):

  

阅读我无法访问的流程记忆

你不能。

如果您没有足够的目标进程访问权限,Windows安全性将阻止您获得具有必要权限的该进程的句柄。 (如果情况并非如此,那就没有安全保障。)

但是我们假设读取过程正在使用Debug或等效权限运行,从而提供足够的访问权限(这就是为什么在某种程度上被称为" God Privileges"允许持有者绕过安全性的原因) )。

  

处理控制哪个窗口

你需要一个进程句柄,而不是一个窗口句柄:它们是完全不同的东西。使用OpenProcess从进程ID获取进程句柄,在请求的访问权限中读取内存包括PROCESS_VM_READ

他们需要利用Windows进程的(虚拟)内存布局知识来确定您需要阅读的地址。请记住,ASLR和32对64位进程将改变该内存布局。额外的分配地址空间不太可能是连续的,因此您不能只是按顺序读取内存。

这是一个高级主题。并且最终几乎总有一种更好的方法(正确的API,利用SendMessage来请求控件的内容,......)而不是直接读取进程内存(记住对一个DLL的微小更改 - 例如来自安全补丁 - 会改变现状。

总结:找到另一种更好的方式。

编辑:了解Windows中内存的一些资源:

  1. Mysteries of Memory Management Revealed,with Mark Russinovich (Part 1 of 2)
  2. Mysteries of Memory Management Revealed,with Mark Russinovich (Part 2 of 2)

    两部分谈话(第1部分:虚拟内存,第2部分:物理内容),也将介绍一些内容 非常有用的工具,用于查看内存及其组织方式。

  3. 阅读 Windows Internals ,Mark Russinovich等。 (并非所有都是相关的,但您还需要了解Win32中的安全性。)

  4. 阅读高级Windows ,Jeffrey Richter。我认为这已经绝版(我的第3版涵盖了Win95 / NT4),但它是您阅读过程记忆并解释结果时需要了解的唯一信息。