Chapter 8

Shimcache and Amcache

Shimcache (AppCompatCache) and Amcache.hve record executables that the Windows application compatibility subsystem has seen — covering servers where Prefetch is disabled and providing SHA-1 hashes for attribution even when the binary is deleted.

Scenario

You're investigating a compromised Windows Server 2022 domain controller. Prefetch is disabled — servers don't use it. The attacker dropped an implant as wuauclt.exe in a temp directory and ran it, then deleted both the binary and the temp folder. EDR telemetry shows the process creation but not the file hash (the file was deleted before EDR scanned it). Amcache.hve has the entry — with the SHA-1 hash of the binary, the first run timestamp, and the full path. VirusTotal hit on the hash confirms it's a known Cobalt Strike stager. Shimcache has the AppCompatCache entry too — with the file's last-modified timestamp at the time it was seen. Without Amcache and Shimcache, you'd have the process name but not the hash that confirms what it actually was.

Shimcache (AppCompatCache)

Shimcache is stored in the SYSTEM hive and records executables that Windows has checked for application compatibility issues. It exists on both workstations and servers.

  Shimcache Location and Contents
  ═══════════════════════════════════════════════════════════════════

  Registry location:
    HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache

  What it records per entry:
    ├── File path (full path of the executable)
    ├── File size
    ├── Last modified timestamp of the file (at time of first encounter)
    └── Execution flag (Windows XP-7 only; Windows 8+ dropped this flag)

  Key limitation on Windows 8+:
    The "was executed" flag was removed. An entry in Shimcache means the
    system "saw" the file — either it was run OR it was merely present
    on disk (e.g., copied there but never run). This distinction matters:
    Shimcache presence = file existed at this path.
    Shimcache + Amcache = file existed AND was executed (corroboration).
    Shimcache + Prefetch = strongest execution evidence combination.

  Capacity: approximately 1,024 entries (LIFO — oldest pushed out first)
  Persistence: stored in SYSTEM hive — survives reboots
  Written: cache is NOT written to registry until system shutdown or
           a forced flush. Live Shimcache in memory may differ from
           what's in the SYSTEM hive on disk.
Common mistake: treating Shimcache as execution proof on Windows 10+

On Windows 8 and later, the "executed" bit was removed from Shimcache entries. A file appearing in Shimcache means it was seen by the OS — not necessarily that it ran. Malware droppers that copy files to disk but haven't run yet appear in Shimcache. Forensic reports that say "Shimcache confirms execution" on Windows 10 are technically incorrect. Use Shimcache to establish that a file existed at a path and timestamp, then corroborate execution with Prefetch (if enabled), Amcache (execution timestamp), or Event 4688 (process creation). The combination is solid evidence; Shimcache alone is not.

Batchshimcache-parse.bat
:: Parse Shimcache with AppCompatCacheParser (Eric Zimmermann)

:: From offline SYSTEM hive (e.g., from KAPE collection)
AppCompatCacheParser.exe ^
  -f "D:\evidence\C\Windows\System32\config\SYSTEM" ^
  --csv "D:\analysis\shimcache" ^
  --csvf shimcache.csv

:: Output columns:
::   ControlSet        — which ControlSet the cache came from
::   CacheEntryPosition— order in cache (0 = most recently added)
::   Path              — full path of the executable
::   LastModifiedTimeUTC — last modified time of the file when cached
::   Executed          — True/False (Windows XP-7 only; empty on 8+)

:: Tip: lower CacheEntryPosition = more recently executed/seen
:: Entry at position 0 was the last thing cached before the last flush

Amcache.hve

Amcache is a more modern and more detailed execution tracking mechanism, present on Windows 8+ systems. Unlike Shimcache, Amcache does record actual execution (first run timestamp) and includes the SHA-1 hash of the binary.

  Amcache.hve Location and Contents
  ═══════════════════════════════════════════════════════════════════

  File location: C:\Windows\AppCompat\Programs\Amcache.hve

  Key sections in Amcache:
    Root\File\                    — Per-volume per-file execution records
    Root\Programs\                — Installed application records
    Root\DevicePnp\               — PnP device history
    Root\DriverBinaries\          — Loaded driver records
    Root\InventoryApplicationFile\— Application inventory

  Per-file record contents:
    ├── FileId (SHA-1 hash prefixed with "000000")
    ├── FullPath — full path of the executable
    ├── LastModifiedTimeUTC — file's last modified time
    ├── LinkDate — PE compilation timestamp (from PE header)
    ├── LongPathHash
    ├── ProgramId — links to program entry
    ├── Publisher — binary's publisher from PE resources
    ├── Size — file size
    └── FileVersion — PE version resource

  The SHA-1 hash is the key forensic value — it enables:
    1. VirusTotal lookup even after the file is deleted
    2. Attribution to known malware families
    3. Cross-host correlation (same hash on multiple systems = same tool)
Batchamcache-parse.bat
:: Parse Amcache.hve with AmcacheParser (Eric Zimmermann)

AmcacheParser.exe ^
  -f "D:\evidence\C\Windows\AppCompat\Programs\Amcache.hve" ^
  --csv "D:\analysis\amcache" ^
  -i on

