搜索全站

输入至少 2 个字符,查找相关内容。

↑↓ 选择 Enter 打开Esc 关闭

内存取证总览

如果你接手的是一台还在运行的机器,或者一台刚刚被人手动关机的机器,那么有一个问题磁盘永远回答不了:这台机器在被关掉的那一刻,到底在做什么?

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

一、概述

如果你接手的是一台还在运行的机器,或者一台刚刚被人手动关机的机器,那么有一个问题磁盘永远回答不了:这台机器在被关掉的那一刻,到底在做什么?

磁盘上的一切都是过去式。文件时间戳、注册表 hive、事件日志、缓存文件,全是已经落盘的状态快照。

内存是现在进行式。它装着正在跑的进程、当前的网络连接、已解密但从未写回磁盘的会话密钥、正在编辑但从未保存的文档。这部分数据在磁盘上不是"被删除了",而是从未被写入过。

所以会出现这种局面:磁盘分析做了好几天,最后才发现委托方真正想问的那个问题,答案在设备断电那刻就已经灭失了。而且不可补。

内存取证卡在整个流程的最前端,属于采集环节,而且是唯一一个"顺序错了就全盘皆输"的环节。它的上游依赖很少:目标机还开着、有权限、有外接存储,三条就行。下游则支撑起后面所有分析工作——进程与注入检测、网络连接归属、凭据与密钥提取,全都只能从内存镜像起步。

按流程位置排:现场在线判断 → 内存采集 → 同期状态快照 → 磁盘镜像 → 离线分析。内存排在磁盘前面不是习惯问题,是证据属性决定的。

这块能碰到的工件分四种载体:

载体 典型工件 关键字段
物理内存镜像 DigiForensics-mem.raw、lime/avml 输出、.vmem 快照、hiberfil.sys 物理地址空间、页表、符号表
运行态结构 EPROCESS、_RTL_USER_PROCESS_PARAMETERS、内核池 tag 进程链、命令行、模块基址
活动会话状态 tasklist / netstat -ano / route print / arp -a 的现场输出 PID、协议、本地与远端地址
分析配置 Volatility Profile 的 PDB GUID 与 build 号、ISF 符号文件 NtBuildLab、符号版本号

最后一类最容易被忽略:没有匹配的符号,内存镜像里的一切都读不出来。所以 Profile 机制不是工具细节,是内存分析的准入条件。

据此能回答的是这些:某时刻有哪些进程在运行、进程之间是什么父子关系、有哪些已建立或已关闭的 TCP 连接、哪些内存区域是私有可执行页(注入特征)、会话密钥与解密后内容是否驻留在内存、攻击者程序是否只存在于内存中而磁盘无痕。

回答不了的是这些:用户在采集区间内具体看到或输入了什么、精确到秒的行为先后顺序、设备在采集区间之前已经发生过的行为、以及任何在采集时被换出到 pagefile.sys 而未随镜像采集的内容。内存镜像代表的是一个区间而不是一个时刻,这一点决定了所有结论的表述方式。

往下读之前,先确认你已经具备:磁盘镜像与只读挂载的基本能力(否则拿到的 .raw 无法进入分析环境,见镜像制作)、哈希与保管链的常规意识(见证据保管链)、以及最低限度的体系结构知识——理解进程、虚拟地址空间、内核与用户态的分界。

磁盘侧还一无所获时,先看取证工件地图建立对照。

二、核心原理

2.1 易失性等级(Order of Volatility)

这是内存取证最核心的操作原则。证据的易失性从高到低有严格顺序,采集必须按此顺序进行——不是"按方便程度",而是"按丢失速度"。

顺序 证据类型 丢失机制 典型采集手段
1 CPU 寄存器 / 指令指针 / 栈顶 纳秒~微秒 硬件调试器(JTAG/FPGA)、崩溃转储寄存器段
2 运行时表(内核池、活动结构) 秒级 内核内存镜像、NetScan 类扫描
3 网络连接、DNS 缓存、路由表、ARP 缓存 秒~分钟 内核池扫描、NDIS 状态
4 运行中的进程与线程上下文 秒~分钟 进程/线程枚举与转储
5 用户态数据:会话、句柄表、剪贴板、编辑缓冲区 分钟~小时 进程转储、dumpfiles
6 文件系统缓存(页缓存、文件数据) 分钟~小时 filescan + dumpfiles、pagefile
7 磁盘上的持久化数据 永久 常规磁盘取证

