Zone.Identifier 文件和 NTFS 数据流

使用 Windows 资源管理器,将 Windows 中的文件复制到 WSL 文件系统中时发现,目标路径下会多出一个 Zone.Identifier 后缀的文件:

foo.txt
foo.txt:Zone.Identifier

之所以会生成这个文件,和 Windows 的一个安全特性有关,这个安全特性利用 NTFS 文件系统的数据流,为文件保存了一些额外的不可见信息。而资源管理器在复制文件时,将文件的数据流也一起复制过去了。这个多出来的 Zone.Identifier 后缀文件保存的便是看不见的数据流内容。这个文件对 WSL 系统没什么作用,可以直接删除。不过我们还是可以了解一下这个文件的来龙去脉。

Windows 的安全警告

Windows 有一个安全特性,当用户打开从网络下载的文件时,系统会弹出如下的安全警告消息框:

安全警告

打开文件属性,可以看到 此文件来自其他计算机,可能被阻止以帮助保护该计算机 的安全提示:

文件属性
为什么我的系统没有弹出「安全警告」消息框?

该安全特性可以通过「本地组策略编辑器」启用和关闭:

  1. 运行 gpedit.msc
  2. 打开 用户配置 > 管理模板 > Windows 组件 > 附件管理器
    本地组策略编辑器
  3. 双击打开 文件附件默认风险级别,选中 已启用,并设置默认风险等级为 高风险
    文件附件默认风险级别

那系统又是如何知道这个文件来自其他计算的呢?原来,当浏览器从互联网上下载文件后,还会将文件来源的数据写入下载文件的「NTFS 数据流」中。

NTFS 数据流

NTFS 数据流的正式名称为 Alternate Data Streams,缩写是 ADS ,中文可以翻译成「备用数据流」。这是 NTFS 文件系统的一个特性,它允许在文件的内容之外保存额外的数据,每个文件可以存在多个数据流文件。简单地说,就是在 NTFS 文件系统中,每个文件名可以对应不止一份内容。虽然在资源管理器中用户只能看到默认的文件内容,但是可以通过一些方法和工具来访问不可见的数据流文件。

写入数据流内容

Windows 用冒号 : 来分隔文件名和数据流文件名。简单使用 echo 命令便可以实现写入:

cmdecho "Test Text">D:\test.txt:TestStream

或使用 PowerShell 命令:

powershellset-content -Path D:\test.txt -Stream TestStream -Value "Test Text"

其中 D:\test.txt 是要写入数据流的文件名,而 TestStream 则是数据流的名称,Test Text 则是写入的数据流内容。

注意
此处 D 盘必须使用 NTFS 文件系统。

查看数据流内容

使用如下命令查看数据流内容:

powershellget-content -Path D:\test.txt -Stream TestStream

也可以直接用记事本等应用打开数据流:

powershellnotepad D:\test.txt:TestStream

找出文件的数据流

使用 Sysinternals 的命令行工具 Streams 可以找出和删除文件的数据流。使用方法如下:

usage: streams.exe [-s] [-d] <file or directory>
-s     Recurse subdirectories
-d     Delete streams
-nobanner
       Do not display the startup banner and copyright message.

使用以下命令查看文件的数据流:

powershellstreams D:\test.txt

还可以递归查找文件夹以及子文件夹内文件的数据流:

powershellstreams -s D:\
顺便一提

文件夹也是可以存在数据流文件的。

也可以用 PowerShell 命令:

powershellget-item -Path D:\test.txt -Stream *

在命令行提示符下使用 dir /r 命令可以列出目录下所有文件及其数据流。

删除文件的数据流

使用 streams 命令删除文件的全部数据流:

powershellstreams -d D:\foo.pdf

或使用 PowerShell 命令删除文件所有数据流:

powershellremove-item -Path D:\foo.pdf -Stream *

也可以删除指定的数据流:

powershellremove-item -Path D:\foo.pdf -Stream Zone.Identifier

以及清空数据流内容:

powershellclear-content -Path D:\foo.pdf -Stream Zone.Identifier

Zone.Identifier 和 SmartScreen 数据流

streams 命令查看 D:\foo.pdf 文件包含的数据流:

powershellget-item -Path D:\foo.pdf -Stream *

返回结果:

PSPath        : Microsoft.PowerShell.Core\FileSystem::D:\foo.pdf::$DATA
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::D:\
PSChildName   : foo.pdf::$DATA
PSDrive       : D
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : D:\foo.pdf
Stream        : :$DATA
Length        : 36158778

PSPath        : Microsoft.PowerShell.Core\FileSystem::D:\foo.pdf:Zone.Identifier
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::D:\
PSChildName   : foo.pdf:Zone.Identifier
PSDrive       : D
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : D:\foo.pdf
Stream        : Zone.Identifier
Length        : 223

这个 Zone.Identifier 数据流中保存的就是文件的来源。使用下列命令查看该数据流的内容:

powershellget-content -Path D:\foo.pdf -Stream Zone.Identifier

内容如下:

[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://github.com/tabris17/traymond/releases
HostUrl=https://objects.githubusercontent.com/... ...

其中 ZoneId 表示文件来源,它可以是以下的值:

对于某些下载文件,还会多出一个名为 SmartScreen 的数据流。比如这个 foo.exe 文件:

txtPSPath        : Microsoft.PowerShell.Core\FileSystem::D:\foo.exe::$DATA
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::D:\
PSChildName   : foo.exe::$DATA
PSDrive       : D
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : D:\foo.exe
Stream        : :$DATA
Length        : 124120680

PSPath        : Microsoft.PowerShell.Core\FileSystem::D:\foo.exe:SmartScreen
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::D:\
PSChildName   : foo.exe:SmartScreen
PSDrive       : D
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : D:\foo.exe
Stream        : SmartScreen
Length        : 7

PSPath        : Microsoft.PowerShell.Core\FileSystem::D:\foo.exe:Zone.Identifier
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::D:\
PSChildName   : foo.exe:Zone.Identifier
PSDrive       : D
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : D:\foo.exe
Stream        : Zone.Identifier
Length        : 156

D:\foo.exe:SmartScreen 文件内容如下:

Anaheim

如果一个可执行文件包含此数据流,Windows 会弹出如下的警告对话框:

SmartSreen

Exploit

在早年 Windows XP 时代,NTFS 刚在用户电脑中普及,有些病毒和木马程序会寄生在文件的数据流中。不过现在的杀毒软件都能查杀此类病毒。另外,专业的取证软件也不会落下数据流中隐藏的信息,利用 NTFS 数据流来隐藏个人数据没有任何安全性可言。

参考资料

  1. MS-FSCC: Zone.Identifier Stream Name
  2. About URL Security Zones