Skip to content
Anti-Forensicintermediate

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:

cmd
:: 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.txt

The 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 $MFT and enumerate all $DATA attributes per record. Any record with a named (non-empty attribute name) $DATA beyond Zone.Identifier is worth review; a stream containing an MZ/PE header is a strong indicator. Tools: MFTECmd (Eric Zimmerman), AlternateStreamView, PowerShell Get-Item -Stream *.
  • Resident streams store their bytes directly in the MFT record, so small payloads can be recovered straight from a $MFT dump even after the host file is touched; non-resident streams point to data runs you can carve.
  • Triage with dir /r or Get-Content -Stream: legitimate streams are almost always Zone.Identifier, SmartScreen, or Wof. 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 :stream path 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.

Votes

Comments(0)