为什么"寄存器排第一":如果攻击者正在执行,CPU 寄存器里的指令指针指向他此刻正在跑的代码——这是最直接的活动证据。但软件采集拿不到寄存器(只有崩溃转储或硬件方法才行),因此软件采集实际上从第 2 层开始,第 1 层是理论上的最优起点。这一点在报告里要写明,不能声称"已采集寄存器"。

顺序的实际含义:先拷贝磁盘再采内存是错的。拷贝几 TB 磁盘要几小时,期间内存里的一切都已改变甚至消失。

先关机再采内存同样错。关机瞬间内存归零。

正确顺序:保持开机 → 采集内存 → 然后才是磁盘。

2.2 内存为什么"一采就变"

内存不是只读介质。采集过程本身就在改写它:

采集开始 ──┬─ 加载驱动/内核模块(本身要占内存)
            ├─ 分配目标缓冲区(挤占被采集的数据)
            ├─ 把内存页 pin 住(防止被换出)
            └─ 目标系统继续运行(网络包、内核日志仍在变化)

这导致一个根本性事实:内存镜像的物理地址不再等于采集瞬间的物理地址。 你在镜像里看到的"偏移 0x1a3e5000 的字节",是采集期间某一刻被复制过去的,它之前的内容已经被覆盖。

对取证的直接影响分三块。

不能做的,是对内存镜像做严格的"逐字节解释"。要求毫秒级时序精度的场景(函数入口追踪之类)直接排除。

可以放心做的是枚举类操作——进程、网络、句柄,加上字符串搜索、注入特征检测。这些只需要"某个时刻存在过",不要求"精确在那一刻"。

还有一条容易写反:报告中不应把内存的时序精度说成比磁盘更高。恰恰相反,内存证据的时序精度受采集耗时影响,远低于磁盘上的 FILETIME 精度。

2.3 采集的时机窗口

内存证据的"窗口"由三件事共同决定:采集耗时(32 GB 内存、软件采集、USB 3.0 写入通常 5–15 分钟;1 TB 服务器用 PCIe FPGA 可缩短到 1–2 分钟)、采集期间的系统活动(采集越慢,"镜像代表哪一刻"越模糊)、数据自然衰减(部分内容会被换出、被覆盖)。

这三项里,采集耗时最容易被低估。它同时决定两件事:镜像有多长,以及"镜像代表哪一刻"这个问题有多模糊。

必须在报告中记录的三个时间点:采集开始时间(到秒)、采集结束时间(到秒)、时区与 UTC 偏移。只有开始时间是不够的——"内存镜像代表的时间"是一个区间 [开始, 结束],不是时刻。

2.4 手机与小内存设备:现实约束

约束 桌面 Windows 手机
物理内存大小 8–128 GB 4–12 GB
采集权限 管理员即可 必须 root(iOS 需越狱)
加密存储 BitLocker(可尝试) 文件级加密 + SELinux 双层
采集通道 USB 3.0 / PCIe USB 2.0/3.0 慢,或直接推送到云
电池 不考虑 边充边采,否则中途关机全丢
热管理 一般无问题 长时间采集易过热降频甚至强制重启

最要命的一条是"必须先解锁":现代手机在重启后需要用户输入口令才能解密 data 分区。已锁定状态下 /data 里的内容在内存中是不可读的密文。

所以对已关机的手机做内存取证基本无意义——内存里没有你想要的明文。

2.5 板块内容地图

本板块 10 篇按"从采集到报告"的完整链路组织:01 总览(本文)→ 02 采集方法 → 03 Volatility 3 框架 → 04 Profile 与符号匹配 → 05 进程与注入检测 / 06 网络连接与流量痕迹 / 07 凭据与密钥 / 08 注入执行与免杀痕迹(四根分析支柱)→ 09 Linux 与 Android → 10 可采性与报告。

最后一篇讲这些证据能不能用:采集痕迹要如何说明、隐私最小化到什么程度、报告该怎么写。见第 10 篇。


