
与其 Windows 版本 Winpmem 类似,这不是传统的内存转储工具。Linpmem 提供了一个从任意物理地址读取的 API,包括保留内存和内存空洞,但它也可以用于常规内存转储。此外,该驱动提供了多种读取物理内存的访问模式,如字节、字、双字、四字和缓冲区访问模式,其中缓冲区访问模式适用于大多数标准情况。如果读取需要对齐的字节/字/双字/四字读取,Linpmem 将精确执行。
目前,Linpmem 的功能包括:
缓存控制将在未来添加,以支持特定的读取访问模式。
至少目前,你必须自己编译 Linpmem 驱动。一种在其他 Linux 系统上加载预编译 Linpmem 驱动的方法正在开发中,但尚未完成。尽管如此,编译 Linpmem 驱动并不困难,基本上就是执行 'make'。
你需要 make 和一个 C 编译器。(我们推荐 gcc,但 clang 应该也可以工作。)
确保你已经安装了 linux-headers(使用你的目标 Linux 发行版的任何包管理器)。确切的包名可能因你的发行版而异。
一个快速(与发行版无关)检查是否安装了该包的方法:
ls -l /usr/lib/modules/`uname -r`/
就这样,你可以继续进行第二步了。
外部系统: 目前,如果你想为另一个系统编译驱动,例如,因为你想要创建内存转储但无法在目标系统上编译,你必须直接从该系统的 Linux 发行版的包仓库下载头文件包。双重检查包的版本精确匹配外部系统上运行的发行版和内核版本。如果另一个系统使用的是自行编译的内核,你必须获取该内核构建目录的副本。然后,将任一目录的位置放入 KDIR 环境变量中。
export KDIR=path/to/extracted/header/package/or/kernel/root
编译驱动很简单,只需输入:
make
这应该会在当前工作目录中生成 linpmem.ko。
你可能想先检查 precompiler.h,并选择是为发布版还是调试版编译(例如,带有调试打印)。目前没有太多其他预编译器设置。
可以通过 insmod path-to-linpmem.ko 加载 linpmem.ko 模块,通过 rmmod path-to-linpmem.ko 卸载。(这只会在此次运行期间加载驱动。)如果你为调试版编译,也请查看 dmesg。
加载后,为了与驱动通信,你需要创建设备:
mknod /dev/linpmem c 42 0
如果你无法与驱动通信,请检查 dmesg 日志以验证 '42' 确实是注册的主设备号:
[12827.900168] linpmem: registered chrdev with major 42
尽管内核通常会尝试真正分配这个编号。
你可以对该设备使用 chown 将其赋予你的用户,如果你不想一直开着 root 控制台的话。(或者继续在 root 控制台中使用。)
有一个示例代码,演示并详细说明如何与驱动交互。用户空间 API 参考还可以在 ./userspace_interface/linpmem_shared.h 中找到。
如果你想了解如何直接与驱动交互而不使用库,这段代码很重要。它也可以用作简短的功能测试。
Linpmem 有一个(可选的)基本命令行界面工具,即 pmem CLI 工具。可以在这里找到:https://github.com/vobst/linpmem-cli。除了源代码,还有一个预编译的 CLI 工具以及预编译的静态库和头文件,可以在这里找到(已签名)。注意:这是一个初步版本,请务必检查更新,因为很快会有许多添加和改进。
pmem CLI 工具可用于以(相对)安全和方便的方式测试 Linpmem 的各种功能。Linpmem 也可以由该工具加载,而不是使用 insmod/rmmod,未来还会增加一些额外选项。这还有一个好处,即 pmem 会自动为你创建正确的设备供立即使用。它非常便携,可以在任何 Linux 系统上运行(实际上,甚至在 Linux 2.6 上也经过测试)。
$ ./pmem -h
Command-line client for the linpmem driver
Usage: pmem [OPTIONS] [COMMAND]
Commands:
insmod Load the linpmem driver
help Print this message or the help of the given subcommand(s)
Options:
-a, --address <ADDRESS> Address for physical read operations
-v, --virt-address <VIRT_ADDRESS> Translate address in target process' address space (default: current process)
-s, --size <SIZE> Size of buffer read operations
-m, --mode <MODE> Access mode for read operations [possible values: byte, word, dword, qword, buffer]
-p, --pid <PID> Target process for cr3 info and virtual-to-physical translations
--cr3 Query cr3 value of target process (default: current process)
--verbose Display debug output
-h, --help Print help (see more with '--help')
-V, --version Print version
如果你想自己编译 CLI 工具,切换到其目录并按照(CLI)自述文件中的说明进行构建。否则,直接下载预构建的程序,它应该可以在任何 Linux 上工作。使用 CLI 工具加载内核驱动:
# pmem insmod path/to/linpmem.ko
使用 pmem 工具加载驱动的优点是你不必自己创建设备文件,并且它将在(下一个版本中)提供选择谁拥有 linpmem 设备的选项。
pmem 命令行界面只是一个小型 Rust 库的薄包装,该库公开了与驱动交互的 API。更高级的用户也可以使用这个库。从 https://github.com/vobst/linpmem-cli 编译时,该库会与 pmem CLI 工具一起自动编译(作为静态可移植库),但也(预编译)包含在这里(已签名)。注意:这是一个初步版本,更多内容即将推出。
如果你不想使用用户模式库,更愿意自己直接与驱动交互,你可以在 ./userspace_interface/linpmem_shared.h 中找到其用户空间 API/接口和文档。我们还在 demo/test.c 中提供了示例代码,说明如何直接使用驱动。
LinPyMem:linpmem 驱动的 Python 包装器。可在 PyPI 上获取。
尚未实现。
如果系统在加载模块时报告以下错误信息,可能是因为安全启动:
$ sudo insmod linpmem.ko
insmod: ERROR: could not insert module linpmem.ko: Operation not permitted
仍有不同的方法来加载模块。最明显的一种是在 UEFI 设置中禁用安全启动。
如果你的发行版支持,一个更优雅的解决方案是在使用前对模块进行签名。这可以通过以下步骤完成(在 Ubuntu 20.04 上测试)。
$ sudo apt install mokutil
$ openssl req -new -newkey rsa:4096 -keyout mok-signing.key -out mok-signing.crt -outform DER -days 365 -nodes -subj "/CN=Some descriptive name/"
$ sudo mokutil --import mok-signing.crt
$ /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 path/to/mok-singing/MOK.key path/to//MOK.cert path/to/linpmem.ko
之后,你应该能够加载模块。
注意,从取证准备的角度来看,你应该在需要之前准备好签名的模块,因为上述过程会导致系统重启两次,从而破坏内存中的大部分易失数据。
(如果遇到任何问题,请报告潜在问题。)
Linpmem 和 Winpmem 的存在离不开我们前辈在(现已退休的)REKALL 项目中的工作:https://github.com/google/rekall。
我们的开源贡献者: