首页 / 资讯中心 / 文章详情

Hindsight:开源Chromium浏览器取证工具解析Chrome历史记录实战指南

Hindsight:开源Chromium浏览器取证工具解析Chrome历史记录实战指南 ★ FEATURED ARTICLE
前些日子帮一个朋友处理内部调查目标很单纯搞清楚某个时间窗口里一台工作机到底访问过哪些站点、搜过什么关键词、下过什么文件。Chrome 的 History 文件本质是 SQLite 库直接打开也能看但原始表里全是 WebKit 时间戳URL、标题、跳转来源散落在不同表里想拼出完整画像得自己写 join 和换算公式我熬到后半夜才得到一份勉强能交差的结论。后来在一份公开取证报告里看到 Hindsight 这个名字试了一次就离不开了。Hindsight 是 Ryan Benson 维护的开源 Chromium 系浏览器取证工具名字起得很妙hindsight 就是“事后之明”而浏览器取证恰恰是一场事后复盘。它能把 Chrome、Chromium、Edge、Brave、Opera、Vivaldi 这类浏览器的用户目录拆成一份结构化的 SQLite 结果库再生成一份带时间线的 HTML 报告省掉大量手搓 SQL 的功夫。这篇文章不讲广告只讲我怎么用它、它到底读哪些数据、以及实战里最容易翻车的几个坑。1. 从“后见之明”说起为什么浏览器取证要在事后做文章1.1 一次内部调查把我带到 Hindsight 面前那次调查的场景很典型同事离职前有一台工作电脑需要确认他在最后两周是否把核心资料导出到了个人网盘或者是否有异常外发行为。不能直接开机翻浏览器因为开机本身就会改变系统状态而且你手动打开 Chrome 去点“历史记录”等于在证据上留了新的痕迹。所以标准做法是先把磁盘做成只读镜像或者至少对用户目录做一次规范的逻辑提取然后在副本上分析。但副本拿到手麻烦才开始。Chrome 的用户目录里有几十种文件光是 History、Cookies、Login Data、Web Data 这些 SQLite 库就够喝一壶更别说 Local Storage、Session Storage、IndexedDB 都是 LevelDB 格式Cache 又是另一套分片结构。手工逐个去解析工作量不是“多写几个脚本”能解决的。Hindsight 的角色就是在这一步出现给它一个 profile 目录路径它会自动识别里面的工件解析完成后输出一个.sqlite结果库和一个.html报告。我那次从拿到镜像副本到生成报告实际动手不到 20 分钟剩下的时间全花在看报告、核对时间线、补查周边文件上。1.2 它解决的是一类非常具体的需求先说清楚 Hindsight 适合谁。它面向的是数字取证、事件响应、企业内部调查这一类场景。如果你只是想“看看自己浏览器里存了什么”杀鸡用牛刀了但如果你需要在授权范围内分析一台机器、一个用户目录并且要给结论找依据它真的能省掉大量重复劳动。它做的事可以概括成三层自动枚举 profile 目录下的工件识别格式、版本、关联关系把零散的 SQLite、LevelDB、JSON 数据整理成统一结构的输出库尝试解密新版浏览器加密过的 Cookie 和登录凭据解密不了也会保留原始密文并做标记。顺带提醒一句这类工具只该用于你有明确授权或权限的设备。内部调查要有制度依据司法案件要走程序别因为工具好用就忘了边界。2. Hindsight 到底在翻哪些家底Chrome 用户目录的数据地图2.1 用户目录是浏览器的“记忆仓库”Chromium 系浏览器把几乎一切状态都放在一个叫 User Data 的目录下里面每个子目录对应一个用户配置通常是Default。不同系统的根路径差异不小我先列一下常用的后续实践会用到系统Chrome 默认 profile 路径WindowsC:\Users\用户名\AppData\Local\Google\Chrome\User Data\DefaultmacOS~/Library/Application Support/Google/Chrome/DefaultLinux~/.config/google-chrome/DefaultEdge 的话把上面的Google\Chrome换成Microsoft\Edge就行。注意路径里的空格和中文用户名命令行处理时一定要加引号。2.2 关键文件一张表说清楚我第一次用 Hindsight 的时候对里面各种文件到底有什么价值是晕的。后来自己整理过一张表现在看还是很实用文件/目录底层格式关键内容调查价值HistorySQLite访问的 URL、标题、访问次数、下载记录、搜索关键词核心时间线几乎所有案件先看这里CookiesSQLiteCookie 的域名、名称、值新版本加密账号关联、会话还原、站内身份判断Login DataSQLite表单保存的用户名、密码加密凭据发现配合解密可还原登录账号Web DataSQLite自动填充的姓名、地址、信用卡信息身份画像、收货地址等辅助证据BookmarksJSON手动收藏的书签意图佐证比如收藏了竞品资料页Preferences / Secure PreferencesJSON浏览器配置、扩展列表、启动参数扩展行为、是否有异常配置Local Storage / Session StorageLevelDB站点本地键值数据Web 应用状态、登录 token 残留IndexedDBLevelDBWeb 应用的结构化数据在线文档、聊天类应用的本地数据Cache磁盘分片文件缓存图片、脚本、响应头内容还原比如删除图片后仍有缓存这张表不只是给 Hindsight 用户看的理解每个文件的格式和价值才能读懂它输出的结果。2.3 存储格式与加密的入门常识如果只看表面Chrome 的“记录”无非是历史、密码、缓存。但落到技术上每种工件的存储机制完全不同这也是为什么 Hindsight 这种聚合型工具能成为刚需。SQLite 类History、Cookies、Web Data、Login Data 都是 SQLite 库适合用标准 SQL 查。问题在于不同表的字段含义差异大比如 History 里的时间字段不是 Unix 时间戳。LevelDB 类Local Storage、Session Storage、IndexedDB 用的是 LevelDB一层层.ldb和.log文件不带任何图形工具的话很难直接读。JSON 类Preferences、Secure Preferences、Bookmarks 是纯文本 JSON结构一目了然但字段非常多。加密问题从 Chrome 80 开始Cookie 的 value 默认用 AES-256-GCM 加密密钥来源和操作系统绑定。Windows 上密钥在 Local State 文件里、由 DPAPI 保护macOS 上密钥存在系统钥匙串里。Hindsight 的价值之一就是自动尝试这些解密流程省得你手动去调系统 API。理解这些之后再看 Hindsight 的输出就能明白为什么它既有urls、visits这种一眼懂的表也有cookies、logins这种需要结合解密结果判断的表。3. 完整体验从原始数据到取证报告的实操流程3.1 搭建环境Python、clone 仓库还是 pipHindsight 是 Python 项目依赖项不算多。我最常用的安装方式是 clone 源码这样能同时拿到命令行脚本、GUI 启动脚本和更新日志git clone https://github.com/obsidianforensics/hindsight.git cd hindsight python -m venv venv source venv/bin/activate # Windows 下用 venv\Scripts\activate pip install -r requirements.txt如果不想要 GUI、只想在自己的 Python 项目里调用PyPI 上也有pyhindsight包可以直接装。不过我建议第一次用还是 clone 源码因为仓库里如果有样例数据可以先拿样例跑一遍确认输出结构再上真样本。3.2 对“活机”直接取证 vs 对证据镜像取证有两种常见用法我分开说。场景 A分析原始 profile 目录。适合你自己有权限、机器也没在运行的场景比如把离职员工的用户目录完整拷贝出来之后在分析机上跑python hindsight_cli.py -i /home/evidence/Chrome/Default -o case01-i后面跟 profile 目录-o是输出文件的基础名。跑完会在当前目录生成case01.sqlite和case01.html。场景 B分析磁盘镜像里的 profile。这是更规范的做法。先用 FTK Imager、dd或类似工具把整块磁盘做成镜像挂载成只读卷再把镜像里的User Data\Default目录提取到分析目录然后同样用-i指向它。好处是原始镜像的哈希值可以先算好、存档保证链条完整。如果你的镜像里不是Default而是其他 profile 名比如Profile 1照实写路径就行。Hindsight 只关心这个目录是不是一个合法的 Chromium profile不要求目录名必须是Default。如果图省事想点点鼠标可以跑python hindsight_gui.py界面会问你三件事profile 路径、输出文件名、要不要尝试解密 Cookie。对于新手GUI 更容易理解整个流程对于批量任务命令行脚本更可控。3.3 看输出SQLite 结果库和 HTML 报告怎么看跑完之后我习惯先打开.sqlite看表结构再开 HTML 报告看叙事。你可以用 DB Browser for SQLite 或任何支持 SQLite 的客户端先执行.tables看看有哪些表。不同版本的表命名可能略有差异但大体上会覆盖历史、Cookie、下载、自动填充、访问时间线这些维度。HTML 报告是给“非技术同事”看的它有按时间倒序排列的访问记录、搜索关键词、下载列表甚至能把 URL 和页面标题整理成可读性很高的条目。我在内部调查交付时通常会把 HTML 报告导出成 PDF 附在报告里再补一段文字分析。SQLite 结果库则是给自己用的因为很多问题需要写 SQL 才能问。比如“这台机器上个礼拜访问过哪些登录页”或“哪些密码条目出现在离职交接给别人的邮箱里”这类跨表查询在 SQLite 里很快能得到答案。4. 真正动手后才发现容易翻车的几个点4.1 时间字段UTC 与本地时区的一笔账Chrome 原生 History 里的时间戳是 WebKit 格式也就是从 1601 年 1 月 1 日 UTC 起算的微秒数。真要读懂得先换成 Unix 时间SELECT u.url, u.title, datetime(v.visit_time / 1000000 - 11644473600, unixepoch) AS visit_time_utc, v.visit_duration FROM visits v JOIN urls u ON u.id v.url ORDER BY v.visit_time DESC LIMIT 30;这个-11644473600就是 1601 到 1970 之间的秒数差。Hindsight 的输出库通常已经把时间整理成可读格式但我见过不少版本对时间字段的命名不一致。所以拿到导出库之后先看表结构再看时间是不是 UTC。你本地是北京时间报告里显示 UTC 时间的话直接看会差 8 小时容易把时间线前后顺序搞错。我现在的习惯是报告里用 UTC 做基准写结论时再换算成本地时间。所有时间戳一律带上时区标注避免后面复核时吵架。4.2 解密失败不是工具不行而是上下文不对新版 Chrome 的 Cookie 加密依赖操作系统级的密钥。Windows 上 DPAPI 和当前登录用户绑定如果你在另一台机器上分析别人的 profile这部分的解密基本会失败Hindsight 会把密文原样留在结果里并标记。macOS 上也类似钥匙串里的密钥需要对应账户的登录状态才能读。这不是工具的 bug而是密钥上下文本来就不在你手上。我见过太多人一看到“decrypt failed”就怀疑工具坏了。拿到一个新的 profile第一步要看Local State文件里的版本标记判断 Cookie 用的加密方案是哪一代。如果是 v10 之后的标准就别奢望在没有用户上下文的情况下还原明文 Cookie老老实实把密文和域名记下来再去别的工件比如 Local Storage找未加密的 token。4.3 文件被占用与不完整拷贝的问题活机取证最忌讳的就是直接复制正在运行中的 Chrome 目录。History、Cookies、Local Storage 这些文件很可能被进程锁住复制出来的文件不完整Hindsight 解析时就会报一堆错误你根本分不清是数据缺失还是格式不识别。正确顺序是先结束浏览器进程再做逻辑提取如果出于响应需要不能关机、不能结束进程就用取证工具对磁盘做镜像而不是在资源管理器里 CtrlC。镜像能保证文件系统层面的快照一致性SQLite 内部也不会出现“读到一半文件还在写”的脏状态。另外LevelDB 类的工件对完整性非常敏感。Local Storage 目录里有一堆.log和.ldb文件如果只拷了部分文件Hindsight 解析出来的键值对会少很多而且不会明确告诉你少了哪些。所以做逻辑提取时整个 profile 目录必须完整复制别自作聪明只挑“看起来重要”的文件。4.4 解析结果里的“假阳性”与过度解读这是最容易被忽视的一环。Hindsight 报告里出现一个 URL不代表用户真的点开、浏览过这个页面。原因有几类后台扩展自动拉取接口会留下访问记录网站预加载、预渲染机制会在用户没打开页面的情况下产生 History 记录恶意软件或广告组件可能在后台请求 URL网页里的脚本请求统计接口也会让某些 URL 出现在下载/缓存里。所以在写结论时我通常会交叉验证这条 URL 在 History 里只有一条记录还是在访问时间线里连续出现访问耗时visit_duration是零点几秒还是几十秒下载行为要和文件系统里的落盘文件对上号。单一工件只能给线索多个工件互相印证才叫证据链。4.5 Chromium 换壳浏览器的“坑”Hindsight 支持多种 Chromium 系浏览器但换壳产品有时候会改路径、改数据库结构导致部分功能失效。我实测过 Edge 和 BraveEdge 基本无缝Brave 部分版本会在 Cookies 表里多出几个特有字段Hindsight 解析时可能忽略掉。Vivaldi 也有过类似问题。应对方式是不要因为“支持”就降低警惕跑完先看输出库的行数和原始库的行数对比。如果 History 表行数差一个数量级优先怀疑版本兼容问题而不是去怀疑用户“没怎么上网”。5. 进阶玩法把 Hindsight 当库调批量处理多台机器5.1 用 pyhindsight 写自动化脚本Hindsight 的核心解析逻辑本身是个 Python 包所以它不只能跑命令行。你可以写脚本批量处理多台机器、多个 profile把结果直接落进统一目录。一个很实用的场景是响应阶段批量巡检几十台机器判断哪些机器访问过可疑域名。把每台机器的 profile 借到中心目录后跑一个循环for dir in /evidence/profiles/*/; do name$(basename $dir) python hindsight_cli.py -i $dir -o /output/$name done跑完每台机器都有一个独立的.sqlite接下来就是写 SQL 做全局搜索了。如果你想把 Hindsight 直接嵌进自己的分析框架可以在脚本里 import pyhindsight 相关的模块以我安装的版本为例流程是实例化一个解析器、传入 profile 路径、执行parse()然后读取生成的 SQLite 结果。具体 import 路径因版本差异会变但设计思路是一致的解析逻辑是库CLI 只是薄薄一层调用壳。5.2 自定义 SQL 深挖结果库Hindsight 输出库最有价值的地方是它把一堆零散工件变成了可查询的关系表。我自己最常用的几段 SQL可以分享给你直接改着用。搜索关键词还原想知道用户搜过什么光看 URL 里的 query 参数太费劲直接查搜索词关联表SELECT k.term, u.url FROM keyword_search_terms k JOIN urls u ON u.id k.url_id ORDER BY k.id;下载行为内部泄密调查里下载动作经常是关键节点SELECT target_path, tab_url, start_time FROM downloads ORDER BY start_time DESC;这是 Chrome 原生 History 里的表start_time同样是 WebKit 时间格式查询时需要先换算和上面第 4.1 节一样。登录凭据研判如果解密成功Login Data 里的密码条目可以和 URL 关联起来分析。哪怕解不开光是“这台机器给哪个网站存过密码”这个事实本身也能说明账号关系。这些 SQL 在原生 Chrome 库里同样能用所以就算你不想装 Hindsight至少可以把 History 库的这几张表吃透。5.3 交叉验证别只信一个工具结尾我不做总结只分享一个救过我很多次的做法Hindsight 出的结果一定要和文件系统层面相互印证。比如报告里显示某条下载记录指向一个 ZIP 文件我会去Downloads目录或文件系统日志里找这个文件的实际创建时间、大小、SHA-256确认它是不是真的落盘了。又比如报告里出现的登录凭据我会回到系统日志、邮件记录里找对应的账号行为。数据之间越是对得上结论越扎实。有一次Hindsight 的 History 表里出现了一条“某某云盘网页版”的访问记录看起来像外发但我用文件系统时间线一查发现那条记录对应的visit_duration只有 300 毫秒而且 Cookies 表里根本没有这个域名的写入。最终判定是页面预拉取造成的假象差点冤枉了人。事后我给自己定了个规矩任何结论必须至少有两个独立工件背书否则只写“存在该行为”的风险提示不写“确认该行为”。这套流程走到今天我现在接手一个 profile 的标准动作就是先跑 Hindsight 出基础画像再拿 SQL 去问问题最后回到文件系统和时间线交叉验证。工具替你省掉的是体力活但判断力这关永远得自己过。
阅读完成 · 觉得有帮助?
咨询建站