TL;DR. 第一个 u32 = 头部大小,通常 0x30 到 0x36。在该偏移处,每条条目以 4 字节 magic 10ts 开头,后接 12 字节头部和可变长度主体:UTF-16LE 路径(带长度前缀,无空终止)、FILETIME mtime、末尾数据 blob。执行 flag 在 Windows 10 中被移除。
自 XP 以来每一个 Windows 版本都发布过不同的 AppCompatCache 布局。Windows 10/11 变体是调查人员日常见得最多的,一旦你知道陷阱在哪里,它也是最宽容的。这是我第一次试着手写 parser 时希望能拥有的那份走查。
你要解析的 blob
从以下位置的二进制 value 开始:
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache\AppCompatCache
从 SYSTEM hive 中提取(见 ShimCache 的存放位置)。你得到的是一个单独的 blob,通常为几十到几百 KB。先是一个小的头部,然后是一连串条目,每条以一个已知的 magic 开头。
头部
blob 的前 4 个 little-endian 字节是第一条条目的偏移。在 Windows 10/11 上,这通常是 0x30、0x34、0x35 或 0x36,取决于构建。一些 hive 在此处带有 0x80,表示一个仍然使用 10ts / 00ts 条目签名的 Windows 8.x 布局。
不要硬编码头部大小。读取第一个 u32,并验证该偏移处的字节是已识别条目的起点。如果在声明的偏移处既未出现 10ts 也未出现 00ts,向前扫描寻找 10ts 并从那里继续。真实 hive 有时会发布略偏离规范的数据,一个在首字节不匹配时就退出的 parser,就是一个会输掉案件的 parser。
一条 Windows 10/11 条目,逐字节
每条现代条目以 4 字节签名 10ts(0x31 0x30 0x74 0x73)开头。完整布局:
| 偏移 | 大小 | 字段 |
|---|---|---|
| 0x00 | 4 | Magic,"10ts" |
| 0x04 | 4 | 序列号 / 未知,通常被忽略 |
| 0x08 | 4 | 条目数据大小,紧随该字段之后的字节数 |
| 0x0C | 2 | 路径大小,字节数(UTF-16LE) |
| 0x0E | N | 路径字节,UTF-16LE,无终止符 |
| 0x0E + N | 8 | 最后修改时间,FILETIME(自 1601-01-01 UTC 起的 100 纳秒数) |
| 0x16 + N | 4 | 尾随数据大小 |
| 0x1A + N | M | 尾随数据,通常为空或很小 |
条目总大小为 0x0C + entry_data_size。下一条条目紧随其后开始。
两个实用要点:
- 路径是 UTF-16LE,没有空终止。 使用路径大小字段。不要一直读到遇到零字节,否则你会吞掉下一条条目的头部。
FILETIME是文件的$STANDARD_INFORMATIONmtime。 不是程序运行的时刻。不是该条目被插入的时刻。是在检查时直接从 NTFS 复制过来的文件 mtime。执行证明文章 解释了为什么这一点很重要。
Windows 10 移除的东西
更早的 Windows 版本在每条条目中打包了一个 Executed flag。Win7 和 8.x 时代的分析师学会了读它。Windows 10 移除了它。Windows 11 也没把它放回来。缓存里没有任何办法告诉你一个二进制是否真的运行过。你需要 Prefetch、AmCache 或 EVTX / Sysmon。
旧版本的字段布局(XP 到 8.1)见 遗留 ShimCache 格式。
实战中的解析
一个能通过评审的 parser:
- 在头部声明的偏移处验证 4 字节 magic。
- 通过读取条目数据大小字段并前进来迭代条目。
- 使用长度前缀以 UTF-16LE 解码路径。
- 将
FILETIME转换为下游工具偏好的时间戳格式。Unix 毫秒很方便。ISO 8601 UTC 才是报告真正想要的。 - 暴露检测到的 OS 格式标签(Windows 10/11 vs 8.x vs 8.0)供下游过滤。
- 在读取该 value 之前重放
SYSTEM.LOG1和SYSTEM.LOG2。如果你的 parser 不做这件事,那它读到的就是过时的 hive。
开源的 Shimcache Parser 用 Rust 实现了上述第 1 到第 5 步,并以 WebAssembly 形式交付到你的浏览器。它读取单个 hive 文件,不重放事务日志,因此 dirty 的 hive 请先用 rla.exe 或 Registry Explorer 处理。没有服务器,没有上传。当 SYSTEM hive 来自受监管环境时尤为有用。
延伸阅读
- Eric Zimmerman 的 AppCompatCacheParser:覆盖各种 Windows 变体的金标准 C# 实现。
- Mandiant 的 Shim Cache Parser:原始 Python proof-of-concept,适合作为格式交叉参考。
- Velociraptor
Windows.Registry.AppCompatCache:用于活体采集的 VQL 工件。 - Ø Security 的 Windows 10/11 AppCompatCache deep dive:对现代布局最详尽的公开记述。