:: -i on: include associated program records (more context)
:: Output creates multiple CSVs:
::   amcache_UnassociatedFileEntries.csv  — standalone file entries
::   amcache_ProgramEntries.csv           — program/application entries
::   amcache_AssociatedFileEntries.csv    — files tied to programs
PowerShellamcache-vt-lookup.ps1
# Look up Amcache SHA-1 hashes against VirusTotal
# Requires VT API key (free tier: 4 lookups/min, 500/day)

param(
    [string]$AmcacheCSV = "D:\analysis\amcache\amcache_UnassociatedFileEntries.csv",
    [string]$VTApiKey   = "YOUR_VT_API_KEY",
    [datetime]$AfterDate = "2026-09-01"
)

$entries = Import-Csv $AmcacheCSV

# Filter to recently-seen executables in suspicious paths
$suspects = $entries | Where-Object {
    $_.FullPath -match "\\(Temp|tmp|Public|ProgramData|Users\\[^\\]+\\AppData\\Roaming)\\" -and
    [datetime]$_.LastModifiedTimeUTC -gt $AfterDate
}

foreach ($entry in $suspects) {
    # Amcache FileId is in format "000000" + sha1
    $sha1 = $entry.FileId -replace "^000{6}",""

    if ($sha1.Length -ne 40) { continue }

    $url = "https://www.virustotal.com/api/v3/files/$sha1"
    $headers = @{ "x-apikey" = $VTApiKey }

    try {
        $resp = Invoke-RestMethod -Uri $url -Headers $headers -ErrorAction Stop
        $detections = $resp.data.attributes.last_analysis_stats.malicious
        $total = ($resp.data.attributes.last_analysis_stats.PSObject.Properties.Value | Measure-Object -Sum).Sum

        if ($detections -gt 0) {
            Write-Host "[MALICIOUS] $($entry.FullPath)"
            Write-Host "  SHA-1: $sha1"
            Write-Host "  Detections: $detections / $total"
        }
    } catch {
        Write-Host "[NOT FOUND in VT] $sha1 — $($entry.FullPath)"
    }

    Start-Sleep -Milliseconds 250  # respect free-tier rate limit
}

Shimcache vs Amcache: When Each Helps

SituationUse ShimcacheUse Amcache
Server investigation (Prefetch disabled)Yes — available on all Windows including ServerYes — present on Windows 8+/Server 2012+ including Server 2022
Need execution timestampNo — no execution timestamp in Shimcache (Windows 8+)Yes — Amcache records first-run time in KeyLastWriteTime of the file record
Need binary hash for VT lookupNo — no hash in ShimcacheYes — SHA-1 hash recorded
Binary was deletedPath and last-modified time still in cachePath + hash still in Amcache (until Amcache entry is pruned)
Confirm file existed at a specific pathYes — path recordedYes — path recorded with more context
PE compilation timestampNoYes — LinkDate field in Amcache

Correlating Shimcache and Amcache with Other Artifacts

  Execution Evidence Correlation Matrix
  ═══════════════════════════════════════════════════════════════════

  Strongest execution evidence = multiple sources agree:

  Artifact          | File existed? | Was run? | Timestamp | Hash
  ─────────────────────────────────────────────────────────────────
  Shimcache (W10+)  |     YES       |    ?     |  Modified |  No
  Amcache.hve       |     YES       |   YES    |  First run| SHA-1
  Prefetch          |     YES       |   YES    | All 8 runs|  No
  Event 4688        |      –        |   YES    |  Exact    |   –
  EDR process log   |      –        |   YES    |  Exact    | Yes
  ─────────────────────────────────────────────────────────────────

  Investigation workflow:
    1. Shimcache: file path seen → suggests existence/execution
    2. Cross-check Amcache: confirms execution, adds hash
    3. VT lookup on hash → attribution to malware family
    4. Cross-check Prefetch: confirms run times
    5. Cross-check Event 4688/EDR: exact command line, parent process

  When Shimcache says "yes" but Amcache says nothing:
    File was copied to disk but may not have run (or Amcache entry aged out)
    Consider: could the attacker have the file staged but not yet executed?

Q & A

Q: How do you get the exact first execution time from Amcache when the CSV output doesn't show it directly?

AmcacheParser's CSV output includes a KeyLastWriteTime column for file entries — this is the LastWriteTime of the registry key for that file record in Amcache.hve, which corresponds to when Windows first recorded the file's execution. This is the closest proxy to "first executed at this time." It's not guaranteed to be the exact execution timestamp in all cases (the key could be updated for other reasons), but in the absence of other evidence it's the best execution timestamp available. Cross-reference it with the corresponding Prefetch file's first run timestamp if Prefetch is available — if they're within minutes of each other, your confidence in the execution time is high. If they diverge significantly, investigate why: one may have been modified.

Q: The attacker deleted Amcache.hve. Is it recoverable?

Amcache.hve is a registry hive stored as a file in the AppCompat directory. If it was deleted, the MFT will show it as deleted (IsDeleted=True), and the data may be recoverable through VSS (Volume Shadow Copies — ch16) if a snapshot predates the deletion. Additionally, the ESE database transaction log files (edb.log in the same directory) may contain partial Amcache data. If VSS is unavailable and the file data clusters have been overwritten, a full disk image is needed and you'd attempt file carving for ESE database fragments. In practice, most attackers don't specifically target Amcache for deletion — it's less widely known than Prefetch. If you see a missing Amcache.hve on a system that should have it, that absence itself is suspicious and worth documenting as an anti-forensics indicator.