Shimcache (AppCompatCache)¶
In one sentence
The Application Compatibility Cache records executables the shim engine has looked at — full path, the file's $STANDARD_INFORMATION last-modified time, and (on Win7/8 only) an "executed" flag. It proves a file existed at that path; execution is likely but not guaranteed, and it works on servers where Prefetch is off.
What it tells you¶
- Full path of executables (and some scripts/DLLs) that were executed or browsed to in Explorer (Explorer inspects files to shim them).
- The file's last modification time (
$SI) at the moment it was cached — not the execution time. - Ordering: entries are stored most-recent-first, so position is a relative timeline even without execution timestamps.
- Win7 / Win8: an Insert flag / Execution flag (
CSRSSflag) that indicates actual execution. - Windows 10/11: no execution flag, no insertion timestamp. Existence + order only.
Three things people get wrong
- The timestamp is the file's modification time, not when it ran.
- On Windows 10/11 there is no execution flag — an entry can come from Explorer merely rendering the icon of a folder containing the EXE.
- The cache lives in memory and is only written to the registry on shutdown/reboot (or when it fills). A live system's
SYSTEMhive is stale; a system that never rebooted after the attack may not have the entries yet. Memory forensics (volatility3 windows.shimcachemem) gets the live version.
Location¶
| Item | Path / Key |
|---|---|
| Registry (Win7+) | SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache\AppCompatCache (binary value) |
| Registry (XP) | SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatibility\AppCompatCache |
| Offline hive | C:\Windows\System32\config\SYSTEM (+.LOG1/.LOG2). CurrentControlSet → check Select\Current to pick ControlSet001 vs 002 |
| Max entries | XP: 96 · Win7/8: 1024 · Win10/11: 1024 (older builds) — oldest fall off the end |
Multiple ControlSet00N keys may each hold a cache — parse all of them; the non-current one is an older snapshot.
Format by OS¶
| OS | Header / signature | Timestamp | Exec flag |
|---|---|---|---|
| XP 32-bit | 0xDEADBEEF |
Last mod + last update time | — |
| Vista / 2008 | 0xBADC0FFE |
Last mod | Insert flag |
| Win7 / 2008 R2 | 0xBADC0FFE |
Last mod | Yes (CSRSS insert flag) |
| Win8 / 2012 | 00ts per-entry tag |
Last mod | Yes |
| Win8.1 / 2012 R2 | 10ts |
Last mod | Yes |
| Win10 / 11 / 2016+ | 10ts, header offset 0x30 (0x34 on Creators Update+) |
Last mod | No |
How to collect¶
Windows.Registry.AppCompatCache
How to parse¶
# Offline hive → CSV; -t sorts by timestamp, -c picks a ControlSet (default: all)
AppCompatCacheParser.exe -f C:\Case\SYSTEM --csv C:\Case\out --csvf shimcache.csv
# Live system
AppCompatCacheParser.exe --csv C:\Case\out
Columns: ControlSet, CacheEntryPosition (0 = most recent), Path, LastModifiedTimeUTC, Executed (Win7/8 only), Duplicate.
Analysis tips¶
Use the position, not the timestamp, for sequencing
Entry 0 is the most recently shimmed. If mimikatz.exe is at position 3 and psexesvc.exe at position 4, the attacker ran PsExec, then Mimikatz — regardless of what their modification times say. Insertion order is your timeline; the timestamp just tells you how old the file was.
- Server triage: Prefetch is disabled on Server SKUs, so Shimcache + Amcache + 4688 + BAM is your execution story.
- Path anomalies:
\??\C:\Users\Public\,\Device\HarddiskVolumeShadowCopy, UNC paths (\\server\share\tool.exe), removable drives — all worth pulling. - Timestomping detection: if the Shimcache last-mod time is newer than the file's current
$SImodification time, someone rolled the timestamp back after execution. - Deleted tools stay in the cache until pushed out by 1024 newer entries.
- Explorer noise on Win10: browsing
C:\Tools\in Explorer can shim every EXE inside. Corroborate with Prefetch / Amcache / 4688 before claiming execution. - Duplicates across ControlSets are normal; a path present in
ControlSet001but missing in002shows it appeared between the two snapshots. - Anti-forensics: clearing requires modifying a binary registry value (rare) or preventing the flush by never rebooting cleanly — a system that crashed rather than rebooted may have lost the in-memory entries.
Timeline / correlation¶
| Question | Cross-check with |
|---|---|
| Did it really execute? | Prefetch (workstations), Security 4688, Sysmon 1, Amcache, BAM/DAM |
| What was the file? | Amcache SHA-1 |
| When was it dropped? | $MFT / USN — $FN creation time vs Shimcache last-mod |
| Live vs. on-disk cache differ? | Memory image shimcachemem vs SYSTEM hive |