shimcache是windows注册表中未公开格式的二进制值,c++无法直接读取因其非文件、无标准接口、结构随版本变化且需system权限+wow64绕过才能安全提取原始数据。

Shimcache 是什么,为什么 C++ 程序不能直接“读取”它
Shimcache(也叫 AppCompatCache)不是普通文件,而是 Windows 注册表中 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatibility\AppCompatCache 下的一个二进制值(REG_BINARY),内容经过紧凑编码、无文档化结构、随 Windows 版本变化极大。C++ 本身没有内置解析逻辑,更不存在像 fopen() 那样开箱即用的接口。
想用 C++ 处理 Shimcache,本质是三步:提取原始数据 → 解析二进制结构 → 转为可读记录。前两步必须自己实现或复用成熟解析逻辑,否则读出来只是一堆乱码字节。
如何用 C++ 安全读取 Shimcache 的原始二进制数据
必须以 SYSTEM 权限打开注册表键,且需绕过 Wow64 重定向(32 位程序默认看不到 64 位注册表视图)。关键点:
- 调用
RegOpenKeyEx()时传入KEY_WOW64_64KEY标志,否则在 64 位系统上可能读空或失败 - 目标键路径中的
Session Manager属于受保护子树,普通用户权限会返回ERROR_ACCESS_DENIED;必须以提升权限运行(UAC 提权或 SYSTEM 上下文) -
AppCompatCache值名实际存在多个变体:AppCompatCache(Win7)、AppCompatCacheEx(Win8+)、部分版本还用AppCompatCacheLayout,需按 Windows 版本试探读取 - 建议先用
RegQueryValueEx()传NULL缓冲区获取真实大小,再分配内存读取,避免缓冲区溢出
解析 Shimcache 二进制结构的现实选择
没有标准头定义,微软从未公开格式。不同 Windows 版本(Win7/8.1/10/11)的结构差异体现在:缓存头部长度、条目偏移计算方式、路径字符串是否 Unicode / 是否带 NULL 截断、是否存在时间戳字段等。硬写解析器极易崩溃或漏数据。
更可行的做法是复用已验证的开源逻辑:
- 参考 FireEye 的 flare-wmi 或 libesedb 项目中对 Shimcache 的解析片段(注意其 license)
- 直接调用 Python 的
python-registry+shimcache-parser库做后端,C++ 通过std::system()或管道调用脚本(适合离线分析场景) - 若坚持纯 C++,至少应按 Windows Build 号分支处理:用
GetVersionEx()或RtlGetVersion()获取dwBuildNumber,再匹配对应解析逻辑(例如 Build 7601=Win7 SP1,19044=Win10 21H2)
常见错误与不可忽视的细节
很多 C++ 实现卡在看似简单的地方:
- 把
AppCompatCache当成字符串值读取(REG_SZ),实际是REG_BINARY—— 导致RegQueryValueEx()返回ERROR_MORE_DATA或截断 - 忽略路径字符串的“packed”编码:Win7 中路径间用单个
\0分隔,Win10 后改为双\0\0,且末尾不保证有终止符 - 未校验缓存头部的 Magic 字段(如 Win7 是
0x00000000,Win10 是0x44616D69即 “DamI”)就盲目解析,结果全错 - 在 x64 进程中用
sizeof(SHIMCACHE_HEADER)计算偏移,但结构含指针成员(如某些逆向版本误加PVOID),导致 32/64 位布局不一致
真正稳定读取 Shimcache 不在于 C++ 写得多漂亮,而在于能否准确识别当前系统的缓存布局并严格遵循其二进制语义。跳过版本适配直接套用旧代码,大概率得到空列表或访问违规。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











