courses

Plaso: Super-Timeline Forensics

Plaso (from the Icelandic plástur, “plaster”) is a Python-based framework for generating super-timelines: unified chronological event logs assembled from dozens of artifact types across a single image. Where mactime gives you file system timestamps alone, plaso ingests the file system plus event logs, registry hives, browser history, prefetch files, link files, shellbags, USB device history, and much more — producing a single artifact-normalized stream sorted by timestamp.

Plaso is the current successor to the original log2timeline Perl tool. The main components are:

Tool Role
log2timeline Extracts events from a source; writes a .plaso storage file
psort Reads a .plaso file; filters, sorts, and outputs events
pinfo Displays metadata about a .plaso storage file
psteal Combines log2timeline and psort into a single pass
image_export Extracts specific files from a disk image without full processing

The typical workflow: log2timeline.plaso file → psort → CSV/JSON for analysis.


Installation

The packaged version in Kali/Debian frequently lags behind upstream. The current recommended install method is uv, which creates an isolated environment automatically and is significantly faster than pip or pipx:

sudo apt remove python3-plaso plaso 2>/dev/null
curl -LsSf https://astral.sh/uv/install.sh | sh   # install uv if not present
uv tool install plaso

uv tool install adds log2timeline, psort, pinfo, psteal, and image_export directly to your PATH — no manual environment activation needed.

To upgrade:

uv tool upgrade plaso
log2timeline --version
psort --version

Docker (optional)

Docker is useful when you want a fully self-contained plaso environment — no Python version conflicts, no dependency management, and the same image works on any host OS. The official image is maintained by the plaso project.

docker pull log2timeline/plaso

The image is large (~1 GB) but pulls once and works offline thereafter.

Worked example — processing a disk image:

The container has no access to your host filesystem by default. Mount the directory containing your evidence with -v:

# Assume evidence is in ~/forensics/case01/ and contains tim2.dd
docker run --rm \
  -v ~/forensics/case01:/evidence \
  log2timeline/plaso \
  log2timeline \
    --storage-file /evidence/tim2.plaso \
    --parsers webhist,win7,win7_slow,win_gen \
    --hashers md5 \
    --status_view linear \
    /evidence/tim2.dd

Breaking this down:

Export the timeline with psort:

docker run --rm \
  -v ~/forensics/case01:/evidence \
  log2timeline/plaso \
  psort \
    --output_time_zone UTC \
    -o dynamic \
    -w /evidence/tim2.csv \
    /evidence/tim2.plaso

Inspect the storage file:

docker run --rm \
  -v ~/forensics/case01:/evidence \
  log2timeline/plaso \
  pinfo /evidence/tim2.plaso

Time-sliced export (events within ±30 minutes of a known timestamp):

docker run --rm \
  -v ~/forensics/case01:/evidence \
  log2timeline/plaso \
  psort \
    --output_time_zone UTC \
    --slice "2024-11-15T14:32:00" \
    --slice_size 30 \
    -o dynamic \
    -w /evidence/slice.csv \
    /evidence/tim2.plaso

Permissions note: the container runs as root internally. Files it writes to the mounted directory will be owned by root on the host. Fix ownership afterward if needed:

sudo chown $USER ~/forensics/case01/tim2.plaso ~/forensics/case01/tim2.csv

Shell alias for convenience — add to ~/.zshrc or ~/.bashrc:

alias plaso='docker run --rm -v "$(pwd)":/evidence log2timeline/plaso'

Then use it as if plaso were installed locally, with paths relative to your current directory:

cd ~/forensics/case01
plaso log2timeline --storage-file /evidence/tim2.plaso /evidence/tim2.dd
plaso psort -o dynamic -w /evidence/tim2.csv /evidence/tim2.plaso

log2timeline: Event Extraction

log2timeline reads a source (disk image, directory, or single file), runs every applicable parser against every file it finds, and writes timestamped events to a binary .plaso storage file.

Basic usage

log2timeline --storage-file evidence.plaso evidence.dd

This runs all parsers. On a full Windows image it will process for anywhere from 20 minutes to several hours depending on image size and hardware.

