关键词: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)=====
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