Something I've recently found out and that I think it's brilliant is the possibility under Powershell 3.0 to handle file forks natively, which is something I long expected to see implemented. Some of you maybe know already that the NTFS Master File Table (MFT) supports storing forks of files in its tree. These forks are better know under Windows (starting from NT4) as Alternate Data Streams (ADS).
Until now the only way to know if a file had one or more ADS was to recur to our friend the DIR command which, since Windows Vista, offered a /R parameter to display the existing ADS and their somewhat secret size.
Here's a sample output of DIR /R:
dir /r | find "DATA" 26 Introducing Windows Server 2008 R2.pdf:Zone.Identifier:$DATA 26 Parkdale.exe:Zone.Identifier:$DATA 26 setup.exe:Zone.Identifier:$DATA 26 Understanding Microsoft Virtualization Solutions.pdf:Zone.Identifier:$DATA
Piping the output of 'DIR /R' to the 'find' command allows the immediate listing of the files that have multiple data streams only and exclude all other 'normal' files.
As you can see in the example, many files usually have an ADS named 'Zone.Identifier' (whose size is 26 bytes). This particular fork stored withing the same filename tells you whether the file has been downloaded from the Net or not. A typical content is:
with ZoneId values ranging (to my knowledge) from 0 to 4:
ZoneId=0: Local machine ZoneId=1: Local intranet ZoneId=2: Trusted sites ZoneId=3: Internet ZoneId=4: Restricted sites
If the ZoneId is equal to 3 or 4, when you will try to execute the file you will get a warning telling you "The publisher could not be verified. Are you sure you want to run this software?"...
Ok, now that we know how we can find the hidden ADS in our system, let's go back to our Powershell 3.0 command line to see in what ways it does help us in ADS management. Starting with this new version of Powershell, there is a way to find commands (using get-command) based on the parameters they accept (by adding the -parametername parameter). So let's run for instance:
gcm -ParameterName stream | select name
The returned list of cmdlets which support Alternate Data Streams is:
Add-Content Clear-Content Get-Content Get-Item Out-String Remove-Item Set-Content
For instance we can now retrieve the content of a fork the same way we did with
more < "Introducing Windows Server 2008 R2.pdf:Zone.Identifier"
more < "Introducing Windows Server 2008 R2.pdf:Zone.Identifier:$DATA"
Get-Content "Introducing Windows Server 2008 R2.pdf" -stream Zone.Identifier
Get-Content "Introducing Windows Server 2008 R2.pdf" -stream Zone.Identifier$DATA
What's more, we can retrieve the properties of this ADS with Get-Item:
$ads = get-item '.\Introducing Windows Server 2008 R2.pdf' -Stream zone.identifier
$ads | select filename,stream,length | fl
FileName : C:\folder\Introducing Windows Server 2008 R2.pdf Stream : Zone.Identifier Length : 26
We can also quickly remove the fork (in this case no warning pop-up will come to disturb our inner peace!) with
Remove-Item .\file.txt -Stream Zone.Identifier
This is a great step forward for Windows Powershell. Alternate Data Streams management has been left in the shade for almost a decade and today we can finally play with them like if they were standard user's files.
Great, isn't it?