关键词:现场处置、FileVault、APFS 整体镜像、只读挂载、易失数据、工具链、封条、启动安全
难度:综合
前置知识:本板块01–07全部内容、镜像制作与只读分析规范
一、概述
前七篇讲"macOS 上有什么、怎么看"。
这一篇讲的是另一件事:从接手一台 Mac 到出报告,按什么顺序做。
三个现场特征直接决定流程怎么排:
| 特征 |
直接后果 |
| FileVault 2 在 Monterey 之后默认开启 |
大多数新设备关机后即锁,不先解决密钥就什么都拿不到 |
| APFS 多卷共享块池 |
单独镜像某个卷会丢失容器级元数据,完整性无法证明 |
| Apple Silicon 只能启动签名映像 |
无法用传统外接启动盘现场启动取证环境,只能物理镜像 |
核心原则只有一条:先在不改写证据的前提下尽可能多取易失数据,再做物理镜像。
顺序错了,要么丢数据,要么破坏证据同一性。
另有三个现实必须显式处理:
| 现实 |
处理方式 |
| 统一日志、Spotlight 索引、内存态工件随关机消失 |
现场用 log show / mdfind 导出 |
| macOS 上的恶意软件常主动检测取证环境 |
现场处置记录必须详尽 |
| 破坏 Apple 封条在法律上有明确后果 |
见 2.7 |
在取证流程中的位置:本篇是 macOS 板块的流程编排篇,横跨采集与报告两端,既不是"只读挂载怎么做"那种单点技术,也不是"某个工件怎么解析"。它的输入是"一台处于某种状态的机器",输出是一份完整处置链路:现场状态记录 → 零密钥结构确认 → 镜像制作 → 只读挂载与验证 → 按序提取 → 工具链与报告。顺序在这里是内容的一部分,不是格式——同一个动作放错位置,性质就从"取证"变成"改写证据"。所以它是这个板块的实际起点:前几篇是它的参考手册,最后几篇是它的深水区。
本篇处理的证据形态,按易失程度分四类,处置顺序由此决定:
| 优先级 |
证据 |
现场手段 |
丢失后果 |
| P0 |
进程列表、网络连接、登录会话、打开的文件 |
ps auxww、netstat -an、who/w/lsof -nP,每份输出前置 date -u |
关机即永久消失 |
| P1 |
统一日志、Spotlight 索引与 kMDItemWhereFroms |
/usr/bin/log show --last 30d --info --style json、mdfind、mdutil -s |
关机后只剩部分持久化部分 |
| P2 |
硬件与系统标识、加密状态 |
system_profiler SPHardwareDataType(型号、Chip、序列号、Hardware UUID)、sw_vers、uptime、fdesetup status |
uptime 直接决定值不值得保持通电 |
| P3 |
镜像与卷结构 |
整个 APFS 容器(不是单个卷)、diskutil apfs list、容器超级块 |
缺失则完整性声明站不住 |
每份现场输出都必须带采集时刻,且必须录像——屏幕内容、登录用户、连接状态都要入镜。零密钥阶段还有一层:FileVault 没解开时不碰数据,也能靠 diskutil apfs list 的容器与卷清单、ntfs/apfs 结构的可见部分确认这台机器上"应该有什么",这个结论本身就是有价值的产出。
本篇能回答什么:这台设备的型号、芯片、序列号与硬件 UUID、加密状态、卷与快照布局、通电时长、处置顺序为什么这么排,以及每个环节拿到了什么、每份输出的采集时刻。
本篇不能回答什么:顺序对了不等于数据全——关机状态下 Spotlight 索引与内存态工件已经没了,log show 导出的也只是持久化部分,报告里要写明"哪些易失项因设备关机未能获取"。FileVault 密钥不在这台机器上时,镜像做得再规范也只能做零密钥结构分析,此时能出的结论限于结构性判断(例如存在多少个用户卷、有没有加密的交换卷),内容层面一概不能碰,所以阴性表述的门槛在零密钥现场要高得多。uptime 短不代表没发生过什么,它只说明现场状态与事发状态可能已经隔开了,时间线断层必须写明。另外本篇给不出结论,结论要靠证据链与交叉验证得出(见 取证流程与原则);它也无法判断机器上运行的恶意软件具体做了什么——那要回到 plist、统一日志、LaunchAgents 与 Quarantine 的具体分析。
读者前提:需要先读完本板块前两篇,知道工件在哪些路径下;需要理解 FileVault 2 的加密范围与 APFS 容器/卷/共享块池的关系,这两件事直接决定"能不能取"和"怎么证明没被破坏";需要知道 Apple Silicon 的启动安全性机制意味着无法现场外接启动盘,这不是工具缺失而是平台限制,所以必须接受物理镜像这条唯一路径;还要接受一条纪律:封条、录像、采集记录本身就是交付物的一部分,现场处置记录越详细,复核时能还原的空间越大;最后需要具备现场判断能力——uptime 与封条状态这种信息只出现一次,判断错了没有第二次机会。
二、核心原理
2.1 现场处置决策树
收到一台 Mac
│
├─ 已关机?──→ FileVault 状态?
│ ├─ 已解锁 → 直接镜像
│ └─ 已锁定 → ★ 必须先取得密钥
│
└─ 通电 ──→ ★ 关键决策点
├─ 近期有使用且易失数据有价值 → 先导出易失数据 → 关机 → 镜像
├─ 长期闲置、易失数据无价值 → 直接关机 → 镜像
└─ 疑似作案进行中 → ★ 保持现状,立即记录全部现场状态
"是否关机"没有标准答案,只有权衡记录。
复核人看的不是结论对不对,而是当时的信息支撑下这个决策是否合理。
决策理由、决策人、时间必须写进现场记录。
2.2 FileVault 密钥的四条合法路径
| 路径 |
适用 |
说明 |
| 委托人当面解锁 |
最常见 |
在委托方或司法人员在场时输入口令,当场镜像 |
| 个人恢复密钥 |
委托人记得 |
Apple ID 账户可查 |
| 组织统一管理的恢复密钥 |
企业环境 |
IT 部门集中保管,需书面授权 |
| 依法向 Apple 调取 |
常规路径均不可行 |
需司法程序,周期长 |
fdesetup status
FileVault is Off. ← 未启用
FileVault is On. ← 已启用且已解锁(通电状态)
FileVault is Enabled, but not unlocked. ← ★ 已启用且已锁定(关机状态,最常见)
三条红线:报告只写"已使用合法取得的密钥解密",绝不记录密钥字符串;不得尝试暴力破解或绕过密钥派生;"已锁定"绝不等于"数据已销毁"——这个措辞是事实性错误。
2.3 APFS 容器整体镜像的必要性
这是 macOS 取证最贵的坑。
APFS 容器(disk0s2,494.4 GB)
├── 容器超级块(NXSB) ← 块大小、总块数、块池分配表
├── 各卷的 B-tree 元数据 ← 文件名与 inode 映射
└── 共享块池
├── Macintosh HD(系统卷,只读签名) ├── Macintosh HD - Data(用户数据)
├── Preboot(预启动) ├── Recovery(恢复)
└── VM(交换)
单独 dd 某个卷会丢掉什么:
| 丢失的元数据 |
后果 |
| 容器超级块 |
无 NXSB 头,APFS 解析器可能直接拒绝打开 |
| 块池分配表 |
无法确定哪些块属于哪个卷,卷边界不可信 |
| 其他卷的元数据 |
缺 Preboot 会影响系统卷引导校验;缺 VM 丢失交换数据 |
| 快照索引 |
本地快照全部不可见,丢失"删除前内容" |
sudo dd if=/dev/rdisk0 of=/Volumes/Evidence/DigiForensics.dd bs=4m status=progress # ✓ 整盘
sudo dd if=/dev/rdisk0s2 of=/Volumes/Evidence/DigiForensics.dd bs=4m status=progress # ✓ 整容器
sudo dd if=/dev/rdisk3s5 of=/Volumes/Evidence/DigiForensics.dd bs=4m # ✗ 只镜像数据卷
"容量够就行"是错误的。
数据卷显示的 447.8 GB 既不是该卷实际占用块数(共享块池中属于它的块是离散的),也不是完整证据范围。
正确做法是镜像整个容器或整盘。
2.4 只读挂载的三种路径
| 方式 |
命令 |
限制 |
Linux apfs-fuse(主力) |
apfs-fuse -r <key> -o vol=2,ro /dev/loop0 /mnt/mac-data |
★ 默认只暴露一个卷;FileVault 需 -r |
macOS mount_apfs |
sudo mount_apfs -o rdonly,nobrowse … |
原生兼容性最好 |
| 镜像挂载 |
diskutil image attach -readonly DigiForensics.dd |
快速查看卷布局 |
hdiutil attach 在现代 macOS 已弃用,实测会输出 'hdiutil attach ...' is deprecated. Please use 'diskutil image attach ...' instead.。报告里写命令要用 diskutil image attach。
只读挂载后必须做的事:记录挂载前的镜像 SHA-256,分析完成后卸载并重新校验哈希。这是"全程未改写证据"的可复核证明。只写"只读挂载"而没有哈希对比,等于没有证明。
2.5 易失数据的优先级
| 优先级 |
内容 |
采集命令 |
丢失后果 |
| P0 |
进程与网络连接 |
ps auxww、netstat -an |
完全丢失 |
| P0 |
已登录用户与登录会话 |
who、w |
完全丢失 |
| P1 |
剪贴板 |
pbpaste |
完全丢失 |
| P1 |
统一日志(近 30 天) |
/usr/bin/log show --last 30d |
部分丢失(.tracev3 解析难) |
| P1 |
Spotlight 索引查询结果 |
mdfind / mdls |
完全丢失(二进制库无离线解析) |
| P2 |
打开的文件与网络挂载 |
lsof、mount |
丢失 |
| P3 |
FileVault 状态等 |
fdesetup status |
关机后仍可从镜像取得 |
P0–P2 全部"关机即永久丢失",这就是"能不能关机"这个决策的核心依据。
2.6 Apple Silicon 与启动安全性
| 能力 |
Intel Mac |
Apple Silicon |
| 外接启动盘启动系统 |
可(Option 键) |
★ 不可(只能启动签名映像) |
| 降低启动安全性策略 |
可(需管理员密码) |
需另一台 Mac + 恢复固件更新(法律上通常不允许) |
| 扣押后被引导攻击的风险 |
较高 |
★ 较低 |
对取证的影响:Apple Silicon 上无法制作可启动的取证副本,只能逐块物理镜像后在分析机上分析。这不是技术缺陷,是安全设计的副作用。
2.7 封条与证据完整性
| 情形 |
风险 |
| 要求"保持原样"却破坏封条 |
证据同一性受质疑,委托方可能主张排除 |
| 拆机换盘导致来源链断裂 |
需额外说明拆机过程与新盘来源 |
| 涂抹机器标识 |
可能被认定为破坏证据 |
正确做法:开箱与拆机全程录像(覆盖封条原状、序列号、型号);记录封条编号与状态;拆机前取得书面授权并写明授权人、时间、范围;拆下部件单独封存编号,并记录它与主机的对应关系。
三、操作步骤
3.1 第 1 步:现场状态记录(通电状态下立即执行)
system_profiler SPHardwareDataType # 型号、Chip、序列号、Hardware UUID
sw_vers; uptime # ★ uptime 判断是否值得保持通电
fdesetup status # ★ FileVault 状态
易失数据 P0(关机即永久丢失)
{ date -u '+%FT%TZ'; ps auxww; } > /evidence/live-ps.txt
{ date -u '+%FT%TZ'; netstat -an; } > /evidence/live-netstat.txt 2>&1
{ date -u '+%FT%TZ'; who; w; lsof -nP; } > /evidence/live-users.txt 2>&1
易失数据 P1:统一日志与 Spotlight
/usr/bin/log show --last 30d --info --style json > /evidence/live-log-30d.json 2>/dev/null
/usr/bin/log show --last 1h --info --style compact
--predicate 'subsystem == "com.apple.securityd" OR subsystem == "com.apple.network"' \
/evidence/live-log-security.txt 2>/dev/null
mdfind -onlyin /Users/liwei "kMDItemWhereFroms == '*'" > /evidence/live-wherefroms.txt 2>/dev/null
mdutil -s / > /evidence/live-mdutil.txt
mount > /evidence/live-mount.txt; df -h > /evidence/live-df.txt
每份输出都要带采集时刻(上面已前置 date -u)。同时录像:屏幕内容、登录用户、连接状态都要入镜。
3.2 第 2 步:零密钥结构确认
取得密钥之前也有活可干,而且这些结论必须最先写进报告:
mmls /work/DigiForensics.dd # 找 APFS 分区起始扇区
APFS_PART=775920
xxd -s $((APFS_PART*512 + 32)) -l 16 /work/DigiForensics.dd
→ 4e585342 ... ← NXSB 魔数:确认是 APFS 容器、块大小
apfsutil -o $((APFS_PART*512)) /work/DigiForensics.dd # 卷列表、oid、快照
零密钥可得的结论:文件系统类型、块大小、卷数量与名称、各卷 oid、快照存在与否与创建时间。
这些不依赖任何密钥,成本最低,也最经得起复核。
3.3 第 3 步:镜像制作
diskutil list # 区分 (internal, physical) 与 (synthesized)
diskutil apfs list | grep -E 'APFS Container Reference|Volume Name|Capacity'
df -h /Volumes/Evidence # 目标 ≥ 容器标称容量 × 1.03
diskutil unmountDisk /dev/disk3 # 减少写入风险
sudo dd if=/dev/rdisk0 of=/Volumes/Evidence/DigiForensics.dd bs=4m status=progress
sudo dd if=/dev/rdisk0s2 of=/Volumes/Evidence/DigiForensics.dd bs=4m status=progress
shasum -a 256 /Volumes/Evidence/DigiForensics.dd | tee /evidence/DigiForensics.dd.sha256
| 纪律 |
原因 |
必须用 r 前缀设备 |
非 r 走缓冲 I/O,慢一个数量级 |
bs=4m 或更大 |
默认 512 字节块做 500 GB 镜像需数小时 |
| 完成后立即算 SHA-256 |
唯一能证明"之后没人改过"的方法 |
| 记录 dd 起止时间 |
与案件时间线对照 |
| 目标 ≥ 容器标称容量 × 1.03 |
APFS 独立卷与元数据开销不在主卷显示容量里 |
3.4 第 4 步:只读挂载与验证
shasum -a 256 /work/DigiForensics.dd > /evidence/baseline.sha256 # ★ 挂载前算基线
apfs-fuse -r "<恢复密钥>" -o vol=2,ro /dev/loop0 /mnt/mac-data
或:diskutil image attach -readonly /work/DigiForensics.dd
mount | grep apfs # 确认含 ro
EV=/mnt/mac-data
ls -1 $EV/Users/
ls -1 $EV/Library/LaunchDaemons/ | wc -l
ls -1 $EV/Users//Library/LaunchAgents/ | wc -l
ls -1 $EV/var/db/diagnostics/Persist/ | wc -l
ls -1 $EV/Users//Library/Containers/ | w