ADFIRWMC - 5.1 Did It Run? Evidence of Execution
Welcome back. It has been a minute.
In Chapter 3 we built a list of files of forensic interest and added them to our collection script. In Chapter 4 we ran strings across everything to get our bearings. Now it is time for the structured part: actually parsing the artifacts and making them answer questions.
Chapter 5 is Windows disk artifact analysis, and it is big enough that I am breaking it into parts:
- 5.1 Did It Run? Prefetch, Amcache, and ShimCache (you are here)
- 5.2 Who Ran It? User registry hives and event logs
- 5.3 What Did They Open, and From Where? Shortcuts and jump lists
- 5.4 Where Did It Come From? USB and external devices
- 5.5 Putting It All Together One timeline to rule them all
We are going to use the same scenario for every part.
The Scenario
Your antivirus console lights up Thursday morning. It quarantined EVILFILE.EXE from C:\Users\bob\AppData\Local\Temp\ on Bob’s workstation. The AV says it detected the file on Thursday, but the file’s timestamps say it landed on Tuesday. Your boss walks over and asks the only question anyone ever asks first:
“Did it run?”
“The file was there” is not an answer to that question. Lots of evil sits on disk and never executes. Lots of evil executes and then deletes itself. To answer the question you need artifacts that record execution, and you need to know exactly what each one does and does not prove.
Existed vs. Executed
Before we touch a single tool, burn this into your brain. Evidence falls into three buckets:
- The file existed. It was on disk at some point. ($MFT, USN Journal)
- Windows knew about it. The OS looked at it, inventoried it, or showed it in a folder. That does not mean it ran.
- The file executed. Something actually launched it.
Most of the arguments I have seen between analysts (and most of the bad reports I have read) come from treating bucket 2 like bucket 3. Each artifact below gets labeled with its bucket.
Tools Used
- Eric Zimmerman’s Tools: PECmd, AmcacheParser, AppCompatCacheParser, Registry Explorer, and Timeline Explorer
- PowerShell
Eric’s tools are free, they are maintained, and they are the de facto standard for this stuff. If you only take one thing from this chapter, take his tools.
Collection
Good news: if you followed along in Chapter 3, you already collected everything in this part. Prefetch, Amcache, and the SYSTEM hive are all in the collection script.
One fix. Registry hives on a live system are usually “dirty,” meaning recent changes are still sitting in the transaction logs (.LOG1 and .LOG2) and have not been written into the hive yet. The SYSTEM hive line from Chapter 3 already grabs everything in the config folder, but the Amcache line only grabs the hive itself. Swap it for this:
- Line to add to collection script:
$filesigs += '^c:\\Windows\\AppCompat\\Programs\\Amcache\.hve(\.LOG[12])?$'
Keep the transaction logs in the same folder as the hive. Eric’s tools will notice them and replay them for you.
Prefetch
Bucket 3: Executed. This is your strongest evidence of execution on a workstation.
What It Is
Prefetch is a performance feature. When a program launches, Windows watches what files it loads in roughly the first ten seconds and writes that down, so the next launch can preload everything and start faster. The side effect is that Windows keeps a diary of what ran, when, and how often.
- Location:
C:\Windows\Prefetch\ - File name:
EXECUTABLENAME-HASH.pf, for exampleEVILFILE.EXE-1A2B3C4D.pf - The hash is calculated from the executable’s path. The same program run from two different folders gets two different .pf files. If you ever see two
SVCHOST.EXEprefetch files and one hash you do not recognize, start asking questions.
What You Get
- The executable name
- Run count
- Last run time, and on Windows 8 and later, the last eight run times
- Volume information (serial number and creation time) for where it ran from
- A list of the files and directories referenced during that first ten seconds
That last one is criminally underrated. It shows you the DLLs it loaded, the config files it read, and sometimes the files it dropped.
The .pf file’s own timestamps help too. The file is created a few seconds after the first run and modified a few seconds after the most recent run.
Gotchas
- Prefetch is disabled by default on Windows Server. No .pf files on a server is normal, not suspicious.
- It can be turned off on workstations too, through the
EnablePrefetchervalue underHKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters. If a workstation has no prefetch, check that value. - There is a cap of 1,024 files on Windows 8 and later. The oldest entries roll off. On a busy machine, “no prefetch file” does not mean “never ran.”
- Prefetch files are compressed on Windows 10 and later. The strings and grep tricks from Chapter 4 will not work on raw .pf files. Parse them first.
Parsing It
Point PECmd at the whole folder and get CSVs back:
PECmd.exe -d "C:\Cases\BOBPC\Prefetch" --csv "C:\Cases\BOBPC\Out"
Or one file with -f. Open the CSV in Timeline Explorer, or slice it with PowerShell. Here is my favorite trick: search every program’s loaded-file list for anything that touched a user’s Temp, Downloads, or AppData folders.
Import-Csv "C:\Cases\BOBPC\Out\*_PECmd_Output.csv" |
Where-Object { $_.FilesLoaded -match '\\(TEMP|DOWNLOADS|APPDATA)\\' } |
Select-Object ExecutableName, RunCount, LastRun |
Sort-Object LastRun
That usually finds the bad thing and whatever helped it.
Back to Bob
PECmd shows EVILFILE.EXE with a run count of 3. The first run lines up with Tuesday afternoon, and the most recent run is Wednesday morning, a full day before the AV woke up. The files referenced include a DLL in Bob’s AppData\Roaming folder that nobody mentioned.
So yes, it ran. Three times. And now we have a second file to go find.
Amcache
Bucket 2: Windows knew about it. Not proof of execution by itself, but it gives you something Prefetch does not: a hash.
What It Is
Amcache is a registry hive that the Application Experience service uses to inventory programs on the system. It replaced RecentFileCache.bcf, which is a Windows 7 artifact. If you are not looking at Windows 7 machines anymore, you can drop that line from your collection script.
- Location:
C:\Windows\AppCompat\Programs\Amcache.hve - It is a registry hive, so it opens in Registry Explorer just like any other.
What You Get
- Full path of the file
- SHA1 hash
- File size, version info, publisher, and product name
- The compile (link) time of the executable
The SHA1 is the prize. The AV quarantined EVILFILE.EXE and maybe even deleted it, but Amcache still has its hash. Look it up on VirusTotal and you might have your malware family before lunch.
Gotchas
- An Amcache entry is not proof of execution. The inventory process records files that were installed, scanned, or simply present, not just files that ran. ANSSI research published in 2019 tested this thoroughly. Treat Amcache as “this file existed, and here is its hash,” then back it up with something from bucket 3.
- The hash covers only roughly the first 30 MB of a file. For large files, the SHA1 in Amcache will not match the whole-file hash you calculate yourself. Malware is rarely that big, but installers are.
- Key timestamps tell you when the entry was recorded, not when the program ran.
Parsing It
AmcacheParser.exe -f "C:\Cases\BOBPC\Amcache.hve" --csv "C:\Cases\BOBPC\Out"
You get several CSVs back. The file entries are the ones you want for this question. Filter on the path or the file name.
Back to Bob
Amcache has an entry for EVILFILE.EXE in Bob’s Temp folder, with a SHA1. It also has an entry for that DLL from Prefetch. Two hashes, two VirusTotal searches.
ShimCache (AppCompatCache)
Bucket 2: Windows knew about it. This one has burned more analysts than any other artifact I know of, so read the gotchas twice.
What It Is
The Application Compatibility Cache tracks executables Windows evaluated to decide whether they need a compatibility fix (a “shim”). It lives in the SYSTEM hive:
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache, valueAppCompatCache
What You Get
- Full path of the executable
- The file’s last modified time
- The order of entries, most recent first
Gotchas
- The timestamp is the file’s last modified time, not the execution time. Say that out loud. This is the single most common ShimCache mistake, and it shows up in real reports.
- On Windows 10 and later, there is no reliable execution flag. An entry means Windows saw the file. Simply browsing a folder in Explorer can add entries.
- ShimCache is written to the registry at shutdown or reboot. Until then, the newest entries live in memory. If Bob’s machine has not rebooted since Tuesday, the SYSTEM hive you collected may not contain EVILFILE.EXE at all.
Why Bother, Then?
- It keeps paths of files that are long gone, including ones that never ran.
- The order tells you roughly what Windows saw before and after something else.
- The stored modified time is a great timestomping check. If ShimCache says a file was modified in 2024 and the $MFT says 2009, someone has been messing with timestamps.
Parsing It
AppCompatCacheParser.exe -f "C:\Cases\BOBPC\SYSTEM" --csv "C:\Cases\BOBPC\Out"
Bonus: BAM
Bucket 3: Executed, with a user attached.
On Windows 10 (version 1709) and later, the Background Activity Moderator keeps a last-execution time for programs, per user. It lives in the SYSTEM hive:
HKLM\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings\<User SID>
Each value is a program path and its last execution time. Its memory is short, and its behavior has shifted between Windows builds, so treat it as a nice bonus when it is there rather than something you count on. Open the SYSTEM hive in Registry Explorer and browse to the key.
The interesting part is the SID. BAM does not just say the program ran; it says whose session ran it. That is the question for 5.2.
Why Do You Care?
Here is the cheat sheet for this part:
| Artifact | Bucket | Timestamp means | Hash? | Biggest gotcha |
|---|---|---|---|---|
| Prefetch | Executed | First run, last 8 runs | No | Off on servers; 1,024-file cap |
| Amcache | Windows knew | When it was inventoried | SHA1 | Entry is not execution |
| ShimCache | Windows knew | File’s last modified time | No | Not execution time; written at shutdown |
| BAM | Executed | Last run, per user | No | Short memory |
No single artifact answers “did it run?” by itself. Prefetch is the closest thing to a yes, Amcache gives you the hash, ShimCache backs up the path and catches timestomping, and BAM points at a user. Together they make an answer you can defend.
Back to Bob, One More Time
So far we know:
EVILFILE.EXEran three times, starting Tuesday afternoon (Prefetch)- It loaded a DLL from Bob’s
AppData\Roamingfolder (Prefetch) - We have SHA1 hashes for both files (Amcache)
- BAM ties the last run to Bob’s SID
Which leads to the next question. Was it actually Bob, or just Bob’s account? That is a job for 5.2: Who Ran It?
Happy hunting.
