Plaso and Log2Timeline
Plaso (log2timeline's successor) is the gold standard for automated super-timeline generation. It ingests disk images, memory dumps, KAPE output directories, and individual artifact files, extracts timestamps from hundreds of artifact types simultaneously, and stores them in a .plaso storage file that Timesketch can visualize at scale.
You have a KAPE triage collection directory, a memory image, and a partial disk image. You need to build a single coherent timeline covering all artifact types across the investigation window. Processing everything manually would take days. Plaso processes the entire collection in 2-3 hours (for a typical KAPE triage) and produces a unified timeline with over 200,000 events — all normalized to UTC and categorized by artifact source.
Plaso Processing Workflow
Plaso Workflow
═══════════════════════════════════════════════════════════════════
Input sources supported by Plaso:
├── Raw disk images (.dd, .img)
├── E01 disk images
├── VMDK / VHD virtual disk images
├── Directory of extracted artifacts (KAPE output)
├── Individual files: evtx, prefetch, registry hives
├── SQLite databases (browser history, SRUM)
└── Memory images (with Volatility integration)
Processing steps:
1. log2timeline.py (collection):
→ Reads input source
→ Runs appropriate parsers for each artifact type
→ Writes timestamped events to .plaso storage file (SQLite)
2. psort.py (filter + output):
→ Reads .plaso storage file
→ Filters by time range, host, artifact type
→ Outputs to CSV, JSON, ElasticSearch, or Timesketch
3. pinfo.py (statistics):
→ Summarizes .plaso file: parser counts, time range, errors
Output: normalized events with fields:
datetime, timestamp_desc, source, source_long,
message, parser, hostname, inode, filename
Plaso doesn't "parse logs" the way grep does. It runs parsers — one per artifact type — and each parser knows how to find timestamps in that artifact's specific format. The MFT parser reads every MFT record and emits 4 timestamps per file. The prefetch parser reads .pf binary files and emits up to 8 run-timestamps per prefetch entry. The output is always the same normalized schema regardless of the source. This is what makes the super-timeline possible: every artifact speaks the same language after Plaso processes it. Your job after Plaso runs is to filter and read that normalized stream — not re-parse individual artifact formats.
CASE_DIR="/cases/CASE-2026-009"
KAPE_OUT="$CASE_DIR/triage/FINANCE-SRV01"
PLASO_OUT="$CASE_DIR/plaso"
PLASO_FILE="$PLASO_OUT/FINANCE-SRV01.plaso"
mkdir -p $PLASO_OUT
# Step 1: Process KAPE triage output directory with log2timeline
# Plaso auto-detects parsers based on file content
log2timeline.py \
--timezone UTC \
--partitions all \
--logfile $PLASO_OUT/log2timeline.log \
$PLASO_FILE \
$KAPE_OUT
# This processes:
# - All .evtx files → Windows event log parser
# - *.pf prefetch files → prefetch parser
# - NTUSER.DAT, SAM, SYSTEM, SECURITY, SOFTWARE → registry parsers
# - *.db SQLite files → browser history, SRUM parsers
# - $MFT → MFT parser
# - LNK files → LNK parser
# - Jump lists → JumpList parser
# Step 2: Check processing summary
pinfo.py $PLASO_FILE | head -50
# Step 3: Filter and export the attack window to CSV
psort.py \
--timezone UTC \
-o dynamic \
--fields datetime,timestamp_desc,source_long,message,parser,filename \
-w $PLASO_OUT/timeline-attack-window.csv \
$PLASO_FILE \
"date > '2026-09-17 02:00:00' AND date < '2026-09-17 06:00:00'"
echo "Attack window events: $(wc -l < $PLASO_OUT/timeline-attack-window.csv)"
# Step 4: Export to Timesketch (see Ch40)
psort.py -o timesketch \
--output_time_zone UTC \
--name "CASE-2026-009-FINANCE-SRV01" \
--sketch_id 1 \
$PLASO_FILE \
"date > '2026-09-01 00:00:00'"
Running log2timeline.py against a 500 GB E01 image processes every file on the entire disk — including Windows Update archives, side-by-side assembly stores, and thousands of legitimate system files. This can take 8–12 hours and produce tens of millions of events, most irrelevant. The correct approach for IR: run KAPE first to extract only forensic artifacts (≈100–500 MB), then run Plaso on the KAPE output directory. Processing time drops from 12 hours to 30–90 minutes, and the resulting .plaso file contains 200K–500K events instead of 50 million. Use full-image Plaso processing only when you've exhausted KAPE artifacts and need comprehensive filesystem timeline coverage.
Most Valuable Plaso Parsers
| Parser | Artifact(s) | Events extracted |
|---|---|---|
| winevtx | *.evtx | All Windows event log records with full message |
| winprefetch | *.pf | Prefetch run timestamps (up to 8 per file) |
| winreg / winreg_default | NTUSER.DAT, SOFTWARE, SYSTEM, SAM | Registry key LastWriteTime + value data |
| mft | $MFT | All file MACB timestamps (most event-dense parser) |
| lnk | *.lnk | LNK target timestamps + accessed time |
| chrome_history | Chrome History SQLite | Visit times, URLs, download times |
| firefox_history | places.sqlite | Visit times, URLs |
| srum | SRUDB.dat | Application network usage timestamps |
| olecf / msiecf | Office temp files, IE cache | Document open/access times |
Q & A
Q: Plaso processing took 8 hours on a 500 GB image. How do you make it faster?
Several optimizations reduce processing time significantly: (1) Use KAPE triage output instead of the full disk image: KAPE extracts only the relevant artifact files (100–500 MB total). Processing a KAPE output directory takes 30–90 minutes vs 8+ hours for a full disk image. (2) Use --parsers to limit parser set: log2timeline.py --parsers winevtx,winprefetch,mft,lnk,winreg skips parsers you don't need (e.g., macOS parsers on a Windows image). (3) Use --worker_processes: Plaso supports parallel processing. log2timeline.py --worker_processes 4 uses 4 CPU cores. (4) Use --filter_file with path filter: limit processing to specific directories. (5) Mount the E01 first and process the mounted volume: some toolchain configurations process mounted volumes faster than EWF files.