BAM vs UserAssist: Two Per-User Execution Artifacts
BAM and UserAssist both tie program execution to a user. Compare their locations, timestamps, run counts, coverage of GUI and background launches and retention.
TL;DR. Both artifacts say which user ran what. BAM (SYSTEM hive, per SID) catches processes regardless of how they were launched — except removable/network paths and console programs from a command line — but keeps only the last timestamp for about a week. UserAssist (each user's NTUSER.DAT) only sees launches through the Explorer shell, but adds run count, focus count and focus time and keeps them much longer. When they disagree, the difference is usually the launch method.
Most comparisons put BAM next to system-wide artifacts (Prefetch, ShimCache, Amcache). The more interesting neighbour is UserAssist, because it's the other classic per-user execution artifact. Background on BAM: the BAM/DAM forensics guide.
At a glance
| BAM | UserAssist | |
|---|---|---|
| Hive | SYSTEM (one file per host) | NTUSER.DAT (one per user profile) |
| Key | Services\bam\State\UserSettings\<SID> | Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{GUID}\Count |
| Attribution | Key name = SID | The hive belongs to the user |
| Value name | NT device path or package name | ROT13-obfuscated path, often with a Known Folder GUID |
| Timestamps | One FILETIME (last recorded activity) | Last execution FILETIME |
| Counters | None | Run count, focus count, focus time |
| What's recorded | Processes seen by bam.sys (Windows 10 1709+) | Launches via the Explorer shell |
| Retention | ~7 days, pruned at boot | Long-lived |
| Blind spots | Removable/network paths, CLI console tools | Anything not launched through Explorer |
Sources: Suhanov, BAM internals; libyal winreg-kb, UserAssist; Didier Stevens, UserAssist.
UserAssist in two minutes
Under UserAssist each GUID subkey tracks a category; on Windows 7 and later, {CEBFF5CD-ACE2-4F4F-9178-9926F41749EA} covers executable launches and {F4E57C4B-2036-45F0-A9AB-443BCFE33D9F} shortcut launches (libyal). Value names are the program path with ROT13 applied to letters — P:\Jvaqbjf\... is C:\Windows\.... Paths often start with a Known Folder GUID instead of a drive letter.
The value data (72 bytes on Windows 7+) holds an execution count at offset 4, a focus count at offset 8, the focus time at offset 12 and the last execution FILETIME at offset 60 (libyal). libyal lists what the key tracks: launches through Control Panel, the Start menu and shortcuts, the Run dialog, hotkeys, Quick Launch and similar Explorer paths.
Decoding a value name by hand
ROT13 shifts each letter by 13 places and leaves digits and punctuation alone, so it is its own inverse. Take this UserAssist value name:
P:\Jvaqbjf\Flfgrz32\pzq.rkr
Shift the letters back by 13 and you get C:\Windows\System32\cmd.exe. Every UserAssist tool does this for you, but knowing what it looks like helps when you're scrolling through a raw hive in a viewer, or when a keyword search for cmd.exe over the raw hive returns nothing: the plain name is not stored there.
BAM in two minutes
One key per SID in the SYSTEM hive, one REG_BINARY per executable, first 8 bytes a FILETIME updated at process start and exit; about seven days of retention; nothing for removable media or network shares (Suhanov). Details: where the BAM key is and the value format.
Where they disagree — and why
| Seen in | Typical cause |
|---|---|
| BAM only | Launched by a script, a command line (non-console programs), a service or task running as the user, remote execution; or UserAssist was cleared |
| UserAssist only | Older than BAM's week; run from a USB stick or network share (Explorer launch, but BAM excludes the path); executable deleted and the host rebooted |
| Both | Launched through Explorer recently from a local disk |
| Neither | Console program started from cmd.exe/PowerShell, or both cleaned |
The first row is where BAM earns its place: attacker tooling rarely goes through the Start menu. In the fictional lateral-movement case, PsExec64.exe and rclone.exe under svc_backup are exactly the kind of launches UserAssist would not be expected to show, while BAM does.
The second row is where UserAssist earns its place: history. When the incident started three weeks before collection, BAM is probably empty for the early phase, while UserAssist may still show the first run of a tool with a run count.
Different hives, different acquisition
- BAM: one
SYSTEMhive (+ logs) covers every user of the host. - UserAssist: one
NTUSER.DAT(+ntuser.dat.LOG1/LOG2) per profile underC:\Users\<name>\. Deleted profiles take their UserAssist with them; BAM keys for that SID live in SYSTEM, so they may outlive the profile until pruned.
A KAPE collection with registry targets usually gets both (KapeFiles). Our BAM/DAM Parser handles the SYSTEM side; NTUSER.DAT artifacts such as UserAssist can be read with Registry Parser or the tools in the parser comparison.
Timestamps: compare with care
Both are FILETIMEs in UTC, but they don't mean the same thing:
- UserAssist last execution is written when Explorer launches the program.
- BAM is updated at process creation and termination, so it can be later than the UserAssist time for the same run if the program stayed open.
A BAM time a few hours after the UserAssist time for the same path is therefore not a contradiction; it may be the program closing.
Anti-forensics
Both are plain registry data. UserAssist values can be deleted by the user or by cleanup utilities, since the hive belongs to the user; BAM entries can be deleted with enough privileges and disappear on their own after a week or when the executable is deleted and the host reboots (BAM limitations). A user whose UserAssist is empty while BAM shows interactive-looking programs (browser, Office) is worth a second look.
Investigation checklist
- Parse BAM for every SID on the host (one SYSTEM hive covers them all).
- Parse UserAssist from each profile's
NTUSER.DAT, including profiles of accounts you think are irrelevant. - For each program of interest, note: present in BAM? in UserAssist? run count? last times in both?
- Explain each disagreement with the table above (launch method, age, path type) before calling anything suspicious.
- Bring Prefetch and event logs in for the rows that still don't add up.
Frequently asked questions
What is the difference between BAM and UserAssist?
BAM lives in the SYSTEM hive, one key per SID, with a single recent timestamp per executable and roughly a week of retention. UserAssist lives in each user's NTUSER.DAT, records launches made through the Explorer shell, and keeps a run count, focus time and last execution time for much longer.
Why does a program appear in BAM but not in UserAssist?
UserAssist records launches through the Explorer shell (Start menu, desktop, shortcuts, Run dialog). Programs started by a script, a command line, a service or a remote tool don't go through those paths, but can still produce a BAM entry.