NTFS Alternate Data Streams
Hiding a payload in a file's named ADS keeps it off a normal directory listing, but the stream is fully indexed in the MFT.
Every file on an NTFS volume stores its main content in an unnamed $DATA attribute. NTFS also permits named $DATA attributes — Alternate Data Streams (ADS) — attached to the same file or directory. The contents of host.txt:payload do not appear in the file's reported size, do not show in a default dir listing, and are invisible to most applications that open only the default stream. This makes ADS a long-standing place to stash a second-stage binary, a script, or stolen data behind an innocuous-looking host file.
ADS is not malware-only — Zone.Identifier (the Mark-of-the-Web stream) is a legitimate ADS — but attackers abuse the same mechanism to carry executable content. Loaders such as Astaroth have staged payloads in streams and executed them with living-off-the-land binaries, and operators routinely hide droppers in :stream form to slip past tooling that inspects only default content.
How it works
A stream is addressed with the file:streamname syntax, and content can be written to or read from it with built-in tools:
:: Write a payload into a named stream, then list streams on the host file
type payload.exe > C:\Users\Public\notes.txt:svc.exe
dir /r C:\Users\Public\notes.txtThe host file notes.txt keeps its small visible size while the hidden stream carries the full payload. Execution typically relies on a LOLBin that accepts a stream path (e.g., wmic process call create, forfiles, or a script host), since cmd.exe will not launch a :stream path directly. The key forensic fact: every named stream still gets its own $DATA attribute in the host file's $MFT record.
Detection & analysis
Static analysis:
- Parse the
$MFTand enumerate all$DATAattributes per record. Any record with a named (non-empty attribute name)$DATAbeyondZone.Identifieris worth review; a stream containing anMZ/PE header is a strong indicator. Tools:MFTECmd(Eric Zimmerman),AlternateStreamView, PowerShellGet-Item -Stream *. - Resident streams store their bytes directly in the MFT record, so small payloads can be recovered straight from a
$MFTdump even after the host file is touched; non-resident streams point to data runs you can carve. - Triage with
dir /rorGet-Content -Stream: legitimate streams are almost alwaysZone.Identifier,SmartScreen, orWof. Anything else — especially executable or script content — should be extracted and analyzed.
Dynamic analysis:
- Sysmon Event ID 15 ("FileCreateStreamHash") logs creation of an alternate data stream and hashes its content; this is the highest-fidelity live signal for ADS staging. Correlate the writing process against expectations.
- Process auditing (Event ID 4688 / Sysmon 1) often captures the execution LOLBin referencing a
:streampath on its command line — a near-unambiguous tell.
Detection rule hint: Alert on Sysmon Event ID 15 where the stream name is not in an allowlist (Zone.Identifier, SmartScreen, Wof) and the hashed content begins with a PE or script signature; separately, flag any process command line containing a : stream path passed to a script host or wmic. Recovery path: dump named $DATA attributes from the $MFT and carve non-resident stream data runs from unallocated space.