
The problem
An attacker has compromised your network. They’ve moved laterally across Windows servers, Linux machines, and cloud infrastructure. Your evidence is scattered: EVTX files from 50 machines, Linux auth logs from a dozen servers, network data from your EDR. You need to reconstruct the attacker’s path — every hop, every credential used, every failed attempt — and you need it now.
Masstin parses all these sources and merges them into a single chronological timeline where a Windows RDP logon, a Linux SSH brute-force, and an EDR network connection appear side by side, in the same format, ready for analysis or graph visualization.
- Repository: github.com/jupyterj0nes/masstin
- License: AGPL-3.0
- Platforms: Windows, Linux and macOS — zero dependencies, single binary
Key Features
| Feature | Description | Article |
|---|---|---|
| Unified cross-OS image parsing | Single parse-image command auto-detects OS per partition — NTFS gets Windows parsing (EVTX + UAL + VSS), ext4 gets Linux parsing (auth.log, wtmp, audit.log, systemd-journald binary logs, etc.) — all merged into one timeline. Point at a folder of mixed images and get a single CSV. Zero manual steps. |
Forensic images |
| graph-hunt: statistical detection | Every connection after the cutoff is measured against the network’s own baseline: p-values, the false discovery rate as the only parameter, Hopper classes, chain reconstruction from a seed, an analyst report. Runs straight from the CSV, no database or plugin needed | graph-hunt |
| Multi-directory incident analysis | Analyze dozens of machines at once with multiple -d flags, critical for ransomware investigations |
Parse evidence |
| Cross-platform timeline | Windows EVTX + Linux SSH + EDR data in one timeline — parse-image auto-merges across OS boundaries |
Windows / Linux / Cortex |
| 33+ Event IDs from 12 EVTX sources + Scheduled Tasks XML | Security.evtx, Terminal Services, SMBServer, SMBClient, RdpCoreTS, WinRM, WMI-Activity, Sysmon (Event 3 network connections) + remote task detection — covering RDP, SMB, Kerberos, NTLM, share access, PowerShell Remoting, WMI and Scheduled Tasks | Security.evtx / RDP / SMB |
| Event classification | Every event classified as SUCCESSFUL_LOGON, FAILED_LOGON, LOGOFF or CONNECT |
CSV Format — event_type |
| Recursive decompression | Auto-extracts ZIP/triage packages recursively (KAPE, Velociraptor, UAC, Cortex; tar / tar.gz streamed, nested in each other), handles archived logs with duplicate filenames, auto-detects common forensic passwords | Linux artifacts — triage support |
| Linux smart inference | Auto-detects hostname, infers year from dpkg.log, supports Debian (auth.log) and RHEL (secure), RFC3164 and RFC5424 formats |
Linux artifacts — inference |
| systemd-journald binary logs | Pure-Rust reader for /var/log/journal/*.journal[~] — compact mode + zstd decompression. Essential on Ubuntu 22 / RHEL 8+ with SSSD + Active Directory, where /var/log/auth.log is empty because PAM routes auth through the journal. Walks sshd events and applies the same Accepted/Failed password regexes as text logs. Works on Windows analyst hosts without libsystemd. |
Linux artifacts — systemd-journald |
| Graph visualization with noise reduction | Direct upload to Neo4j or Memgraph with connection grouping (earliest date + count) and automatic IP-to-hostname resolution | Neo4j / Memgraph |
| Temporal path reconstruction | Cypher query to find the chronologically coherent attacker route between two nodes | Neo4j — temporal path / Memgraph — temporal path |
| Session correlation | logon_id field enables matching logon/logoff events to determine session duration |
CSV Format — logon_id |
| Silent mode | --silent flag suppresses all output for integration with Velociraptor, SOAR platforms and automation pipelines |
Actions table |
| Bulk evidence processing | Point -d at an evidence folder — masstin recursively finds all E01/VMDK/dd images, auto-detects OS per partition, extracts all artifacts from live + VSS, per-image artifact grouping in summary. One command for an entire incident |
Forensic images |
| BitLocker detection | Detects BitLocker-encrypted partitions (-FVE-FS- signature) and warns the analyst — no wasted time on unreadable data |
Forensic images |
| streamOptimized VMDK | Full support for compressed VMDKs (OVA exports, cloud templates). Also handles incomplete SFTP uploads (.filepart fallback) |
Forensic images |
| VSS snapshot recovery | Detect and extract EVTX from Volume Shadow Copies — recover event logs deleted by attackers | VSS recovery |
| Mounted volume support | Point -d D: at a mounted volume or use --all-volumes — live EVTX + VSS recovery from connected disks, no imaging needed |
Forensic images |
| UAL parsing | Auto-detect User Access Logging ESE databases — 3-year server logon history surviving event log clearing | UAL |
| MountPoints2 registry | Extract NTUSER.DAT from each user profile and parse MountPoints2 — reveals user→server share connections with timestamps, survives log clearing. Dirty hive + transaction log support | MountPoints2 |
| EVTX carving | carve-image scans raw disk for EVTX chunks in unallocated space — recovers events after logs AND VSS are deleted. Implements Tier 1 (full 64 KB chunks) + Tier 2 (orphan record detection); Tier 3 (template matching) is planned. Builds synthetic EVTX files grouped by provider and parses them through the full pipeline. Three upstream parser bugs (infinite loops and multi-GB OOMs on corrupt BinXML) were reported and fixed in evtx 0.11.2; masstin keeps thread isolation + catch_unwind + --skip-offsets as a belt-and-suspenders safety net |
EVTX carving |
| Transparent reporting | CLI shows artifact discovery, processing progress, hostname/year inferences and per-artifact event counts | Parse evidence |
Install
Download pre-built binary (recommended)
No Rust toolchain needed. Just download and run.
| Platform | Download |
|---|---|
| Windows | masstin-windows.exe |
| Linux | masstin-linux |
| macOS (Apple Silicon) | masstin-macos-arm64 |
| macOS (Intel) | masstin-macos-x86_64 |
Go to Releases and download the binary for your platform. That’s it.
Build from source (alternative)
git clone https://github.com/jupyterj0nes/masstin.git
cd masstin && cargo build --release
Parse evidence
# Forensic images — auto-detects Windows and Linux, single merged timeline
masstin -a parse-image -f DC01.e01 -f ubuntu-server.vmdk -o timeline.csv
# Scan entire evidence folder — any mix of Windows/Linux images
masstin -a parse-image -d /evidence/all_machines/ -o full_timeline.csv
# Parse extracted logs from directories
masstin -a parse-windows -d /evidence/DC01 -d /evidence/SRV-FILE -o windows.csv
masstin -a parse-linux -d /evidence/linux-triage/ -o linux.csv
Visualize in a graph database
# Load into Memgraph (no auth needed)
masstin -a load-memgraph -f full-timeline.csv --database localhost:7687
# Load into Neo4j
masstin -a load-neo4j -f full-timeline.csv --database localhost:7687 --user neo4j
A masstin timeline in Memgraph Lab: every login of the hour the attacker came in, then one query from the catalogue returns the chronologically valid path from the attacker’s IP to the workstation. DFIR Madness “Szechuan sauce” case.
Reconstruct the attacker’s path
The temporal path query finds the chronologically coherent route between two nodes:
MATCH path = (start:host {name:'10.10.1.50'})-[*]->(end:host {name:'SRV-BACKUP'})
WHERE ALL(i IN range(0, size(relationships(path))-2)
WHERE localDateTime(relationships(path)[i].time) < localDateTime(relationships(path)[i+1].time))
RETURN path ORDER BY length(path) LIMIT 5

Hunt without knowing what to look for
Once the timeline exists, graph-hunt-csv asks the question an analyst brings to the first day: of everything that happened after the compromise, what is new for this network? No database, no plugin: every window connection is measured against the baseline, the only number you choose is the false discovery rate, and the report explains each finding in words. No hint needed: on the public Los Alamos set (21 million logins, 749 labelled red-team events) the red-team machine comes out at rank 1 and 204 connections survive the 5 % false discovery rate. The 22-minute run is cut in the recording.
masstin -a graph-hunt-csv -f timeline.csv --investigation-from "2026-03-15 00:00:00" \
--report hunt.md -o hunt.csv
How it decides, and what it found on the public LANL set, is in the graph-hunt post.
Available Actions
| Action | Description |
|---|---|
parse-windows |
Parse Windows EVTX from directories or files (supports compressed triage packages) |
parse-linux |
Parse Linux logs: auth.log, secure, messages, audit.log, utmp, wtmp, btmp, lastlog |
parser-elastic |
Parse Winlogbeat JSON logs exported from Elasticsearch |
parse-cortex |
Query Cortex XDR API for network connections (RDP/SMB/SSH) |
parse-image |
Auto-detects OS per partition. Open E01/dd/VMDK images (including streamOptimized), scan evidence folders (-d /evidence/), mounted volumes (-d D:), or --all-volumes. Detects BitLocker. NTFS → EVTX + UAL + VSS + Tasks. ext4 → Linux logs. All merged into one CSV |
parse-massive |
Like parse-image but also includes loose EVTX and log files from -d directories — use when evidence is a mix of disk images and extracted triage packages |
carve-image |
Last resort recovery. Scans raw disk for EVTX chunks in unallocated space. Recovers lateral movement events after logs + VSS are deleted. Use --carve-unalloc for unallocated-only scan |
parse-cortex-evtx-forensics |
Query Cortex XDR API for forensic EVTX collections across multiple machines |
parse-custom |
Parse arbitrary text or JSON logs (VPN, firewall, proxy, web app, Mordor / OTRF) using YAML rule files with csv, regex, keyvalue and json extractors. Bring your own log format — see masstin custom parsers |
merge |
Combine multiple CSVs into a single chronological timeline |
load-neo4j |
Upload timeline to Neo4j for graph visualization |
load-memgraph |
Upload timeline to Memgraph for in-memory graph visualization |
merge-neo4j-nodes |
Fuse two :host graph nodes after loading (e.g., when an IP and a hostname were not auto-unified). No APOC required |
merge-memgraph-nodes |
Same as above, for Memgraph. No MAGE required |
graph-hunt-csv |
Statistical lateral movement hunt straight from the timeline CSV. Every connection after --investigation-from is measured against the baseline; Benjamini-Hochberg at --alpha decides; --seed reconstructs chains, --report writes the analyst report, --sigma joins Hayabusa / Chainsaw hits. No database. See graph-hunt post |
graph-hunt |
Same hunt on a graph loaded into Memgraph with --ungrouped. Everything is computed in memory; no MAGE needed |
graph-hunt-neo4j |
Same hunt on Neo4j (--db <name> for named databases). No GDS plugin needed |
parse-windows vs parse-image vs parse-massive — what each one actually processes
The three Windows-side actions differ by what you feed them, not by the parser underneath — EVTX dispatch is the same in all of them (Provider.Name routing, unknown providers silently skipped).
| Source | parse-windows |
parse-image |
parse-massive |
|---|---|---|---|
| Loose EVTX files and directories | ✅ | ❌ | ✅ |
| Recursive ZIP walk (unlimited nesting) | ✅ | ❌ | ✅ |
Provider.Name fallback for archived / renamed EVTX |
✅ | ✅ | ✅ |
| Forensic disk images (E01, VMDK, raw, dd, img) | ❌ | ✅ | ✅ |
NTFS walker → winevt/Logs + VSS recovery |
❌ | ✅ | ✅ |
UAL databases (LogFiles/Sum/*.mdb) |
❌ | ✅ | ✅ |
Scheduled Tasks XML (System32/Tasks/) |
❌ | ✅ | ✅ |
| MountPoints2 (NTUSER.DAT registry hive) | ❌ | ✅ | ✅ |
| Triage detection (KAPE / Velociraptor / UAC / Cortex XDR) with per-source labels | ❌ | ❌ | ✅ |
Loose-artifact promotion of -d directories into the pipeline |
❌ | ❌ | ✅ |
Rule of thumb:
- Folder / ZIP / single EVTX →
parse-windows - Forensic image (
.e01,.vmdk,.raw) →parse-image - Mixed evidence (image + zip + triage + loose files) →
parse-massive
In all three, any EVTX whose Provider.Name matches a channel masstin knows is parsed — regardless of filename. Archived logs (Security-YYYY-MM-DD-HH-MM-SS.evtx produced by the “Archive the log when full” retention policy), operator-renamed copies, and extracts from third-party tooling all route correctly. See Archived EVTX post for the full story.
Documentation
Artifacts
| Artifact | Article | |
|---|---|---|
| Security.evtx (14 Event IDs) | Security.evtx and lateral movement | |
| Terminal Services EVTX | Terminal Services EVTX | |
| SMB EVTX | SMB EVTX events | |
| WinRM, WMI-Activity + Scheduled Tasks | PowerShell Remoting (Event 6), remote WMI (Event 5858) and remotely created tasks (Author field) | WinRM, WMI & Tasks |
| MountPoints2 (NTUSER.DAT) | Remote share connections from registry — user→server with timestamps, survives log clearing | MountPoints2 |
| Linux logs | Linux forensic artifacts | |
| Winlogbeat JSON | Winlogbeat artifacts | |
| Cortex XDR | Cortex XDR artifacts | |
| Custom parsers (BYO logs) | VPN, firewall, proxy, web app — define your own log format with a YAML rule file and parse it like any other source. masstin custom parsers |
Output Format and Advanced Features
| Topic | Article |
|---|---|
| CSV columns, event_type, Event ID mapping, logon_id, detail | CSV Format and Event Classification |
| Forensic image analysis and VSS recovery | Recovering deleted logs from VSS |
| User Access Logging (UAL) | Server access history from ESE databases |
| vshadow-rs — pure Rust VSS parser | vshadow-rs |
Triage detection (KAPE / Velociraptor / Cortex) — automatic recognition of triage packages inside parse-image and parse-massive |
Triage detection in masstin |
| graph-hunt — statistical lateral movement detection: p-values against the network’s own baseline, false discovery rate, Hopper classes, seed chains, analyst report; from the CSV, Memgraph or Neo4j, no plugins | graph-hunt in masstin |
Graph Databases
| Database | Article |
|---|---|
| Neo4j | Neo4j and Cypher: visualization and queries |
| Memgraph | Memgraph: in-memory visualization |
$ comments