SecurityRonin/snss-forensic

GitHub: SecurityRonin/snss-forensic

一个用 Rust 编写的 Chromium 系浏览器 SNSS 会话文件只读取证解码器,用于验证、解码并重放浏览器会话恢复数据中的标签页状态。

Stars: 0 | Forks: 0

# snss-forensic [![snss-core](https://img.shields.io/crates/v/snss-core.svg?label=snss-core)](https://crates.io/crates/snss-core) [![Docs.rs](https://img.shields.io/docsrs/snss-core?label=docs.rs)](https://docs.rs/snss-core) [![Rust 1.81+](https://img.shields.io/badge/rust-1.81%2B-orange.svg)](https://www.rust-lang.org) [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE) [![Sponsor](https://img.shields.io/badge/sponsor-h4x0r-ea4aaa?logo=github-sponsors)](https://github.com/sponsors/h4x0r) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/1c4bc22135185827.svg)](https://github.com/SecurityRonin/snss-forensic/actions/workflows/ci.yml) [![Coverage](https://img.shields.io/badge/coverage-100%25%20lines-brightgreen.svg)](https://github.com/SecurityRonin/snss-forensic/actions/workflows/ci.yml) [![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) [![Security advisories](https://img.shields.io/badge/security-cargo--deny-informational.svg)](deny.toml) **面向 Rust 的 Chromium/Brave/Edge SNSS 会话文件取证工具 —— 一个无 panic、 只读的解码器,用于验证 `SNSS` 命令流,将其拆分为 带长度前缀的记录,解码 navigation-command 的 `base::Pickle` payload,并 将它们重放为浏览器启动时恢复的各窗口 tab 状态。** SNSS 是 Chromium 系浏览器用来持久化 会话和 tab 状态的追加写入(append-only)命令日志格式 —— 即“恢复你的标签页”背后的 `Session_*`、`Tabs_*` 和 `Apps_*` 文件(以及 现代的 `Sessions/` 文件夹)。每个文件由一个 4 字节的 `SNSS` magic 加上一个版本头组成,其后跟着带有 `u16` 长度前缀的命令 记录;导航命令包含一个 Chromium `base::Pickle` payload。 [`snss-core`](https://crates.io/crates/snss-core) 如实解码该结构,并且 不做任何主观判断 —— 没有 `unsafe`,没有 C 绑定,也没有写入路径。 ## 30秒读取会话文件 ``` [dependencies] snss-core = "0.1" ``` ``` use std::io::Cursor; // 1. Validate the SNSS header and split the command stream into records. let stream = snss::read_records(Cursor::new(bytes))?; // 2. Replay the commands into the per-window tab tree the browser would restore. let replayed = snss::replay(&stream, snss::Dialect::Session); for window in &replayed.windows { for tab in &window.tabs { let nav = tab.current_nav(); // the current entry of each open tab println!("tab {} -> {} ({})", tab.id, nav.url, nav.title); } } // Non-fatal anomalies (a truncated live-file tail, a bad navigation Pickle) are // surfaced, never silently dropped: for w in &stream.warnings { eprintln!("{w:?}"); } # Ok::<(), snss::SnssError>(()) ``` `Tabs_*` 文件(最近关闭的恢复列表)使用 `Tabs` 方言;请传入 `snss::Dialect::Tabs`。要一次性遍历 profile 目录下的每一个会话源, 请使用 `snss::SessionStore::open_dir(profile_dir)`(或者 `open_default_profile()`),它会读取每个源并保留各源的警告。 ## 解码内容 | 入口 | 读取内容 | 产物 | |---|---|---| | `read_records` | `SNSS` magic + 版本头,`u16` 长度记录 | `RecordStream { version, records, warnings }` | | `decode_navigation` | 一个导航命令的 `base::Pickle` payload | `NavCommand { tab_id, index, url, title }` | | `replay` | 一个 `RecordStream` + 方言 | `Replayed { windows }` — `Window`/`Tab`/`Nav` 树 | | `SessionStore::open_dir` | 一个 profile 目录 | 所有发现的 `Source` + 警告 | `base::Pickle` 解码器是 4 字节对齐的,且完全按照 Chromium 写入它的方式带有长度前缀(UTF-8 URL,UTF-16-LE 标题);重放时对 `(tab, index)` 应用“最后写入生效”(last-write-wins)原则,并解析每个 tab 的当前条目及固定状态。 ## 信任但要验证 SNSS 文件是未经信任的、可被攻击者控制的输入,因此该 crate 在构建时经过了严格的安全加固: - **`#![forbid(unsafe_code)]`** 覆盖整个工作区 —— 任何地方都不允许使用 `unsafe`。 - **设计上即为只读** —— 解码器**不提供写入路径**;通过此 API 在结构上是不可能修改浏览器会话存储的。 - **无 panic** —— 每个记录长度、Pickle 字段长度以及对齐步骤 在使用前都经过了边界检查;精心构造的长度字段无法引发 越界读取或内存分配炸弹。格式错误的输入会以类型化的 `SnssError` 或非致命的 `Warning` 呈现,绝不会是静默的默认值。 - **经过模糊测试** —— `cargo-fuzz` 目标涵盖了记录流读取器(`records`)和 导航 `base::Pickle` 解码器(`navigation`);其不变性是“绝不能发生 panic。” - **基于真实 Chromium 数据验证** —— 读取并重放了真实的 Brave `Session_*`/`Tabs_*`/`Apps_*` 文件(测试夹具被 gitignore 忽略了 —— 因为它们包含个人 历史记录),并辅以字节精确的合成命令流。请参阅 [`docs/validation.md`](docs/validation.md)。 ## 计划中:`snss-forensic` 分析器 该工作区今天发布了读取器(`snss-core`)。一个同级的 `snss-forensic` 分析器 crate —— 针对 会话恢复异常(例如悬空或前向引用的 tab 索引、 截断尾部恢复、重放不一致)输出严重性分级的 [`forensicnomicon::report`](https://crates.io/crates/forensicnomicon) 结果 —— 是一个计划中的后续项目,以便将会话文件的异常情况与其他所有 artifact 层统一聚合。目前还没有 分析器逻辑;这里也没有对其进行存根或伪造。 ## 参考 - **Chromium `components/sessions`** —— 标准的 SNSS 写入器/读取器(命令 帧封装、`SNSS` magic + 版本头、追加写入日志): - **Chromium `base::Pickle`** —— 导航 payload 使用的字段编码格式: [隐私政策](https://securityronin.github.io/snss-forensic/privacy/) · [服务条款](https://securityronin.github.io/snss-forensic/terms/) · © 2026 Security Ronin Ltd
标签:Chromium, Rust, 云资产清单, 可视化界面, 数字取证, 数据解析, 网络流量审计, 自动化脚本, 逆向工程, 通知系统