Have you ever wondered how a file in a file listing is shown with size 0 bytes but can still contain data? Or maybe wondered where all that meta data is stored, how malware can infect files or just how you can “hide” stuff in a file?
Let’s talk about Alternate Data Streams to learn more.
ADS - Alternate Data Streams
When you hear “Alternate Data Streams” you may think about resource forks in Mac OS HFS. But we’re talking about Windows and NTFS. Back in the days of Windows NT 3.1 (ha!), NTFS streams were actually implemented to support the Mac resource forks.
Let’s fire up a cmd prompt and start with a practical example:
As you can see, we redirected our echo to the file, but specified another name after the colon. This is the name of the stream, which now contains our “Hello World!”. Note, though, that our created file is still being displayed as having a file size of 0 bytes.
Seeing the streams
What we just did, was to write data to a data stream other than the original data stream, a.k.a. the file itself.
We could go on and add another stream like this:
echo more stuff > hello.txt:mystream.
After creating our streams, how do we actually look at them?
We can (on Win >= 8) use the
Get-Content Cmdlets in Powershell:
The above command will show us the streams we’ve created, plus the default one, also called unnamed data stream. When looking at the sizes/lengths, we can also see that the unnamed stream is still only 0 bytes (which can make it hard for users to detect disk usage in case of the presence of some large alternate data streams).
$DATA is actually the stream type. So our unnamed default stream is literally just an unnamed stream, while our “hidden” stream would be an alternate stream with a name, which could also be written like
Fun fact: if we were to create a hash of our
hello.txt file (
Get-FileHash hello.txt), then added data to an ADS, the hash would not change.
Getting the contents out
To get the content out again, we can use the
What’s so interesting?
So what’s so interesting about the alternate data streams, being old and not very much used?
Well, besides storing simple text strings, we can also store executable code in a stream. The fact that it doesn’t show in the file size, won’t change the hash, doesn’t come up in explorer / in the UI and that ADS can’t be disabled, makes it an ideal hiding place for malicious software (and it has indeed been used by malware in the past).
Nowadays, AV software usually scans these alternate data streams too (just try it out).
Storing an executable in an ADS
Let’s see how it can be done by storing the calc.exe in an ADS called
exestream of our
hello.txt. We will use the
Set-Content Cmdlet and explicitly specify byte encoding and a readcount of 0, to read the file in one read operation. The
Get-Command is only used to not type out the path.
If you have some known malware on your system and store it in an ADS, you will notice that it is detected nonetheless. Well, let’s hope so :-).
Launching the hidden code
Now that we have a binary in our
exestream, we can launch it, e.g., via
wmic (Windows Management Instrumentation). I use
Resolve-Path, again, only not to type out the full path.
If it works, you should see the calculator pop up.
Finding alternate data streams
Now that we know what a data stream is and what we can do with it, let’s see how we can list all the files in and below a directory that actually have alternate data streams (and maybe check that everything is in order).
Note: one of the more common ADS that you will find is
Zone.identifier. These are usually for files that were downloaded and might be used to indicate this fact to the user; see info at the Microsoft docs.
Have fun playing around with Alternate Data Streams!