A forensic tool for parsing the Windows 10/11 ShimCache (AppCompatCache) registry artifact, producing enriched CSV output with file metadata, Authenticode signatures, PE compile timestamps, SHA-256 hashes, and original filenames for use in malware triage and incident response.
- What is ShimCache?
- Why it Matters Forensically
- Features
- Building
- Usage
- Options
- Output Columns
- Examples
- Forensic Notes
- Limitations
The ShimCache, formally known as the Application Compatibility Cache, is a Windows subsystem component that tracks executable files encountered by the operating system. It is stored in the registry at:
HKLM\SYSTEM\ControlSet001\Control\Session Manager\AppCompatCache\AppCompatCache
Windows writes an entry to the cache whenever it observes an executable during process creation, directory enumeration, or certain API calls. The cache persists across reboots and is one of the most reliable sources of evidence that a particular binary existed on a system, even if the file has since been deleted.
- Proves file existence — an entry confirms a binary was present on disk, even if it has been deleted.
- Approximate timeline — the
LastModifiedtimestamp reflects the file's last-write time at the moment Windows cached it, useful for building execution timelines. - Execution indicator — some Windows builds store an execution flag, indicating whether the binary was actually launched.
- Malware detection — combining the cache path with enriched metadata (signature status, original filename, PE compile time) surfaces renamed, unsigned, or anomalous binaries that would otherwise blend in.
| Feature | Detail |
|---|---|
| Live registry parsing | Reads directly from HKLM\SYSTEM on the current machine |
| Offline hive parsing | Loads an external SYSTEM hive file via RegLoadKey |
| Multi-ControlSet support | Parses all ControlSets found, or a specific one with -c |
| Authenticode verification | Reports Signed, Unsigned, or FileNotFound per binary |
| File metadata | Size, creation time, and last-access time from the filesystem |
| PE compile time | COFF TimeDateStamp from the PE header (compiler/linker time, not filesystem) |
| SHA-256 hashing | Full-file hash for VirusTotal pivoting and threat-intel lookups |
| OriginalFilename | Extracted from the PE Version Info resource — does not change when a file is renamed |
| CSV output | UTF-8 with BOM for clean Excel compatibility |
| Sort by timestamp | Optional newest-first ordering with -t |
- OS: Windows 10 or Windows 11
- Privileges: Administrator (required for live registry access and offline hive loading)
- Compiler: MSVC (Visual Studio 2019+) or MinGW-w64 with C++17 support
- Dependencies: All system libraries no third-party dependencies
cl /EHsc /std:c++17 /O2 AppCompatCacheParser.cpp ^
/link advapi32.lib wintrust.lib crypt32.lib shlwapi.lib version.lib
g++ -std=c++17 -O2 AppCompatCacheParser.cpp -o AppCompatCacheParser.exe ^
-ladvapi32 -lwintrust -lcrypt32 -lshlwapi -lversion
The
#pragma comment(lib, ...)directives in the source handle library linking automatically under MSVC, so you can also build directly from Visual Studio without modifying project settings.
AppCompatCacheParser.exe --csv <output_directory> [options]
--csv is the only required argument. All other options are optional.
| Flag | Description |
|---|---|
-f <path> |
Path to an offline SYSTEM hive file. Omit to use the live registry. |
-c <num> |
Parse only the specified ControlSet number (e.g. 1, 2). Default: all. |
-t |
Sort CSV output by LastModified descending (newest first). |
--csv <dir> |
Output directory for the CSV file. Created automatically if it does not exist. (Required) |
--csvf <file> |
Override the auto-generated filename. Default: YYYYMMDD_HHMMSS_AppCompatCache.csv |
--nosig |
Skip all on-disk enrichment (signature, metadata, PE time, SHA-256, OriginalFilename). Use when the target files are not present on the analysis machine. |
--debug |
Print verbose diagnostic output to stderr showing raw offsets and parse decisions. |
-h / --help |
Display help and exit. |
| Column | Description |
|---|---|
ControlSet |
The registry ControlSet the entry was read from (e.g. 1, 2). |
CacheEntryPosition |
Zero-based insertion order. Lower numbers were inserted more recently — the cache is last-in, first-out (LIFO). |
Path |
Full NT path of the executable as stored in the cache. |
LastModified |
The file's last-write timestamp recorded by Windows at cache-insertion time (UTC). |
Executed |
Execution flag: Yes (flag set), No (flag clear), or N/A (not present in this entry). Note: absence of the flag does not conclusively prove the file was never run. |
Signature |
Authenticode result: Signed, Unsigned, or FileNotFound. |
FileSize |
File size in bytes at the time of enrichment. |
CreationTime |
File creation timestamp from the filesystem (UTC). |
LastAccessTime |
File last-access timestamp from the filesystem (UTC). |
PECompileTime |
The TimeDateStamp field from the PE COFF header (UTC). This is set by the compiler or linker, not the filesystem. A mismatch between this and LastModified can indicate timestomping or a repacked binary. |
SHA256 |
Hex-encoded SHA-256 hash of the full file. Use for VirusTotal lookups or internal threat-intel correlation. |
OriginalFilename |
The OriginalFilename value from the PE Version Info resource. This is compiled into the binary and does not change when the file is renamed. A mismatch between this and the filename in Path is a strong indicator of a renamed or masquerading executable. |
Parse the live registry on the current machine:
AppCompatCacheParser.exe --csv C:\Output
Parse live registry, sort results newest first:
AppCompatCacheParser.exe --csv C:\Output -t
Parse only ControlSet001:
AppCompatCacheParser.exe --csv C:\Output -c 1
Parse an offline SYSTEM hive acquired from a forensic image:
AppCompatCacheParser.exe -f D:\Evidence\SYSTEM --csv C:\Output
Offline parse without file enrichment (faster, no disk reads for target files):
AppCompatCacheParser.exe -f D:\Evidence\SYSTEM --csv C:\Output --nosig
Custom output filename:
AppCompatCacheParser.exe --csv C:\Output --csvf suspect_shimcache.csv
Full debug run with custom filename:
AppCompatCacheParser.exe --csv C:\Output --csvf suspect.csv --debug
OriginalFilename as a rename detector
The OriginalFilename field in the PE Version Info resource is embedded at compile time. When an attacker renames a malicious binary to impersonate a legitimate process (e.g. renaming a payload to svchost.exe), the OriginalFilename field will still contain the original name the binary was compiled with. Comparing OriginalFilename against the filename component of Path is one of the fastest triage checks for masquerading malware.
PECompileTime vs LastModified
The PECompileTime is the TimeDateStamp in the PE COFF header and reflects when the binary was compiled or linked. Legitimate software from major vendors typically has a compile time that predates the file's LastModified time. A PECompileTime that is significantly newer than a well-known binary's expected release date, or that matches the LastModified exactly, can indicate the binary was repacked, patched, or had its timestamp manipulated (timestomping).
Cache insertion order
The ShimCache is a LIFO structure. The entry at position 0 was the most recently inserted. Sorting by CacheEntryPosition ascending gives you the most recently observed executables first, which is useful for narrowing down activity around a known incident window.
Unsigned binaries outside system directories
Legitimate Windows and application binaries are virtually always signed. An Unsigned result for a binary located outside %SystemRoot% or %ProgramFiles% especially in user-writable locations like %APPDATA%, %TEMP%, or user profile directories warrants immediate investigation.
--nosig for offline analysis
When analyzing a hive acquired from a different machine, the file paths recorded in the cache will not exist on the analysis workstation. Use --nosig to skip enrichment in this scenario and avoid false FileNotFound results in the Signature column.
- Only the Windows 10 / Windows 11 ShimCache format (
10tsentry signature) is supported. - SHA-256 computation reads the entire file sequentially; large binaries will increase total runtime.
- The
Executedflag is not consistently populated across all Windows 10/11 builds its absence is not conclusive evidence of non-execution. - Authenticode verification uses the local certificate store and does not perform online revocation checks (
WTD_REVOKE_NONE). A certificate that has been revoked since the binary was signed may still report asSigned. - Must be run as Administrator. Standard user accounts do not have the privileges required by
RegLoadKey(SE_RESTORE_NAME/SE_BACKUP_NAME).