Windows Alternate Data Streams FG

1. Alternate Data Streams

  • ADS was first introduced to NTFS in Windows NT 3.1 and was Microsoft’s attempt at implementing filesystem forks in order to maintain compatibility with other filesystems like Apple’s HFS+ and Novell’s NWFS and NSS.

  • In NTFS – files consists of attributes, security settings, mainstreams and alternate streams. By default, only the mainstream is visible.

  • ADS has been used to store metadata, like file attributes, icons, image thumbnails.

  • Great way to hide data using NTFS.

  • Can be scanned by antivirus (Windows Defender Smartscreen is ADS aware).

  • Does not change the MD5 hash of the file.

  • Deleted once copied to a fat32.

  • Cannot be disabled.

  • [filename.extension]:[alternate_stream_name]:$DATA


2. Alternate Data Streams in Command Prompt

The demonstrations below are the basics of creating and viewing alternate data streams on a file and directory. The ADS demo will need a elevated command prompt (cmd.exe) and also an elevated PowerShell or PowerShell ISE window. You should understand that just because something isn’t viewable by normal means, doesn’t mean something isn’t hidden. It thus becomes important to understand the commands used to enumerate, recognize indicators, and list contents for ADS.


Perform steps below in an elevated CMD shell.

1. Creating a regular data stream on a file
C:\windows\system32>echo Always try your best > reminder.txt (1)

C:\windows\system32>dir reminder.txt (2)
 Directory of C:\windows\system32
 02/27/2021 07:13 PM                 25 reminder.txt
                1 File(s)            25 bytes
                0 Dir(s) 20,060,768,688 bytes free

C:\windows\system32>type reminder.txt (3)
Always try your best
1 echo content Always do your best into new file called reminder.txt.
2 dir, for files, displays the file name extension and size in bytes.
3 type displays contents of a text file, showing Always do your best.


2. Creating an Alternate Data Stream on a file
C:\windows\system32>echo social security numbers > reminder.txt:secret.info (1)

C:\windows\system32>dir reminder.txt (2)
 Directory of C:\windows\system32
 02/27/2021 07:13 PM                  23 reminder.txt
                 1 File(s)            23 bytes
                 0 Dir(s) 20,060,712,960 bytes free

C:\windows\system32>type reminder.txt (3)
Always try your best
1 echo content social security numbers into the ADS :secret.info of reminder.txt.
2 dir shows no visible change to reminder.txt even after previous added ADS content.
3 type shows no visible change to content of reminder.txt even after previous added ADS content.

Refs: dir / echo / type


3. Viewing an Alternate Data Stream on a file.
C:\windows\system32>more < reminder.txt:secret.info (1)
social security numbers

C:\windows\system32>notepad reminder.txt:secret.info (2)

C:\windows\system32>dir /R reminder.txt (3)
 Directory of C:\windows\system32
 02/27/2021 07:13 PM                   23 reminder.txt
                                       26 reminder.txt:secret.info:$DATA
                1 File(s)              23 bytes
                0 Dir(s)   20,060,557,312 bytes free

C:\windows\system32>type reminder.txt:secret.info (4)
The filename, directory name, or volume label syntax is incorrect.
1 Read contents of reminder.txt:secret.info into more, showing ADS content social security numbers.
2 Shows another way to view ADS content using notepad.
3 dir /R displays the ADS info (not the same as listing the ADS contents however). $DATA will be discussed later.
4 Unfortunately, some commands and applications like the type are unable to list ADS content.


4. Creating and Viewing an Alternate Data Stream on a directory
C:\windows\system32>mkdir kids (1)

C:\windows\system32>echo top-secret information > kids:hidden.txt (2)

C:\windows\system32>dir /R kids (3)
 Directory of C:\windows\system32\kids
 02/27/2021 07:29 PM      <DIR>           .
                                       25 .:hidden.txt:$DATA
 02/27/2021 07:29 PM      <DIR>           ..
               0 File(s)                0 bytes
               2 Dir(s)    20,060,160,000 bytes free

C:\windows\system32>more < kids:hidden.txt (4)
top-secret information
1 mkdir creates a directory called kids.
2 echo writes content top-secret information in ADS to kids:hidden.txt.
3 dir /R shows ADS info for kids directory. Notice the ADS hidden.txt created earlier and the main stream $DATA.
4 more shows ADS contents of kids:hidden.txt and we see top-secret information.


3. Alternate Data Streams in PowerShell

1. Creating a regular data stream on a file.
PS C:\windows\system32>echo "Always do your best" > reminder.txt (1)

PS C:\windows\system32>Get-ChildItem .\reminder.txt (2)
    Directory: C:\windows\system32
Mode                LastWriteTime        Length  name
----                -------------        ------  ----
-a----           2/28/2021  2:40 AM          44   reminder.txt

PS C:\windows\system32>Get-Content reminder.txt (3)
Always do your best
1 echo content Always do your best into a new file called reminder.txt.
2 Get-ChildItem, just like dir example, will show a file’s attributes, last modified time (LastWriteTime), size (Length), and name.
3 Get-Content shows the content of the file reminder.txt: Always do your best.


2. Creating an Alternate Data Stream on a file.
PS C:\windows\system32>Set-Content .\reminder.txt -Value "social security numbers" -Stream secret.info (1)

PS C:\windows\system32>Get-Childitem reminder.txt (2)
    Directory: C:\windows\system32
Mode                LastWriteTime        Length  name
----                -------------        ------  ----
-a----           2/28/2021  2:41 AM          44   reminder.txt

