← Back to blog

Reconstructing a user activity timeline from the USN journal

From three minutes of $UsnJrnl records you can usually reconstruct what a user was doing — Office, browser, downloads, code. How to read the journal as a behaviour log.

5 min read

A great deal of "what happened on this computer between 14:00 and 16:00" can be answered straight out of the USN journal. The records aren't a syscall log and they aren't tagged with a user — but they have something nearly as useful: a high-frequency, per-operation record of every file the machine touched. With a bit of pattern knowledge, you can recover the user's behaviour at the granularity of Office save, browser navigation, IDE rebuild, lunch break.

This post is the field guide for reading the journal as a behaviour timeline.

Why this works

The USN journal records which file changed, when, and how — and most user-visible actions on a desktop produce a recognisable signature of file activity. The user clicks Save in Word; Word writes a temp file, atomically renames, and BasicInfoChange | Closes the result. Chrome opens a new tab; the disk cache appends. The IDE rebuilds; a thousand object files spring into being.

These signatures aren't documented anywhere official — they're learned. Below is a starter set, plus the parser controls that make them tractable.

Office in the wild

When a user saves a Word, Excel or PowerPoint file, you see:

FileCreate | Close            ~$<filename>.docx     (lock file)
FileCreate | Close            <filename>.tmp        (atomic temp)
DataExtend | Close            <filename>.tmp        × N
RenameOldName | Close         <filename>.docx
FileDelete | Close            <filename>.docx
RenameNewName | Close         <filename>.docx       (was <filename>.tmp)
FileDelete | Close            ~$<filename>.docx
BasicInfoChange | Close       <filename>.docx

The ~$ lock file is Office's signal that a document is open; its FileCreate and FileDelete tell you the open/close moment of the document. The atomic rename .tmp.docx is the save itself. The leading ~$ files are surprisingly useful because they exist only while the document is open.

A pivot trick: filter for FileCreate records whose filename starts with ~$ to enumerate all Office documents the user opened in the window. Subtract FileDelete of the same names to find any still-open at the time of acquisition (a forensic image taken from a live box may have lock files for documents that were never properly closed).

Browser activity

Modern browsers maintain heavy file-system caches. Chrome and Edge use \Users\<u>\AppData\Local\<browser>\User Data\Default\Cache\Cache_Data\ (or Code Cache\); Firefox uses \Users\<u>\AppData\Local\Mozilla\Firefox\Profiles\<id>\cache2\.

What you see during browsing:

  • A sustained low rate of FileCreate | Close and DataExtend | Close in the cache directory.
  • Occasional FileDelete | Close as the LRU evicts old entries.
  • Every few minutes, RenameNewName of cache files as the index gets compacted.

Bursts of cache writes correlate well with visiting media-heavy or single-page-application sites. Quiet periods correlate with the user being away or on a long-loading page.

The cache filenames don't tell you what URLs were visited (that's in the browser's own database), but the cadence of cache I/O tells you the user was browsing. Combine with the journal's FileCreate events in the user's Downloads\ directory to identify deliberate downloads.

Code activity

If the user is a developer, IDE rebuilds produce highly characteristic bursts:

  • Webpack/Vite/Turbopack — many FileCreate in node_modules\.cache\ and dist\, often hundreds per build.
  • Visual Studio C++FileCreate of .obj and .pdb files in Debug\ or Release\ subtrees.
  • Cargo (Rust) — incremental builds touch target\debug\incremental\ heavily; full builds touch target\debug\deps\.

A 5-minute burst of FileCreate events in node_modules\ followed by a DataExtend swarm on a dist\bundle.js is "ran the build, then a dev server reloaded".

Downloads and installations

A direct download produces:

FileCreate | Close             \Users\<u>\Downloads\<file>.crdownload   (Chrome)
DataExtend | Close             \Users\<u>\Downloads\<file>.crdownload  × N
RenameNewName | Close          \Users\<u>\Downloads\<file>
BasicInfoChange | Close        \Users\<u>\Downloads\<file>

.crdownload, .part, .download extensions are Chrome, Firefox, Edge respectively. The atomic rename at the end is what makes the file appear "complete".

Installation of a new program typically follows: FileCreate of an installer .exe/.msi in Downloads, then a burst of FileCreate records in \Program Files\ or \Program Files (x86)\ or \Users\<u>\AppData\Local\Programs\. The minute-by-minute histogram makes installs trivially identifiable.

Putting it together: a daily timeline

The recipe for a "what did the user do today" report:

  1. Pull the user's parsed journal for the day. Restrict to records under \Users\<u>\ to remove system noise.
  2. Compute, per 10-minute bucket: count of FileCreate, DataExtend, BasicInfoChange.
  3. Plot the three series. The shape tells you the rough activity:
    • High creates + extend: writing/saving content.
    • High BasicInfoChange only: browsing, scrolling, light editing.
    • High extend with low create: large downloads or media playback.
    • Sustained creates in Cache\ directories: browsing.
    • Sustained creates in node_modules\ / Debug\ / target\: coding.
  4. Annotate spikes by inspecting the top filenames in each bucket. Office filenames are great anchors; cache filenames you can usually ignore.

The parser on this site exposes the per-minute histogram on its timeline component — clicking a bar filters the table to that window, which is the workflow above without writing any code.

Pitfalls

  • Backup and AV scans produce volume-wide BasicInfoChange bursts that look superficially like user activity. They tend to follow scheduled times and visit every directory, not just the user's, which makes them easy to identify and exclude.
  • Sync agents (OneDrive, Dropbox) generate journal traffic that looks like user activity but is the agent's own work. Filter to records where the path is outside the sync folder to focus on user-initiated work.
  • Background indexers (SearchIndexer.exe) touch files in \Users\<u>\AppData\Roaming\Microsoft\Windows\Recent\ and \ProgramData\Microsoft\Search\ — easy to bucket as system noise.

Where to go next

  • The Microsoft Learn Windows event reference for pairing journal activity with Security/Sysmon events.
  • The Velociraptor artifacts pack — many community artifacts use journal + MFT correlations like the ones above.
  • For a working timeline at scale, Plaso (log2timeline) can ingest a parsed journal and merge it with every other Windows timeline artefact into a single super-timeline.

The journal alone won't replace a proper super-timeline. But for 80% of investigations, "what was the user doing between 14:00 and 16:00" is answerable with just $J and $MFT, in the time it takes to drag them onto this page.