Common flags

Flag Effect
--storage-file <file> Output .plaso file path
--parsers <list> Comma-separated parsers or groups (default: all)
--hasher <list> Hash files during extraction (md5, sha256, etc.)
--vss_stores <n\|all> Include Volume Shadow Copy stores
--volumes all Process all volumes in the image
--filter_file <file> Restrict extraction to paths matching a filter file
--artifact_filters <list> Use named artifact definitions (e.g., WindowsEventLogs)
--workers <n> Number of parallel worker processes (default: CPU count)
--status_view linear Append status lines rather than overwriting (better for logs)
--logfile <file> Write processing log to a file
-q Suppress progress output

Targeted extraction with parsers

Processing every parser on every file is thorough but slow. For common scenarios, restrict parsers to what is relevant:

# Windows investigation: registry, event logs, prefetch, browser, MFT, file stats
log2timeline --storage-file evidence.plaso \
  --parsers winevtx,winreg,prefetch,filestat,lnk,mft,msie_webcache,chrome_history,firefox_history \
  evidence.dd

# Linux server incident
log2timeline --storage-file evidence.plaso \
  --parsers syslog,utmp,bash_history,filestat,cron,dpkg \
  evidence.dd

List all available parsers:

log2timeline --parsers list

Volume Shadow Copy processing

VSS stores are snapshots of the NTFS volume at previous points in time. Processing them can recover artifacts that were deleted or overwritten on the live volume.

# Process all VSS stores
log2timeline --storage-file evidence.plaso --vss_stores all --volumes all evidence.dd

# Process specific VSS stores (from mmls output)
log2timeline --storage-file evidence.plaso --vss_stores 1,3 evidence.dd

VSS processing multiplies runtime roughly by the number of stores. Disable it when not needed.

Artifact filters

Rather than specifying individual parsers, plaso supports artifact definitions — named collections of file paths and parser combinations defined in YAML. This approach is more maintainable for repeated workflows.

# List available artifact groups
log2timeline --artifact_filters list

# Use a named artifact group
log2timeline --storage-file evidence.plaso \
  --artifact_filters WindowsEventLogs,WindowsPrefetchFiles,WindowsRegistryFiles \
  evidence.dd

pinfo: Storage File Inspection

Before exporting events, inspect the storage file to confirm what was processed:

pinfo evidence.plaso

pinfo reports:

# Verbose output: individual parser event counts
pinfo -v evidence.plaso

Check pinfo output before running psort. A parser with zero events may indicate the image lacks that artifact type, or may indicate a parser error worth investigating.


psort: Filtering and Output

psort reads the .plaso storage file and writes events to a human-readable format. The storage file is binary and not meant to be read directly.

Basic export

# CSV output
psort -o dynamic -w timeline.csv evidence.plaso

# JSON Lines output (one JSON object per line)
psort -o json_line -w timeline.jsonl evidence.plaso

Output formats

Format Flag Use case
dynamic -o dynamic CSV; columns adapt to event type. Most common.
json_line -o json_line One JSON object per line. Suitable for jq, Elastic, Splunk.
l2tcsv -o l2tcsv Legacy log2timeline CSV format. Compatible with older tools.
timeline -o timeline Simple human-readable columnar format.
tln -o tln Five-field format for Timeline Explorer.
xlsx -o xlsx Excel workbook.

Timezone normalization

All events in the storage file are stored in UTC. Normalize output to the timezone of the evidence system:

psort --output_time_zone "America/Los_Angeles" -o dynamic -w timeline.csv evidence.plaso

Use IANA timezone names (America/New_York, Europe/London, UTC, etc.). Verify the evidence system’s configured timezone from the registry (HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation) before choosing.

Filtering events

Pass a filter expression as a positional argument to restrict output:

# Events from a specific date range
psort -o dynamic -w filtered.csv evidence.plaso \
  "timestamp > DATETIME('2025-03-01T00:00:00') AND timestamp < DATETIME('2025-03-15T00:00:00')"

