ESC
开源 2 分钟阅读

vol-rs:Volatility 3 移植至 Rust——输出完全一致,速度快得多

内存取证框架 Volatility 3 被 Rust 重写为 vol-rs:读取相同内存镜像,插件与输出逐字节一致,速度却大幅提升。Windows 全套插件从 5723 秒降至 273 秒,Linux 从 3130 秒降至 68 秒,最快插件提速 599 倍。AES、YARA、反汇编等全部内置,无需 Python 依赖,项目以 Volatility Software License 1.0 发布。

来源:GitHub

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

插件RustPython提速
windows.malware.suspicious_threads.SuspiciousThreads0.47 秒281.6 秒599 倍
windows.suspicious_threads.SuspiciousThreads0.50 秒259.1 秒518 倍
windows.malware.hollowprocesses.HollowProcesses0.52 秒257.9 秒496 倍
windows.suspended_threads.SuspendedThreads0.090 秒42.0 秒467 倍
windows.malware.malfind.Malfind0.52 秒236.5 秒455 倍
windows.hollowprocesses.HollowProcesses0.59 秒263.0 秒446 倍
windows.debugregisters.DebugRegisters0.090 秒37.0 秒411 倍
windows.malfind.Malfind0.65 秒239.7 秒369 倍
windows.vadinfo.VadInfo0.99 秒329.7 秒333 倍
windows.verinfo.VerInfo0.99 秒150.7 秒152 倍

Linux

插件RustPython提速
linux.library_list.LibraryList1.99 秒788.7 秒396 倍
linux.kallsyms.Kallsyms2.41 秒161.6 秒67 倍
linux.netfilter.Netfilter0.89 秒56.3 秒63 倍
linux.lsof.Lsof0.89 秒55.6 秒62 倍
linux.sockstat.Sockstat1.60 秒97.2 秒61 倍
linux.check_idt.Check_idt0.82 秒49.7 秒61 倍
linux.malware.netfilter.Netfilter1.07 秒62.0 秒58 倍
linux.pagecache.Files1.67 秒93.4 秒56 倍
linux.kthreads.Kthreads0.87 秒47.2 秒54 倍
linux.proc.Maps2.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 及其贡献者的成果。本移植版移植了他们的设计、插件集和输出格式,它之所以存在,正是因为这些工作是开放的。