Hostwinds Blog
Search results for:
Since 1995, the Microsft Windows NTFS file system has supported streams. In fact, all NTFS "files" are actually streams. What we normally think of as a file in NTFS is more precisely called a default data stream. A default data stream is unnamed. What's an unnamed data stream? Consider the NTFS fully qualified filename format:
file-name:stream-name:stream-type
From left to right, we have:
An example follows:
myTextFile.txt
This is a default data stream. As mentioned, default data streams are unnamed. This can be seen in its fully qualified filename form:
myTextFile.txt::$DATA
The fact that there's nothing between the two colons (::) indicates that this is an unnamed data stream. For a default data stream, we do not need to use the fully qualified filename, although we can. For example, from the Windows command prompt, the following two commands open precisely the same default data stream:
notepad myTextFile.txt
notepad myTextFile.txt::$DATA
To simplify things, we will use the term "file" in place of the more accurate "default data stream".
You can create a named stream in a file using normal NTFS naming conventions. For example, from the command prompt, run the following:
notepad foo.docx:bar.txt
Select Yes when asked if you want to create a new file. Next, type the following content:
This is the named stream "bar.txt" that is in (attached to) the file "foo.docx".
Save and exit Notepad.
When you run the dir command, you will see a file named foo.docx whose size, interestingly, is 0 bytes. However, when you run the dir /r command, you will see the named data stream you just created, whose size is 80 bytes:
These two stream sizes make sense in that stream foo.docx has no content while stream foo.docx:bar.txt has 80 bytes worth of content. To help elucidate this, add some content to the default data stream, as follows:
notepad foo.docx
Enter the following text:
This is the default data stream (file) named "foo.docx", which has one named data stream attached to it, called "bar.txt".
Save and exit Notepad.
Run dir /r again and note that the default data stream foo.docx now contains 120 bytes of data:
Because of this, we can tell that the two streams consume 200 bytes on the volume. That said, running the unadorned dir command does provide somewhat misleading information - it implies that foo.docx only contains 120 bytes of data, which is inaccurate in the sense that when you delete foo.docx, you're actually releasing 200 bytes back to volume as available free space:
del foo.docx
dir /r
The moral of the story, perhaps, is to always use the /r switch. Which begs the question, how do you find all files that contain "hidden" streams? That topic is discussed next.
If we let the term "file" mean "default data stream" and "stream" mean "named data stream", then we can use PowerShell to find all files containing streams as follows.
Open a PowerShell command prompt and optionally run the following command (this suppresses possibly annoying file access denied error messages):
$ErrorActionPreference = "SilentlyContinue"
Next, run the following commands:
Get-ChildItem -Path \ -Recurse | Get-Item -Stream * | Where-Object Stream -ne ':$DATA' | Convert-Path
For the current volume, this returns a list of all files containing one or more streams. This PowerShell pipeline is explained as follows:
From a PowerShell command prompt, you can remove the stream bar.txt from file foo.docx as follows:
Remove-Item -Path .\foo.docx -Stream bar.txt
If the stream name has spaces, you must use quotes, as in:
Remove-Item -Path ".\Bob's Grandfather.png" -Stream "Image Info.txt"
The original intent of NTFS streams was to enable Apple Macintosh file interoperability but NTFS streams can be quite handy. For example, you may want to "embed" detailed information within family photograph files:
If the above image file were named "Bob's Grandfather.png", then you could add a stream (using PowerShell) containing detailed image information, as follows:
Set-Content -Path ".\Bob's Grandfather.png" -Stream "image-info.txt" -Value "This is Bob's grandfather (on his mother's side) in the Gold Rush Bar and Restaurant in Seattle, WA - circa 1856."
To view the image metadata you just set, run:
Get-Content -Path ".\Bob's Grandfather.png" -Stream "image-info.txt"
Note that the -Stream argument requires that you know the exact name of the stream (wildcards are not permitted). Recall that you can always obtain stream names using Get-Item (which accepts wildcards):
Get-Item -Path '.\Bob''s Grandfather.png' -Stream *
For the sought after stream name, look at the Stream property in the resulting output:
Other uses for NTFS streams can include:
Lastly, you may have noted that your volume contains a number of streams named Zone.Identifier. These streams are generally used by Windows for the storage of URL security zones, which determine whether a file should be trusted or not. An example showing how to view the contents of a Zone.Identifier stream follows:
Get-Content -Path .\sanders.net-May-2022.gz -Stream Zone.Identifier
And via the Windows command prompt:
notepad sanders.net-May-2022.gz:Zone.Identifier
Hopefully, you've found this article interesting; and perhaps you'll find some interesting uses for NTFS streams to boot.
Written by Karlito Bonnevie / May 24, 2022