Plaso: Super-Timeline Forensics
- Plaso: Super-Timeline Forensics
- Installation
- log2timeline: Event Extraction
- pinfo: Storage File Inspection
- psort: Filtering and Output
- psteal: Single-Pass Processing
- image_export: Targeted File Extraction
- Parser Reference
- Working With Output
- Practical Workflow: Windows Investigation
- Practical Workflow: Linux Investigation
- Connecting to The Sleuth Kit
- References
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:
--rm— remove the container when it exits (keeps things tidy)-v ~/forensics/case01:/evidence— mounts your local directory as/evidenceinside the container; all paths inside thelog2timelinecommand use the container path/evidence/...--storage-file /evidence/tim2.plaso— writes the output back to your mounted directory so it persists after the container exits- The image name
log2timeline/plasocomes last, then the plaso command and its arguments
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:
- Plaso version and format version
- Source path and image type
- Parsers that ran and how many events each produced
- Total event count
- Processing start/end times and duration
- Any errors or skipped files
# 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
- Plaso documentation
- Plaso GitHub repository
- Timeline Explorer by Eric Zimmerman
- Timesketch
- SANS FOR508 course materials cover plaso workflows in detail and are worth reading independently of the course