PS C:\windows\system32>Get-Content reminder.txt (3)
Always do your best
1 Set-Content writes new or replaces existing content in a file; Using -Value and -Stream to create an ADS on reminder.txt.
2 Get-Childitem shows no visible change to reminder.txt even after previous added ADS content.
3 Get-Content shows no visible change to content of reminder.txt even after previous added ADS content.


3. Viewing an Alternate Data Stream on a file.
PS C:\windows\system32>Get-Item reminder.txt -Stream * (1)
PSPath        : Microsoft.PowerShell.Core\FileSystem::C:\windows\system32\reminder.txt::$DATA
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\windows\system32
PSChildName : reminder.txt::$DATA
PSDrive       : C
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : C:\windows\system32\reminder.txt (2)
Stream        : :$DATA (3)
Length        : 44

PSPath        : Microsoft.PowerShell.Core\FileSystem::C:\windows\system32\reminder.txt:secret.info
PSParentPath  : Microsoft.PowerShell.Core\FileSystem::C:\windows\system32
PSChildName  : reminder.txt:secret.info
PSDrive       : C
PSProvider    : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName      : C:\windows\system32\reminder.txt
Stream        : secret.info (4)
Length        : 25

PS C:\windows\system32>Get-Content reminder.txt -Stream secret.info (5)
social security numbers
1 Get-Item with the -Stream option allows us to see all streams for *reminder.txt.
2 FileName property provides the full path info for reminder.txt.
3 Stream property lists $DATA which is the main stream and commonly expected on most files. $DATA is the actual content.
4 Stream property lists secret.info which is an ADS to be investigated since it is outside the norm.
5 Get-Content with option and value -Stream secret.info gets us our ADS content, social security numbers.
The last command can be further improved to list only the FileName and Stream properties.

Get-Item reminder.txt -Stream * | select FileName,Stream

4. Malicious Alternate Data Streams

In this demonstration, we will show how malicious logic can be embedded in an Alternate Data Stream to execute on a system. There are a plethora of ways a malicious ADS could be triggered to exploit vulnerabilities in a system and grant access or establish persistence for a bad guy.

1. Creating a Malicious Alternate Data Stream
PS C:\windows\system32> Write-Output "Nothing to see here!" > test.txt (1)

PS C:\windows\system32>Add-Content -Path .\test.txt -Value 'Dim oShell' -Stream 'secret.vbs' (2)
PS C:\windows\system32>Add-Content -Path .\test.txt -Value 'Set oShell = Wscript.CreateObject ("Wscript.Shell")' -Stream 'secret.vbs'
PS C:\windows\system32>Add-Content -Path .\test.txt -Value 'oShell.run "cmd /k CD C:\Program Files & ping 8.8.8.8" ,1 , true ' -Stream 'secret.vbs'

PS C:\windows\system32>Get-Content .\test.txt (3)
Nothing to see here!

PS C:\windows\system32>Get-Content .\test.txt -Stream secret.vbs (4)
Dim oShell
Set oShell = Wscript.CreateObject ("Wscript.Shell")
oShell.run "cmd /k CD C:\Program Files & ping 8.8.8.8" ,1 , true
1 Write-Output functions like echo and sends the content Nothing to see here! to a new file called test.txt.
2 Add-Content lines add some Visual Basic Studio (VBS) code to the ADS secret.vbs on test.txt.
3 Get-Content shows no visible change to test.txt even after previous added ADS content.
4 With -Stream secret.vbs we see our ADS content.


2. Executing a Malicious Alternate Data Stream
PS C:\windows\system32>wscript .\test.txt:secret.vbs (1)
_opens CMD.exe and pings google_
1 wscript part of Windows Script Host allows us to run the VBS code contained in .\test.txt:secret.vbs


3. Output
Pinging 8.8.8.8 with 32 bytes of data: (1)
Reply from 8.8.8.8: bytes=32 time=6ms TTL 113
Reply from 8.8.8.8: bytes=32 time=6ms TTL 113
Reply from 8.8.8.8: bytes=32 time=5ms TTL 113
Reply from 8.8.8.8: bytes=32 time=5ms TTL 113

Ping statistics for 8.8.8.8:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip in milli-seconds:
    Minimum = 5ms, Maximum = 6ms, Average = 5 master

C:\Program Files>
1 Output of VBS code is a simple ping to Google. Not so malicious after all…​


3. Does file hash change if we alter the Alternate Data Stream?
C:\Program Files>cd C:\windows\system32 (1)

C:\windows\system32>certutil -hashfile test.txt MD5 (2)
MD5 hash of test.txt:
cb73eeca4f440ee9c6e16ad3cfddb10a
CertUtil: -hashfile command completed successfully.

C:\windows\system32>notepad test.txt:secret.vbs (3)
_enter some extra code or remove some code_

C:\windows\system32>more < test.txt:secret.vbs (4)
Dim oShell
Set oShell = Wscript.CreateObject ("Wscript.Shell")
oShell.run "cmd /k CD C:\Program Files & ping 8.8.8.8" ,1 , true
words and such

C:\windows\system32>certutil -hashfile test.txt MD5 (5)
MD5 hash of test.txt:
cb73eeca4f440ee9c6e16ad3cfddb10a
CertUtil: -hashfile command completed successfully.
1 Change directories to C:\windows\system32 where test.txt is.
2 Add or remove some code to :secret.vbs with notepad.
3 Verify changes to ADS content with more.
4 Runs certutil again to show the hash hasn’t changed.
Changing the ADS content of a file does not affect the file hash. Only changing the actual content on the main stream ($DATA) will result in a change in the file hash. This is important because an operator cannot assume a file was not tampered with just because the file hash has not changed.