vol-rs
将 Volatility 3 内存取证框架从 Python 移植到 Rust。它读取相同的内存镜像,以相同的选项运行相同的插件,并逐字节打印相同的结果,但速度快得多。
许可证
本项目是 Volatility 3 的移植版本,因此属于 Volatility Software License 1.0 条款下的“衍生作品”,并以同一许可证发布。完整文本见 LICENSE,也可在线查阅:https://www.volatilityfoundation.org/license/vsl-v1.0。每个源文件都保留了注明其来源的声明。
本项目与 Volatility Foundation 无隶属关系,也未获得其认可。Volatility 这一名称仅用于说明本项目移植自何处。
构建
需要 Rust 1.85 或更新版本,然后执行:
cargo build --release
生成的二进制文件位于 target/release/vol-rs。不需要任何可选依赖。符号解压、RC4、DES、AES、YARA 匹配、x86 反汇编、PNG 写入和 tar 归档全部内置,而 Python 版本需要依赖 pycryptodomex、yara-python、capstone 和 pillow。
使用方法
./target/release/vol-rs -f memory.raw windows.pslist.PsList
./target/release/vol-rs -f memory.lime linux.bash.Bash
./target/release/vol-rs -f memory.raw -r csv windows.netscan.NetScan
./target/release/vol-rs windows.malfind.Malfind --help
./target/release/vol-rs --list-plugins
Python 版本支持的每个选项这里都支持,名称和默认值完全相同,包括 -o、-r、-s、-c、-e、--filters、--hide-columns、--save-config、--stackers 和 --single-swap-locations。每个插件自身的选项也一一对应,帮助页面可以证明:全部 197 个插件的帮助页面与 Python 版本逐字符一致。
符号
符号包放在 $XDG_DATA_HOME/vol-rs/symbols,若该变量未设置则为 ~/.local/share/vol-rs/symbols。位于其他位置的符号包可通过 --symbol-dirs 或 VOLRS_SYMBOL_PATH 环境变量指定。Windows 符号按需从 Microsoft 符号服务器获取,并缓存在 ~/.cache/vol-rs 下。
已验证内容
双方针对相同的内存镜像运行并进行了对比,包括表头框架和末尾换行符:
| 检查项 | 结果 |
|---|---|
| 无参数运行的 Windows 插件 | 100 个中 99 个完全一致 |
| 无参数运行的 Linux 插件 | 57 个中 56 个完全一致 |
| 带参数的运行 | 43 个中 43 个完全一致 |
| 提取类插件写出的文件 | 对比了 1,747 个,两个工具写出的每个文件都相等 |
| 插件帮助页面 | 197 个中 197 个完全一致 |
未通过对比的 8 个文件是下方“已知差异”中列出的两种情况。其中 7 个是 Python 版本在报告无法转储后留在磁盘上的部分文件,本移植版不会生成这些文件;另外 1 个是 tar 包,其内容一致,但时间戳记录的是每次运行发生的时刻。
上述统计中缺失的两个插件是 Python 版本在测试机上无法运行完成的插件。windows.memmap.Memmap 在输出 780 万行后被 OOM killer 终止,linux.pscallstack.PsCallStack 在结束前被终止。在这两种情况下,Python 版本此前成功输出的每一行都被精确复现。
在所有无参数运行的插件中,Windows 全套测试在本机耗时 273 秒,而 Python 版本为 5723 秒;Linux 全套测试耗时 68 秒,而 Python 版本为 3130 秒。
速度
每个镜像上差距最大的十个插件(统计范围为所有无参数运行的插件):
Windows
| 插件 | Rust | Python | 提速 |
|---|---|---|---|
windows.malware.suspicious_threads.SuspiciousThreads | 0.47 秒 | 281.6 秒 | 599 倍 |
windows.suspicious_threads.SuspiciousThreads | 0.50 秒 | 259.1 秒 | 518 倍 |
windows.malware.hollowprocesses.HollowProcesses | 0.52 秒 | 257.9 秒 | 496 倍 |
windows.suspended_threads.SuspendedThreads | 0.090 秒 | 42.0 秒 | 467 倍 |
windows.malware.malfind.Malfind | 0.52 秒 | 236.5 秒 | 455 倍 |
windows.hollowprocesses.HollowProcesses | 0.59 秒 | 263.0 秒 | 446 倍 |
windows.debugregisters.DebugRegisters | 0.090 秒 | 37.0 秒 | 411 倍 |
windows.malfind.Malfind | 0.65 秒 | 239.7 秒 | 369 倍 |
windows.vadinfo.VadInfo | 0.99 秒 | 329.7 秒 | 333 倍 |
windows.verinfo.VerInfo | 0.99 秒 | 150.7 秒 | 152 倍 |
Linux
| 插件 | Rust | Python | 提速 |
|---|---|---|---|
linux.library_list.LibraryList | 1.99 秒 | 788.7 秒 | 396 倍 |
linux.kallsyms.Kallsyms | 2.41 秒 | 161.6 秒 | 67 倍 |
linux.netfilter.Netfilter | 0.89 秒 | 56.3 秒 | 63 倍 |
linux.lsof.Lsof | 0.89 秒 | 55.6 秒 | 62 倍 |
linux.sockstat.Sockstat | 1.60 秒 | 97.2 秒 | 61 倍 |
linux.check_idt.Check_idt | 0.82 秒 | 49.7 秒 | 61 倍 |
linux.malware.netfilter.Netfilter | 1.07 秒 | 62.0 秒 | 58 倍 |
linux.pagecache.Files | 1.67 秒 | 93.4 秒 | 56 倍 |
linux.kthreads.Kthreads | 0.87 秒 | 47.2 秒 | 54 倍 |
linux.proc.Maps | 2.53 秒 | 135.4 秒 | 54 倍 |
BENCHMARKS.md 中包含其余数据:两个镜像上的所有插件、带参数的运行,以及测量这些数字所用的机器。
已知差异
少数几处无法做到一致,且每一处都是有意为之:
linux.pagecache.RecoverFs会为它写入的 tar 包中的每个文件打上插件运行时刻的时间戳,因此任何两次运行的结果都不一致,即使是两次 Python 运行也一样。表格内容一致,解包后的目录树也一致。--save-config和timeliner --record-config会记录描述镜像的每一项设置,但不会记录 Python 版本中对导入组件是否足够新的检查,因为本移植版没有此类检查可记录。linux.mountinfo --mount-format会连接一个 Python set,因此其列顺序在两次 Python 运行之间会变化。本移植版先列出挂载选项,再按内核保存的顺序列出文件系统选项。frameworkinfo和isfinfo描述的是工具本身而非镜像,因此它们报告的是本移植版自己的层、插件和符号文件。windows.dumpfiles不会像 Python 版本那样,在发现无法读取文件之前先留下部分文件。表格内容一致,目录因这些文件而有所不同。--help中指明缓存目录的那一行写的是本移植版自己的缓存。
待办事项
以下内容均已移植并能编译,但尚未针对真实证据运行过:
- 用真实的 Mac 镜像测试 23 个 macOS 插件。这 23 个插件已逐行对照 Python 源码阅读,其触及的每个类型、成员和符号都对照覆盖 10.10 至 10.15 的 129 个已发布 Darwin 符号文件进行了核对,因此版本回退逻辑已确认是完整的。剩下的只是需要一个真实的 Mac 镜像来运行它们。
- 测试 32 位镜像。目前为止所有验证都使用 64 位镜像,因此 Intel32 和 PAE 分页路径仅有单元测试覆盖。
- 测试其他镜像格式。目前只使用了 VMware 和 LiME 镜像,因此 crash dump、AVML、QEMU、ELF core 和 Xen 层尚未在真实文件上得到验证。
- 测试更多内核版本。一个 Windows 10 19045 和一个 Linux 6.8 镜像的覆盖面太窄,而读取特定版本结构的插件正是移植最容易产生偏差的地方。
- 添加 arrow 和 parquet 渲染器。目前它们在命令行上会被接受然后拒绝,这与 Python 版本在其表格库缺失时的行为一致。
致谢
Volatility 3 是 Volatility Foundation 及其贡献者的成果。本移植版移植了他们的设计、插件集和输出格式,它之所以存在,正是因为这些工作是开放的。