Windows Alternate Data Streams FG Table of Contents 1. Alternate Data Streams 2. Alternate Data Streams in Command Prompt 3. Alternate Data Streams in PowerShell 4. Malicious Alternate Data Streams 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. Resources Abuse of Alternate Data Streams Hasn’t Disappeared SANS: Alternate Data Streams Overview Malwarebytes: Intro to Alternate Data Streams Alternate Data Streams: Out of the Shadows and into the Light