macOS Forensics
macOS is the primary platform for developers, executives, and design teams — and a common entry point for targeted attacks. macOS has a unique artifact set: Unified Logging (replacing traditional syslog), FSEvents (comprehensive filesystem change journaling), plist files for persistence, and Apple-specific databases for Spotlight and Safari.
An executive's MacBook was targeted by a spear-phishing campaign that delivered a malicious DMG file. The attacker installed a macOS implant (LaunchAgent for persistence) and exfiltrated documents from the Desktop and Documents folders. The Unified Log captures the DMG mount, the app execution, and the LaunchAgent installation. FSEvents records every file accessed by the implant. This chapter covers collecting and analyzing these macOS-specific artifacts.
macOS Forensic Artifact Locations
| Artifact | Location | What it records |
|---|---|---|
| Unified Log | /var/db/diagnostics/ + /var/db/uuidtext/ | All system events — replaceed old syslog, process activity, network events |
| FSEvents | /.fseventsd/ | Filesystem change journal — every create, modify, rename, delete (content, not timestamps) |
| LaunchAgents (user) | ~/Library/LaunchAgents/*.plist | Per-user persistence — starts on login |
| LaunchDaemons | /Library/LaunchDaemons/*.plist | System-wide persistence — starts at boot |
| Shell history | ~/.zsh_history (macOS Catalina+), ~/.bash_history | Command-line history |
| Quarantine database | ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 | All downloaded files with URL and timestamp |
| Spotlight database | /.Spotlight-V100/ | Metadata index of all files — also tracks deleted files for a period |
| Safari/Chrome history | ~/Library/Safari/History.db, ~/Library/Application Support/Google/Chrome/Default/History | Web browsing history |
#!/bin/bash
# macOS forensic triage collection
# Run with sudo on the compromised Mac or mounted image
TARGET="/" # live system or set to mounted image path
OUT="/Volumes/EvidenceDrive/CASE-2026-009/$(hostname)"
mkdir -p $OUT/{logs,persistence,users,downloads}
# Unified Log (binary format — convert with 'log' command)
echo "Collecting Unified Log..."
# Export from running system:
log collect --last 7d --output $OUT/logs/unified-log.logarchive
# Or from offline mounted image:
# log show --archive $TARGET/var/db/diagnostics --info --debug \
# --predicate 'subsystem == "com.apple.launchd"' \
# > $OUT/logs/launchd.txt
# FSEvents (requires fseventer or dedicated parser)
echo "Collecting FSEvents..."
cp -R "$TARGET/.fseventsd/" "$OUT/logs/fseventsd/"
# LaunchAgents / LaunchDaemons (persistence)
echo "Collecting persistence..."
cp -R "$TARGET/Library/LaunchDaemons/" "$OUT/persistence/"
cp -R "$TARGET/Library/LaunchAgents/" "$OUT/persistence/system-launch-agents/"
for user_dir in $TARGET/Users/*/; do
user=$(basename $user_dir)
mkdir -p "$OUT/persistence/users/$user"
cp -R "$user_dir/Library/LaunchAgents/" "$OUT/persistence/users/$user/" 2>/dev/null
done
# Quarantine database (downloaded files with URLs)
echo "Collecting quarantine events..."
for user_dir in $TARGET/Users/*/; do
user=$(basename $user_dir)
qdb="$user_dir/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2"
if [ -f "$qdb" ]; then
cp "$qdb" "$OUT/downloads/QuarantineEvents-$user.db"
fi
done
# User home artifacts
for user_dir in $TARGET/Users/*/; do
user=$(basename $user_dir)
mkdir -p "$OUT/users/$user"
cp "$user_dir/.zsh_history" "$OUT/users/$user/" 2>/dev/null
cp "$user_dir/.bash_history" "$OUT/users/$user/" 2>/dev/null
cp -R "$user_dir/.ssh/" "$OUT/users/$user/" 2>/dev/null
done
Unified Log Analysis
LOGARCHIVE="/cases/CASE-2026-009/exec-mac/logs/unified-log.logarchive"
# Show all process launches in a time window
log show --archive $LOGARCHIVE \
--start "2026-09-17 00:00:00" \
--end "2026-09-17 06:00:00" \
--predicate 'process == "launchd"' \
--info | grep -i "spawn\|exec"
# Find network connections (endpointsecurity subsystem)
log show --archive $LOGARCHIVE \
--predicate 'subsystem == "com.apple.endpointsecurity"' \
--info | grep -i "connect\|bind"
# Find LaunchAgent installations (persistence events)
log show --archive $LOGARCHIVE \
--predicate 'process == "launchd" AND message CONTAINS "LaunchAgent"' \
--info
# Find app installations from DMG
log show --archive $LOGARCHIVE \
--predicate 'process == "diskimagemounter"' \
--info | grep -i "mount\|attach"
Quarantine Database Analysis
QDBPATH="/cases/CASE-2026-009/exec-mac/downloads/QuarantineEvents-jdoe.db"
# Query the quarantine database (SQLite)
sqlite3 $QDBPATH << 'EOF'
.headers on
.mode column
.width 30 15 50 30
-- All downloaded files with origin URLs
SELECT
datetime(LSQuarantineTimeStamp + 978307200, 'unixepoch') AS DownloadTime,
LSQuarantineAgentBundleIdentifier AS App,
LSQuarantineDataURLString AS URL,
LSQuarantineOriginURLString AS ReferrerURL
FROM LSQuarantineEvent
ORDER BY LSQuarantineTimeStamp DESC
LIMIT 100;
EOF
# Note: LSQuarantineTimeStamp is Apple Absolute Time (seconds since Jan 1 2001)
# 978307200 converts to Unix epoch
Q & A
Q: The Mac is an M1/M2 (Apple Silicon). Does this change the forensic process?
The artifact types and locations are the same between Intel and Apple Silicon Macs. The key differences for forensics are: (1) Acquisition: Apple Silicon Macs have a Secure Enclave and different boot process. DFU mode (Device Firmware Upgrade) is required for some acquisition techniques, and the process differs from Intel Macs' Target Disk Mode. checkra1n (jailbreak-based acquisition) doesn't support Apple Silicon. Tools like Cellebrite UFED and Sumuri Paladin have been updated for M-series; verify your toolchain supports Apple Silicon before acquisition. (2) Memory: Apple Silicon uses unified memory architecture — RAM and GPU share a memory pool. Standard macOS memory acquisition tools work similarly, but the memory layout differs. (3) Binaries: Apple Silicon runs ARM64 binaries or x86 under Rosetta 2 translation. If an attacker dropped an ARM64 binary, tools running on x86 analysis VMs can't execute it directly — use `file` to identify the architecture, and static analysis tools (Ghidra, Binary Ninja) for examination. (4) File System: APFS is the default on both architectures — artifact locations remain the same.