我正在尝试确定如何读取物理内存。我知道当操作系统处于保护模式时,进程只能访问分配给它的虚拟内存,而不会导致分段错误。是否可以使用在实模式下运行的汇编语言读取物理内存?我假设使用汇编语言将是最有效的方法,而不是使用 C 等高级语言。我的目标是创建一个程序,该程序可以扫描物理内存以用于内存取证应用程序。我正在使用 MASM 运行 Windows 操作系统。
读取物理内存
我知道当操作系统处于保护模式时,进程只能访问分配给它的虚拟内存,而不会导致分段错误。
正确的。按照设计,所有进程都被限制在自己的地址空间内,不能访问(没有操作系统帮助)其他正在运行的进程的地址空间。内核负责每个运行进程的VM管理,基本上借助CR3寄存器,CR3寄存器是每个进程的虚拟地址表的根指针。CR3 由内核在每个新的调度进程执行时更新。CR3 指针表中的所有地址都是物理地址,对应的虚拟地址映射。(稍后会详细介绍)
是否可以使用在实模式下运行的汇编语言读取物理内存?我假设使用汇编语言将是最有效的方法,而不是使用 C 等高级语言。
为什么你认为它会更有效?在实模式下进行物理内存检查可能是一项非常具有挑战性的任务,并且需要重新启动机器,这对于任何面向取证的内存获取都是不可取的。
我的目标是创建一个程序,该程序可以扫描物理内存以用于内存取证应用程序。
这个目标可以在特定内核驱动程序的帮助下从内核空间实现。这样的内核驱动程序需要为每个正在运行的进程和内核本身解析一个虚拟地址表。有几种方法可以做到:
- 每个进程的增值税的主要指针存储在CR3寄存器或Windows的情况下也可以在每一个
KPROCESS struct @ DirectoryTableBase多就可以了这里。一旦你有了这个指针,你就可以手动解析表并获得 PHY 到 VIRT 的映射。有了这些信息,使用内存管理器例程,您可以获得大多数内存页面的内容。这是最困难但更合适的方法。 - 另一种方法是 with
MmGetPhysicalMemoryRanges,但它可能会错过一些范围
我还建议您查看Rekall工具,其中 IMO 被描述为一种更清洁的取证内存获取方式,您可以相对轻松和全面地进行。如果您想更深入地了解该主题,请阅读那里引用的一些技术论文。
一般来说,法医记忆成像是一个非常广泛的主题,有更多的方法可以做到这一点,然后我在这里描述。
您编写的语言在这里没有任何区别,对内存访问的限制来自 CPU 而不是您使用的语言。此外,您realmode切换到保护模式后将无法进入。这也是 CPU 限制。
但在此之前,有一个小的修正:
进程只能访问分配给它的虚拟内存,而不会导致分段错误。
并不是一个进程不能访问另一个进程的内存,它只是不能寻址、描述或引用它,因为保护模式下的每个进程都有自己的地址空间。因此地址可能是有效的,所以如果您想访问0x401000另一个进程中的地址并只是执行,mov eax, DWORD PTR [0x401000]您可能会得到一个值(而不是段错误),它不会是另一个进程中的值。
现在,从用户模式进程的角度来看,访问另一个进程的内存是不可能的。只有内核可以访问不同进程的内存(甚至这是一个复杂的操作)。由于有时需要读取其他进程的内存,windows 提供了两个方便的 API,称为ReadProcessMemory和WriteProcessMemory。您还可以使用VirtualAllocEx在远程进程中分配内存。
我这里有一些很旧的代码,它读取 Windows 下的物理内存:http : //nah6.com/~itsme/cvs-xdadevtools/itsutils/src/sysint-physmem.cpp
在类 Unix 系统中,您将通过读取/dev/mem来访问物理内存。但是,大多数现代变体 - linux、android、macos - 默认情况下禁用此功能。