NTFS 允许一个文件拥有多个 $DATA 属性。第一个没有名字,保存文件的主体内容。其余的 $DATA 属性都是带名字的,作为附着在同一个文件上的并行数据流存在。这些附加的数据流就是备用数据流(Alternate Data Streams,ADS)。
语法
可以在 PowerShell 或 cmd 里读写 ADS:
echo hidden text > notes.txt:secret
type notes.txt:secret
notes.txt 在资源管理器和 dir 中都显示为空 —— 它的主 $DATA 是 0 字节。但名为 secret 的备用流里却装着你的文本。从用户角度看,文件表现得完全正常;备用流就这样隐身随行。
合法使用 ADS 的场景
Windows 自己也会用 ADS 做自己的记录。最常见的是 Zone.Identifier,它会附着在从互联网下载的每一个文件上,里面是一段描述来源 URL 与安全区的小段文本。这正是「该文件来自其他计算机」提示出现的原因。
其他合法用途:
- 用于键盘布局文件的
$KSP - 用于 Outlook 附件的
OECustomProperty - 各种缩略图与搜索索引相关的数据流
为什么攻击者偏爱 ADS
凡是住在主数据流之外的内容,通常对以下对象都是隐形的:
- 只显示文件大小的文件夹视图(显示的是无名流的大小);
- 仅扫描默认数据流的杀毒引擎;
- 没有显式查看数据流的分析师人工排查。
一个常见的套路是:把 payload 丢进 legit-document.docx:payload.exe,通过 WMI 触发执行。文件看起来就是一个 Word 文档,直到你提出正确的问题之前它一直如此。
怎么检测
dir /R 会列出某个目录下每个文件的每一条数据流。输出中,命名流的大小会显示在流名旁边:
1,234,567 legit-document.docx
45,056 legit-document.docx:payload.exe:$DATA
PowerShell 中更简洁的等价用法:
Get-Item legit-document.docx -Stream *
为什么 $MFT 是更好的观察角度
逐个文件的枚举,可能会漏掉那些你压根没想到要去检查的文件上的备用流。$MFT 不存在这个问题:每一个属性就在记录里。遍历 MFT 并枚举每个条目的 $DATA 属性 —— 无论命名还是无名 —— 就能在一次扫描中拿到整卷所有数据流的完整清单。
在排查时,这正是「记得别忘了查 ADS」与「我已经把所有 ADS 都查过了」的区别。