内存采集方法

内存只有一次采集机会,而"能不能采到"这件事在不同平台上的答案完全相反。

最后更新 2026-10-09版本 v1.0维护 DigiForensics查看历史 0

关键词:WinPmem、DumpIt、LiME、AVML、osxpmem、SELinux、内核模块、采集验证 难度:进阶 前置知识:Linux 内核模块基础、Android root 与 SELinux、Windows 驱动加载、哈希与证据保全

一、概述

内存只有一次采集机会,而"能不能采到"这件事在不同平台上的答案完全相反。

Windows 加载一个签名驱动就能拿到全量物理内存。Linux 静态二进制扔过去就能跑。Android 需要 root 加上放行 SELinux。

现代 macOS 则在默认状态下技术上已近乎不可行。

如果你把这四者当成同一件事处理,结果通常是:在 Windows 上采到了但把 minidump 当物理镜像解析,在 Linux 上采到了但被地址空洞坑了结构偏移,在 Android 上耗掉两小时试 dd if=/dev/mem,在 macOS 上把整晚时间花在 kext 签名研究上。最后交出一份没有内存证据的报告。

要解决的就是:在动手之前先判断这条平台该走哪条路,以及每条路的失败方式长什么样。

这一步落在采集环节的执行,紧接在内存取证总览的现场判断之后、Volatility 分析之前。上游是"目标机还开着吗、有没有存储、能不能授权",下游是"镜像能不能被读进去"。一个必须先分清的边界在二、核心原理开头:这里只管"把内存搬出来",搬出来之后能不能读是 Profile 与框架的问题。

硬件采集(PCIe FPGA)是这条执行路径的替代方案,不属于它的组成部分。

四个平台的读取通道、产物与硬约束各不相同:

平台 读取通道 产物 关键约束
Windows 释放签名驱动 → SCM/NtLoadDriver 加载 → 读物理地址空间 DigiForensics-mem.raw、DigiForensics-mem.aff4、lsass.dmp raw 与 minidump 是两种地址空间语义
Linux AVML 读 /dev/crash;LiME 加载 lime.ko format=lime / raw / padded、Snappy 压缩包 lockdown 非 none 时 AVML 静默失败
macOS osxpmem 依赖 kext hiberfil 类休眠镜像 SIP + kext 签名使在线采集不可行
Android adb + root + SELinux 放行 /sdcard/DigiForensics-mem.raw /dev/mem 自 5.x 起默认不可用

产物这一列不是细节。format=lime 与 format=raw 的差别决定了后续结构偏移是否可信。 .aff4 与 .raw 的差别决定了证据完整性论证的便利度。

据此能回答的是这些:这台机器在采集区间内有哪些进程在跑、有哪些网络连接还挂着、内存里有没有可执行私有页、已解密的会话密钥是否驻留。更重要的是,能回答"哪些信息在采集后彻底消失"——这决定了后续分析必须在镜像里找什么。

回答不了的是这些:用户在采集区间内具体看到什么、精确到秒的行为顺序、以及采集前已经发生的行为。另外,采集成功判据本身也回答不了"镜像为什么没有某样东西"——那需要回到内容级验证,而不是这里的判据。

动手之前,先确认你已经掌握:目标平台的基本提权路径(Windows 驱动加载、Linux 内核模块、Android root 与 su)、命令行参数转义的基本规则(insmod 的引号问题就出在这里)、以及哈希与保管链的记录方式。内核模块与 root 提权这两块不熟,先看Linux Shell 痕迹与命令历史;对镜像格式(raw / AFF4 / E01)的区别还不确定,先看证据格式与转换。采完之后不知道怎么把镜像接进分析环境,回只读挂载与安全接入。

二、核心原理

2.1 读物理内存的三条路

所有采集工具本质上只有三种实现路径:

路径 机制 代表工具 干扰程度
驱动 / 内核模块 在内核态打开设备对象,直接读物理地址空间 WinPmem、DumpIt、FTK Imager、LiME 低
特殊设备节点 读内核暴露的字符设备 AVML(/dev/crash) 低
内存总线 / 硬件 绕过 CPU,直接经 PCIe 读内存控制器 PCIe FPGA 采集卡 极低(几乎不影响系统)

硬件采集为什么最"干净":软件采集无论怎么做,都要占用目标机的内存(镜像缓冲区)、要加载代码、要把页 pin 住。

而 FPGA 采集卡是用独立硬件通过 DMA 读内存,目标机 CPU 完全不知道自己被读了,连镜像缓冲区都不需要。

代价是需要专用硬件、且只支持 x86/x64 台式与服务器。

2.2 Windows 侧:驱动加载是必经之路

Windows 没有暴露"读物理内存"的普通用户态接口。WinPmem、DumpIt、FTK Imager 的工作方式都一样:

1. 把一个签名驱动从资源段释放到 %TEMP%
2. 用 SCM 或直接调用 NtLoadDriver 加载它
3. 驱动在内存里扫描物理地址范围(通过 \\.\PhysicalDrive0 或内存管理接口)
4. 把读到的数据流式写入目标文件
5. 驱动卸载,临时文件删除

这条路径的取证含义:

观察点 取证价值
%TEMP% 下的随机名驱动文件 若现场被查获残留,说明有人采过内存
事件日志中的服务安装记录(System.evtx,事件 ID 7045) 记录了驱动服务名与路径
C:\Windows\System32\drivers\ 下的异常 .sys 部分工具会留下驱动
MemProcFS / vol.py windows.modules 中的匿名模块 内核里可能有未在磁盘上的驱动

这些痕迹本身是"有人做过内存采集"的证据——与第 10 篇讲的 Sysmon 事件互为印证。

2.3 Linux 侧:LiME 与 AVML 的取舍

维度 LiME AVML
实现方式 内核模块(lime.ko) 用户态静态编译二进制
编译依赖 需要目标机的内核头文件(/lib/modules/$(uname -r)/build) 不需要,编好的静态二进制直接跑
输出格式 lime(带地址范围表)/ raw / padded LiME 格式(未压缩时),--compress 用 Snappy
压缩 无(可后处理) --compress 采集时即压缩
远程推送 支持(path=tcp:...) 支持(--url / --sas-url / stream tcp)
风险 加载内核模块会在内核里留痕迹,且可能与安全模块冲突 纯用户态,痕迹少

实战选择建议:能在联网环境提前把 LiME 编译好就用 LiME(格式生态最成熟);目标机在内网/断网、或内核头文件与运行内核不匹配时,用 AVML(静态二进制,扔过去就能跑)。

LiME 的三种输出格式:raw 是纯物理内存、地址=文件偏移但丢失地址映射表;padded 是 raw + 对未映射区补零;lime 带地址范围元数据,是首选。

为什么推荐 format=lime:物理内存并非全地址空间连续存在。lime 格式在文件头记录了每个分段的地址范围,分析工具据此正确映射。raw 格式遇到"空洞"(MMIO 区间、设备保留区)时,偏移与地址的对应关系就断了。

2.4 Android:三重锁

第一重:root —— 没有 root,读不了 /dev/mem 也不能加载模块
第二重:SELinux —— 即便 root 了,Enforcing 模式下也禁止访问内存设备
第三重:设备指纹 —— 不同厂商 ROM 对上述机制的实现不同,通用命令常常失效

SELinux 是最容易踩坑的一环:

确认当前状态:Enforcing(拦截)/ Permissive(记录但不拦截)/ Disabled

adb shell getenforce adb shell su -c "setenforce 0" # 方式 A:临时切 Permissive(会留状态变更痕迹) adb shell su -c "setsebool -P allow_execmem 1" # 方式 B:Enforcing 下的正规做法

方式 C(最彻底):内核编译时完全关闭 SELinux,仅适用于自建 ROM 或专用设备

⚠️ setenforce 0 本身会改变系统安全状态。如果后续要对该设备做其他取证,这一状态变更必须记录在报告里;恢复为 setenforce 1 后再取证更规范。** /dev/mem 为何不可用**:新内核(自 5.x 起)默认限制 /dev/mem 只暴露前 1 MB 甚至完全禁止,这是一项针对 /dev/mem 攻击面长期存在的加固措施。所以别在 Android 上指望 dd if=/dev/mem。

2.5 macOS:SIP 与 kext 签名

Apple 从 OS X 10.11 起引入 SIP(System Integrity Protection),默认阻止加载未签名或未授权的第三方 kext。osxpmem 这类工具依赖一个内核扩展(kext)来读物理内存,因此:

系统状态 可行性
完全默认的现代 macOS + SIP 开启 不可行,且技术上难以绕过
需重启进入恢复模式降低安全策略 降低后仍需 kext 通过签名校验
企业环境通过 MDM 下发并授权了取证工具 可行(Apple 为此在企业场景留了正式通道)

结论:现代 macOS 的在线内存采集在技术上已近乎不可行。 若确需 macOS 内存证据,现实路径是关机后取证休眠镜像(/private/var/vm/sleepimage,或 12 点后改为 hibernation 相关文件)——休眠本质是压缩后的内存转储,虽然是"休眠那一刻"而非"关机那一刻",但仍是有效的内存证据。macOS 侧的其他工件见计算机取证 macOS 板块。

Linux 与 Android 的具体采集命令、AVML 与 LiME 的取舍、root 与 SELinux 的门槛,见第 09 篇。


三、操作步骤

3.1 Windows:三种采集方式

方式 A:WinPmem(推荐,开源、支持 raw / AFF4 / ELF)

raw 格式(最通用,Volatility 可直接读)

E:\kit\winpmem.exe -o E:\evidence\DigiForensics-mem.raw --format raw

AFF4 格式(容器格式,自带采集元数据,可用 7-Zip 解包出内部 raw 流)

E:\kit\winpmem.exe -o E:\evidence\DigiForensics-mem.aff4

指定线程数加速(默认 2)

E:\kit\winpmem.exe -o E:\evidence\DigiForensics-mem.aff4 --thread 4

查看完整帮助

E:\kit\winpmem.exe -h

格式选择建议:.raw 兼容性最好,任何工具都能读;.aff4 自带元数据(采集时间、工具版本、范围表),在法庭上更利于证据完整性论证,但部分老工具不认。--format elf 支持稀疏区间,不常用于取证场景。

