The ":Zone.Identifier:$DATA" alternate data stream (ADS)
- John
- 4 days ago
- 3 min read
This post is one of a series providing implementation examples of Windows API Functions, Types, Enums and Consts using VBA. The code in this post can be used as-is, however, if you regularly (or even just occasionally) work with Windows API declarations in VBA, you may want to see the posts Automatically add Windows API declaration(s) and Using 'F1' to view Windows API web pages which explain some of the functionality that can be added to the VBE by VBE_Extras.
As well as relating to the Windows API, this post is the third of three relating to alternate data streams (ADS). If you haven't already, I suggest you read the first two posts in the series Getting the alternate data streams (ADS) for a file or folder and Reading, writing and deleting alternate data streams (ADS) which covers the basic principles of streams, how to get the names and data of streams and how to write and delete streams.
So, what's this ":Zone.Identifier:$DATA" stream then?
First, take a look at the stream and its data. Find a file you have downloaded from the internet, likely somewhere in your Downloads folder. If you don't have one to hand, you could download the VBE_Extras installer from this page VBE_Extras (why wouldn't you!).
Using the code from the Reading, writing and deleting alternate data streams (ADS) post, update the msPATH_TO_FILE_OR_FOLDER Const to the path of the downloaded file and run TestGettingStreams(). You should see that the downloaded file has a stream named ":Zone.Identifier:$DATA" and its contents (if you used the VBE_Extras installer) would be the following (or very similar) ...
[ZoneTransfer] | ZoneId=3 | ReferrerUrl=https://www.thevbahelp.com/vbe-extras-download | HostUrl=https://www.thevbahelp.com/_files/archives/5d1600_bdc7660df1274b1ab75fc1a161c5f3e3.zip?dn=VBE_Extras_Setup.zip... if you don't see the stream, read on and you will see why not.
So what does all this mean? The key part is the "ZoneId" and the associated value of 3 which means that the file came from the internet ... which, depending on the settings on your device, means that the file will be "blocked". Yes ... this is the "Mark of the web". When this ZoneId is present in this stream, VBA code will typically be blocked from executing until the file is "unblocked" ... for more, including how to unblock a file manually, see my Unblock a file containing VBA code post and there's an article here (3rd party link) https://www.cloudsek.com/blog/malicious-macros-and-zone-identifier-alternate-data-stream-information-bypass with more info on zone identifiers and zone ids.
So, if you didn't see this stream when running TestGettingStreams() then it's because the file was already unblocked (or was never blocked ... if you didn't use a file that was downloaded from the internet).
So now we know this is the "Mark of the web", there are two obvious questions:
Can we detect the presence of this Stream (i.e. can we tell if a file is blocked)?
Can we remove the Stream (i.e. can we unblock a file)?
... and, for both of these questions, the answer is "yes we can" (based on the code in the previous two posts).
And not only can we do that, it's also possible to abstract away some of the complexity because ideally all we want to have to do is call an IsFileBlocked() and/or an UnblockFile() Function. So here you go ...
... these two Functions can go in the "UtilsStreams" Module from the Reading, writing and deleting alternate data streams (ADS) post or in a stand-alone standard Module if you want.
Note that these two Functions only look for the stream, not the contents of the stream. If you manually unblock a file using the "Unblock" checkbox in the file properties dialog, the ZoneId isn't adjusted to something "less risky" ... the entire stream is removed. Hence this code does the same.


Comments