三、操作步骤

3.1 第 1 步:现场评估——先判断"还有没有内存可采"

在动手之前必须先回答一个问题:这台机器现在是开着的吗?内存里还有东西吗?

# Windows:确认系统在线(不要执行任何会关闭服务的命令)
Get-Date
query session

# 确认内存总量,这决定后续存储规划
systeminfo | Select-String 'Total Physical Memory','Available Physical Memory'
# Linux:确认在线 + 内存总量
uptime
free -h

# Android(已连接 adb)
adb shell getprop ro.product.model
adb shell cat /proc/meminfo | head -3
adb shell "su -c 'getenforce'"     # SELinux 状态,决定能否采

⚠️ 这一步的顺序绝不能颠倒。很多处置流程写成"先断开网络防止数据外传"——但如果执行方式是物理断电,内存就没了。正确做法是:先评估能否就地采集内存,不具备条件才考虑断电,并在报告中写明"因设备条件限制未采集内存,该部分证据已灭失"。

3.2 第 2 步:准备存储与工具

# 内存镜像大小 ≈ 物理内存大小(或略大,取决于采集工具与地址空间)
# 必须按"镜像大小"规划,且分析阶段还要额外空间

# 检查目标机可用的外部存储
df -h /media/usb

# 记录采集工具自身的哈希(关键,报告要用)
sha256sum /media/usb/avml ./winpmem.exe ./lime.ko
md5sum    /media/usb/avml                      # 部分旧工具只提供 MD5

必须提前准备的三件事:

准备项 理由
工具版本与哈希 同名工具不同版本行为可能不同,报告需可复现
充足的外部存储 镜像等于物理内存大小;32 GB 内存的机器要准备 ≥ 32 GB 空间
确认目标机未被污染 采集前不要在目标机上安装其他取证工具,会往内存里写入新东西

3.3 第 3 步:按易失性顺序采集

具体命令见第 02 篇。此处只给出顺序骨架:

[第一层] 崩溃转储中的寄存器段(若有)或硬件方式
[第二层] 内存镜像 ← 软件采样的起点
          Windows: winpmem / DumpIt
          Linux:   AVML(优先)或 LiME
          macOS:   osxpmem(需 kext 签名/SIP 放行)
          Android: 需 root
[第三层] 当前状态快照,与内存镜像同时进行
          进程列表、netstat -ano、路由表、ARP 表、已打开文件
[第四层] 关机 / 拆卸后按标准流程做磁盘镜像

"同时进行"是难点:内存镜像采集要花几分钟,期间系统状态一直在变。务实在内存采集开始的那一刻,把进程列表和 netstat 输出也记下来——这两样是"采集开始时刻"的快照,比镜像本身更接近真实起点。

3.4 第 4 步:立即固定与验证

# 采集后立刻算哈希(不要做任何其他操作)
sha256sum DigiForensics-mem.raw | tee acquisition-hash.txt

# 记录镜像大小,应与物理内存大小接近
wc -c < DigiForensics-mem.raw
ls -lh DigiForensics-mem.raw

# 记录采集工具哈希
sha256sum /media/usb/avml | tee tool-hash.txt

验证清单:

验证对象 方法 通过标准
镜像完整性 哈希已记录且后续复算一致 两次 SHA-256 相同
镜像大小 wc -c < 镜像 接近物理内存大小(偏差 < 5%)
镜像可解析 windows.info / linux.pslist 能输出结构化结果
时间可信 采集开始/结束时间已记录 含时区

3.5 第 5 步:分析产出必须可复现

# 每条分析命令都要留痕(这是报告的"可复现性"要求)
mkdir -p /evidence/analysis/{commands,output}
cd /evidence/analysis

# 用 -l 参数把 Volatility 自己的日志也留下来
python3 vol.py -f /evidence/DigiForensics-mem.raw -l vol.log -q windows.info

四、常见陷阱

内存取证最贵的错误不是"没采到",而是采到了却把它当成了它不是的东西。

把一个跨越 12 分钟的混合体当成某一时刻的快照。把"没找到"当成"没发生"。把工具自己写进内存的痕迹