方式 B:DumpIt(Comae / Magnet 旗下,操作极简)

DumpIt.exe /O E:\evidence\DigiForensics-mem.raw /T RAW   # /O 目标路径,/T RAW 输出 raw
DumpIt.exe /O E:\evidence\DigiForensics-mem.dmp            # 默认为 Windows 崩溃转储格式

注意版本:老版 DumpIt 在较新的 Windows 10 上可能产生不完整的转储。遇到解析失败优先换 WinPmem。

方式 C:FTK Imager(GUI,商业,机构常用)

菜单路径:File → Capture Memory…,选目标介质,可勾选 Include pagefile(建议勾上,页缓存里的数据价值很高),输出 .mem 文件(raw)。

方式 D:ProcDump(进程级,不是全量)

procdump64.exe -accepteula -ma <PID> E:\evidence\lsass.dmp          # 按 PID
procdump64.exe -accepteula -ma lsass.exe E:\evidence\lsass.dmp     # 按进程名
procdump64.exe -accepteula -ma <PID> \\analyst-pc\share\lsass.dmp  # 远程 UNC

ProcDump 输出的是 Windows 崩溃转储格式(minidump full),不是物理内存镜像。它可以用 Windbg/IDA 分析,但不能直接当 vol.py -f 的输入。它的价值在于只关心一个进程时,能拿到该进程全部内存(包括 LSA Secret),且体积远小于全量镜像。

方式 E:LiveAcquire(FTK 的商业一体化方案)

以采集代理方式运行在目标机(需安装为服务),提供计划任务、告警回调、自动归档到 FTK 平台。适合企业常态化采集,不适用于司法现场的一次性取证(部署本身就改动了目标机)。

3.2 Linux:AVML 优先

===== 前提:确认环境 =====

uname -r # 记录内核版本(分析时需要匹配符号) cat /proc/meminfo | head -3 # 确认内存总量 id # 确认 root cat /sys/kernel/security/lockdown # 若非 none,AVML 会静默失败

===== 方式 A:AVML(推荐,无需内核模块)=====

./avml /media/usb/DigiForensics-mem.raw # 基础采集(LiME 格式) ./avml --compress /media/usb/DigiForensics-mem.raw.compressed # Snappy 压缩 ./avml --source /dev/crash /media/usb/DigiForensics-mem.raw # 指定内存源 ./avml --url https://analyst-pc:9000/ --delete /tmp/DigiForensics-mem.raw # 上传并删本地

AVML 的重要限制:若目标机开启了内核的 lockdown 安全特性(部分发行版默认开),AVML 无法采集。此时需先确认 cat /sys/kernel/security/lockdown 的返回值,或改用 LiME 等其他方式。

AVML 压缩镜像的转换(分析前必须解压):

./avml-convert /media/usb/DigiForensics-mem.raw.compressed /work/DigiForensics-mem.raw

或使用新版的子命令形式

avml convert ./compressed.lime ./uncompressed.lime

方式 B:LiME(内核模块)

===== 构建(在与目标机同版本内核的机器上做)=====

sudo apt install -y build-essential linux-headers-$(uname -r) git git clone https://github.com/504ensicsLabs/LiME.git cd LiME/src && make # 产出 lime.$(uname -r).ko

===== 加载并采集(目标机上执行,需 root)=====

注意 path= 和 format= 必须带引号(否则 insmod 解析失败)

sudo insmod ./lime.ko "path=/media/usb/DigiForensics-mem.raw format=lime" sudo insmod ./lime.ko "path=tcp:analyst-pc 9000 format=lime" # 远程推送

采集端同时执行:nc -l 9000 > DigiForensics-mem.raw

卸载模块(务必卸载,否则在 /proc/modules 留下记录)

sudo rmmod lime lsmod | grep lime # 应无输出

⚠️ insmod 引号是硬性要求。不带引号时 shell 会在 = 处分词,导致参数被拆开,加载失败或写入异常路径。这是 LiME 最常见的错误。

方式 C:/proc/kcore 与 /dev/mem(为什么实际少用)

方法 问题
/proc/kcore 体积巨大(包含全部物理地址空间,含大量未使用区域),速度慢(要逐页读),且需要 CAP_SYS_RAWIO;某些内核配置下根本打不开
dd if=/dev/mem 现代内核基本失败:自 5.x 起 /dev/mem 默认只暴露前 1 MB;CONFIG_STRICT_DEVMEM 进一步限制;即使能读也极慢

结论:这两条路在取证实践中基本不作为首选。/proc/kcore 只在"没有其他手段且机器空闲"时作为最后选项,且要预估数倍于物理内存的磁盘占用。推荐顺序:AVML > LiME > 其他专用工具 >> /proc/kcore / /dev/mem。

3.3 macOS

传统方式(需 kext 通过签名 + SIP 放行,现代系统上基本不可行)

sudo ./osxpmem -o DigiForensics-mem.raw sudo ./osxpmem -h

现实可行的替代路径:休眠镜像(本质是压缩的内存转储)

ls -la /pri