| 3 minutes
NTFS (and also recent versions of ReFS) contains a feature called alternate data streams, which as the name implies allows you to associate multiple data streams with one filename. Nowadays this feature is mostly used for marking files downloaded from the internet, but there really is no restriction to what you can store in an alternate stream. So why don’t we use this feature to hide music “inside” a text file?
Creating the magical file
To create a new stream in a file (the file does not have to exist beforehand), use the below PowerShell snippet:
Add-Content 'path to file' -Stream 'stream name' -AsByteStream (Get-Content 'path to other file' -AsByteStream -ReadCount 0)
To list all the streams of a file, use the below PowerShell snippet:
Get-Item 'file' -Stream *
To get a specific stream, just substitute the asterisk with your desired stream name. If you ran the Add-Content
snippet correctly, you should see the default stream with an empty name, as well as one with the name of your newly added one.
Accessing the hidden music
Accessing the hidden data is the most difficult part. In theory, it is as simple as using the filename:stream
syntax, but in practise, most programs including Windows Explorer and the open dialog only use the default data stream and will not let you open any alternate ones. Luckily, for our desired usecase the solution is quite simple: m3u playlists. They are dead simple to write by hand and programmatically. For example, assuming you wish to use a stream called magic
, all you need to write in a playlist file is the following line:
[full path to file]:magic
Note that relative paths cannot be used for this based on my testing.
Fruits of our labor
The text file looks normal on first glance, but opening our m3u playlist in foobar2000 reveals that we have an entire hidden album that is fully playable using our playlist file! The only clue the average user has is the size on disk being much larger in Explorer, as it only reads the default stream for the size measurement: The size on disk value shows that our “4 byte” file is in reality taking 570 MB on disk!
Conclusion
While alternate data streams are quite neat, ultimately they really shouldn’t be used this way for serious purposes. You risk data loss if you move a file with them to an unsupported filesystem or use a program that might discard them either intentionally or unintentionally.
Bonus scripts!
While it’s certainly not the most robust thing in the world, this script allows you to add new streams in a much friendlier way. It also includes code for automatically generating a playlist if the PlaylistName
option is specified.
param (
[Parameter(Position=0,mandatory)]
[string] $File = "",
[Parameter(Position=1,mandatory)]
[string] $FileToAdd = "",
[Parameter(Position=2,mandatory)]
[string] $Stream = "",
[Parameter(Position=3)]
[string] $PlaylistName = ""
)
Add-Content $File -Stream $Stream -AsByteStream (Get-Content $FileToAdd -AsByteStream -ReadCount 0)
if ($PlaylistName -ne "") {
# default stream should be skipped as we are not interested in it
$streams = (Get-Item $File -Stream * | Where-Object {$_.Stream -ne ':$DATA'}).Stream
$streams | ForEach-Object {
"$PWD\${File}:$PSItem"
} | Out-File "$PlaylistName.m3u"
}
I used the below one-liner to add a whole album as alternate streams (assumes above script is saved as Add-Ads.ps1
in PATH):
Get-ChildItem 'path of album' | ForEach-Object { Add-Ads -File 'file name' -FileToAdd $PSItem -Stream $PSItem.Name -PlaylistName 'playlist name' }