# Events matching a specific data type
psort -o dynamic -w registry.csv evidence.plaso \
  "data_type is 'windows:registry:key_value'"

# Events whose message contains a string
psort -o dynamic -w logins.csv evidence.plaso \
  "message contains 'logon'"

# Combine conditions
psort -o dynamic -w exec.csv evidence.plaso \
  "data_type is 'windows:prefetch:execution' AND timestamp > DATETIME('2025-01-01T00:00:00')"

Filter expressions use ObjectFilter syntax: field names, is, contains, matches (regex), ==, >, <, and logical AND, OR, NOT.

Time slicing

Extract a window of events around a known point of interest:

# Events within ±5 minutes of a timestamp
psort --slice "2025-03-10T14:32:00" --slice_size 5 -o dynamic -w slice.csv evidence.plaso

Time slicing is useful after you have identified a suspicious event time and want to see what happened immediately before and after.


psteal: Single-Pass Processing

psteal combines extraction and output into one command, skipping the intermediate .plaso file. Use this when you need a quick export and do not need to reprocess the storage file later.

psteal --source evidence.dd -o dynamic -w timeline.csv

The tradeoff: you cannot re-run psort with different filters without re-running the full extraction. For any investigation that will require multiple analysis passes, use log2timeline + psort instead.


image_export: Targeted File Extraction

image_export extracts specific files from a disk image without running the full parser suite. Use it to pull targeted artifacts quickly:

# Extract all Windows Event Log files
image_export --source evidence.dd --filter_file evtx_filter.txt -w exported/

# Extract by file extension
image_export --source evidence.dd --extension evtx,lnk,pf -w exported/

A filter file is a text file with one path glob per line:

