Skip to content

FSEvents Investigation: A Mac Exfiltration Walkthrough

A fictional macOS intrusion traced with FSEvents alone: a download, a LaunchAgent, Full Disk Access, a hidden staging folder, a USB stick and the cleanup.

Published on 4 min read

TL;DR. Using only the .fseventsd logs of a laptop and of a USB stick, you can show that between roughly 10:05 and 10:50 UTC someone downloaded and unpacked tools.zip, stripped an extended attribute, wrote a LaunchAgent, triggered a TCC change, gathered 48 finance documents in a hidden folder, wrote them to a stick named EXFIL, and deleted the staging folder. Everything here is the synthetic sample of the FSEvents Parser: click Try a sample to follow along.

The case

This continues the fictional intrusion that began on the Windows workstation FIN-WKS-07 (the svc_backup account). The same actor used a stolen session on FIN-MBP-03, the MacBook of finance employee dana.whitlock, on 2026-09-14. The responder has two archives: the Data volume's .fseventsd and the .fseventsd of a USB stick found on the desk, imaged through a write blocker.

1. Load the logs

Drop both archives (or load the sample). The Sources tab shows two volumes: the Data volume (seven 3SLD logs) and EXFIL (one log). The timing line reads "file times look original": the log mtimes are spread over the morning, so the time windows can be trusted. The EXFIL volume's history started at 10:31:14, the modification time of its fseventsd-uuid: the stick was first seen by fseventsd then.

2. Set the window

In the time range bar, type 2026-09-14 10:00:00 → 10:55:00 UTC (the sample offers a one-click button). The chip reads 770 of 1,068 records and the URL gains #from=2026-09-14T10:00:00Z&to=2026-09-14T10:55:00Z. All counts, findings and exports now use this window. Keep the default time field, approximate window (overlaps), to miss nothing (why).

3. Read the findings

  • LaunchAgent written. ~/Library/LaunchAgents/com.example.updater.plist.tmp is created, then renamed to com.example.updater.plist and its metadata changed, between 10:09:55 and 10:23:18. See launch agent.
  • TCC database changed. The system Library/Application Support/com.apple.TCC/TCC.db (and its -wal) is modified in the same window, right after com.apple.systempreferences.plist. Consistent with Terminal being granted Full Disk Access; the TCC.db rows would confirm it (TCC database).
  • Extended attributes removed. Downloads/tools/sync-helper and Downloads/tools/com.example.updater.plist lose an attribute between 09:58:40 and 10:09:55, after being extracted with one. Removing com.apple.quarantine is a likely explanation; FSEvents cannot name the attribute (quarantine attribute).
  • Hidden folder. Users/dana.whitlock/Library/Caches/.sync is created with 48 spreadsheets, CSVs and PDFs.
  • External volume EXFIL. Volumes/EXFIL is mounted and unmounted on the Data volume; on the stick, exfil/ receives the same 48 names, each with an AppleDouble ._ companion.
  • Mass removal. 48 removals in .sync, then the folder itself, between 10:38:02 and 10:52:41.
  • Short-lived files. Downloads/tools/* and Downloads/tools.zip appear and disappear in the loaded history.

None of these is proof of intent on its own. Together, in this order, they tell a coherent story.

4. Follow the files

  • Open the tools.zip removal and click Show every record of this path: the archive arrives by a rename from tools.zip.download/tools.zip (Safari's download bundle), gets its attributes, and is removed at the end. The Renames tab pairs both sides by their shared node ID.
  • Filter to node: + the LaunchAgent's node ID to see the .tmp and final names as one object.
  • The Path tree shows Users/dana.whitlock/Library/Caches/.sync with Created and Removed chips, and exfil on the EXFIL volume with Created only.
  • The browser visit to transfer.example leaves only Safari/History.db writes in FSEvents: the domain itself is in the History database, not here.

5. Export and report

Export Records (CSV) and Rename pairs (CSV) for the report, Timesketch (CSV) to merge with other timelines (each record placed at its log file's flush time, labelled as an upper bound), or Everything (JSON). File names carry the range, e.g. FIN-MBP-03_fsevents_2026-09-14T100000Z-2026-09-14T105500Z_records.csv.

In the report, give each event as a window, cite the log file, and say what FSEvents does not show: no user, no process, no file content.

What would change the conclusions

  • If the log mtimes had been reset by the copy, only the order would remain.
  • If the stick had never been imaged, only the mount point and the staging/deletion on the Mac would show; the list of files written to it would be missing.
  • If the Mac had been idle for days before the incident, the first window could span days.

For the collection side, see how to collect .fseventsd; for the format, 1SLD, 2SLD and 3SLD pages.

Related articles