内存是如何在Windows中工作的

本文关键字:工作 Windows 内存 | 更新日期: 2023-09-27 18:16:55

所以我一直在与外部进程内存读取(读取进程I 无法访问的内存)的问题作斗争。我对许多事情的理解都变了,但有一件事我就是想不明白。

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;
    }

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

我正在运行两个版本的进程"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);

这当然意味着句柄是控制内存读取的位置,而不是地址,实际上地址与我实际尝试做的事情完全无关?有人能给我解释一下为什么会这样吗?

如果这个问题过于具体,我很抱歉,但是这个问题已经困扰我很久了,尽管我每天都和许多程序员交谈,但没有一个人能够(或者更多的是他们不愿意)帮助我。

我完全意识到这将只适用于2运行相同的exe实例,所以它不会工作,如果你要阅读火狐和记事本(我认为)。我只是想知道为什么是句柄做了这个改变,而不是地址。

谢谢

内存是如何在Windows中工作的

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

在这一段中有很多关于你正在做的事情的误解,我真的不知道从哪里开始。

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

读取没有访问权限的进程的内存

你不能。

如果你对目标进程没有足够的访问权限,Windows安全性将阻止你获得具有必要权限的进程句柄。(如果不是这样,就没有安全性。)

然而,我们假设读取进程以Debug或同等权限运行,具有足够的访问权限(这就是为什么,在某种程度上,这被称为"上帝特权",允许持有者绕过安全)。

处理哪些窗口

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

你需要利用Windows进程的(虚拟)内存布局的知识来计算你需要读取的地址。记住,ASLR和32位与64位进程将改变内存布局。另外,分配的地址空间不太可能是连续的,所以不能顺序地读取内存。

这是一个高级主题。最后,几乎总是有一个更好的方法(适当的api,利用SendMessage请求控件的内容,…),而不是直接读取进程内存(记住一个dll的微小变化)。从安全补丁(将改变周围的东西)。

总结:寻找另一个更好的方法。

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

  1. 内存管理的奥秘揭示,与Mark Russinovich (1/2)
  2. 揭示内存管理的奥秘,与Mark Russinovich (2/2)

    两部分的演讲(第1部分:虚拟内存,第2部分:物理内存)也将介绍一些
  3. 阅读Windows内部, Mark Russinovich等人(不是所有都相关,但您也需要了解Win32中的安全性)。

  4. Read Advanced Windows, Jeffrey Richter。我想这已经绝版了(我的第3版涵盖了Win95/NT4),但这是你需要知道的读取进程内存和解释结果的信息的唯一严肃的覆盖。