/Windows/System32/winevt/Logs/*.evtx
/Windows/Prefetch/*.pf
/Users/*/AppData/Roaming/Microsoft/Windows/Recent/*.lnk

image_export is faster than a full log2timeline run when you only need specific files for manual analysis or for feeding to a different tool.


Parser Reference

Windows artifacts

Parser Artifact Forensic value
filestat All file metadata MACB timestamps for every file
mft $MFT File system activity; recovered deleted file records
usnjrnl USN change journal Chronological record of file create/delete/rename/close events
winevtx .evtx event logs Logons, process creation, service installs, PowerShell execution
winreg Registry hives Run keys, USB history, user activity, application settings
prefetch Prefetch files Executable name, run count, last eight run times, files loaded
lnk Link (.lnk) files File accessed by user; source/target path; timestamps
olecf Office documents Author, last saved time, revision count
pe PE executables Compile timestamp, import hash
amcache Amcache.hve Execution evidence; SHA-1 hash of every executed binary
winjob .job scheduled tasks Task name, run time, command line
recycler $Recycle.Bin Original path and deletion time of binned files
msie_webcache IE/Edge WebCache.dat URLs visited, downloads, form data
chrome_history Chrome history SQLite URLs visited, searches, downloads
firefox_history Firefox places.sqlite URLs visited, downloads, form fill

Linux/Unix artifacts

Parser Artifact Forensic value
filestat All file metadata MACB timestamps
syslog /var/log/syslog System events, authentication
utmp utmp/wtmp/btmp Login/logout records, failed logins
bash_history .bash_history Commands typed by each user
cron Cron logs Scheduled task execution
dpkg dpkg.log Package install/remove history
apt_history apt/history.log Apt transaction history

macOS artifacts

Parser Artifact Forensic value
filestat All file metadata MACB timestamps
plist Property list files App preferences, launch agents, MRU lists
mac_appfirewall_log Application firewall log Inbound/outbound connection decisions
mac_securityd security.log Authentication, keychain access
spotlight Spotlight store Search queries, file metadata cache

Working With Output

Reducing noise

A full Windows image typically produces 2–10 million events. Strategies for reducing noise:

Filter to a time window: if you know when the incident occurred, limit output to ±24 hours of that window.

Filter by data type: registry and file system events together often dominate. Separate them and analyze targeted categories first.

Exclude known-good hashes: if you collected hashes during log2timeline with --hasher md5, filter out events whose file hashes appear in the NSRL:

psort -o dynamic -w filtered.csv evidence.plaso \
  "sha256_hash not in ['<known_good_1>', '<known_good_2>']"

Focus on user profiles first: limit to paths under C:\Users\ to find user-generated activity before expanding to system-wide artifacts.

Analyzing with command-line tools

For CSV output:

# Count events by data type
cut -d',' -f<type_column> timeline.csv | sort | uniq -c | sort -rn | head -20

# Extract rows containing a string
grep -i "powershell" timeline.csv > powershell_events.csv

# Find events in a specific path
grep -i "\\\\Downloads\\\\" timeline.csv > downloads.csv

For JSON Lines output with jq:

# Count events by data_type
jq -r '.data_type' timeline.jsonl | sort | uniq -c | sort -rn | head -20

# Extract specific fields from registry events
jq 'select(.data_type == "windows:registry:key_value") | {timestamp, key_path, value_name, data}' timeline.jsonl

Timeline Explorer

Eric Zimmerman’s Timeline Explorer is a Windows GUI for browsing plaso CSV output. It supports column filtering, color-coded event types, and bookmarking. Export from psort using -o l2tcsv or -o dynamic and open the resulting CSV in Timeline Explorer.

Timesketch

Timesketch is an open-source web application for collaborative timeline analysis. It ingests plaso storage files directly and supports search, tagging, and annotation. It is the appropriate tool when multiple analysts need to work on the same timeline simultaneously.

# Upload a plaso file to a running Timesketch instance
tsctl import --file evidence.plaso --sketch_id 1 --timeline_name "Evidence Drive"

Practical Workflow: Windows Investigation

# 1. Extract events (VSS included)
log2timeline \
  --storage-file evidence.plaso \
  --vss_stores all \
  --volumes all \
  --hasher md5,sha256 \
  --logfile log2timeline.log \
  --status_view linear \
  evidence.dd

# 2. Inspect what was found
pinfo -v evidence.plaso

# 3. Export full timeline to CSV (UTC)
psort --output_time_zone UTC -o dynamic -w full_timeline.csv evidence.plaso

# 4. Extract Windows event log entries only
psort -o dynamic -w evtx_events.csv evidence.plaso \
  "data_type contains 'windows:evtx'"

# 5. Extract a time slice around a known event
psort --slice "2025-03-10T02:15:00" --slice_size 30 \
  --output_time_zone UTC -o dynamic -w incident_window.csv evidence.plaso

# 6. Extract prefetch execution evidence
psort -o dynamic -w prefetch.csv evidence.plaso \
  "data_type is 'windows:prefetch:execution'"

Practical Workflow: Linux Investigation

# 1. Extract with Linux-relevant parsers
log2timeline \
  --storage-file linux_evidence.plaso \
  --parsers filestat,syslog,utmp,bash_history,cron,dpkg,apt_history,lnk \
  --logfile log2timeline.log \
  linux_evidence.dd

# 2. Inspect
pinfo linux_evidence.plaso

# 3. Export, normalized to system timezone
psort --output_time_zone "America/Los_Angeles" \
  -o dynamic -w linux_timeline.csv linux_evidence.plaso

# 4. Isolate authentication events
psort -o dynamic -w auth.csv linux_evidence.plaso \
  "message contains 'session opened' OR message contains 'authentication failure'"

Connecting to The Sleuth Kit

Plaso incorporates The Sleuth Kit for file system parsing and can consume TSK body files directly. If you already have a TSK body file from fls, add it to a plaso run:

# Import an existing TSK body file into a plaso storage file
log2timeline --storage-file combined.plaso --parsers mactime body.txt

This allows you to combine TSK file system timestamps with plaso’s artifact parsers in a single timeline without reprocessing the full image.

Alternatively, use the TSK body file directly with mactime for fast, focused file-system-only timelines, and use plaso when you need the broader artifact context. The two tools complement each other: TSK is faster and more granular at the file system layer; plaso is more comprehensive across artifact types.


References