Accessing Alternate Data Streams from a Mac

Most of you have probably heard of alternate data streams, a semi-obscure means of attaching additional data to a file on Windows machines, specifically under NTFS (and now ReFS.) Alternate data streams, often abbreviated as ADS, were originally intended to store metadata about files. For example, in order to make NT a better file server for the Macintosh systems of the day when it was developed, Microsoft added ADS to allow Mac clients to save files with resource forks, the metadata used at the time for icons and other attributes of mac files. 

This would seem to imply that ADS are small pieces of data, but there’s really not any size limit imposed by the NTFS filesystem – nor is there a limit on the types of data.  You can store text like text files, source code, and XML and HTML documents or binary data, including images, audio files and even executables and libraries. ADS don’t have many applications on Windows today, but one very common use still is marking the source of a files downloaded using a web browser. IE, Edge, Chrome and other browsers will add an ADS named Zone.Identifier to a file downloaded using the browser with some info about the source, some browsers even adding other details about the file downloaded like source and referrer URLs.  A few DLP solutions mark files with ADS to help track files leaving the organization in ways they aren’t supposed to.  And of course, malicious parties can hide data or even executables inside ADS.

There are several means to access them on Windows, but just to be different, I want to demonstrate ways to access ADS using a Mac.  Next time we’ll look at some of the best ways on modern Windows systems to see ADS and manipulate them. Note:  this technique also works on Linux, I’ll likely be testing this for a future blog post.

For this demonstration I’m going to connect to a Windows file share over SMB, then locate ADS using the ls command, and access the contents with the xattr command.

First, I need to make sure I have some ADS to view:

I created file1.txt and its ADS, file1.txt:ads.txt using notepad.  You can see I used the command “dir/r” to list the contents of the C:\Temp directory.

Next, I need to connect to a file share from the Mac.  For simplicity I’ll be using the C$ default share, which gives me access to the entire C drive, as long as I use an account with administrative privileges.

 

Once I’ve connected, Finder shows I have access to the C drive on the target system:

And the contents of Temp:

This view in Finder, like Explorer in Windows, doesn’t show the ADS, just the parent file it’s “riding” on. For that, we’ll need to switch to the command line

First, I’ll check that the share is mounted and where:

Olorin:~ ron$ mount
/dev/disk1 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)
/dev/disk3s2 on /Volumes/SSDExternal (exfat, local, nodev, nosuid, noowners)
//XXXXXX@10.11.76.100/c$ on /Volumes/c$ (smbfs, nodevnosuid, mounted by ron)

Switching to the Temp directory and running the ‘ls’ command gives me this:

Olorin:~ ron$ cd /Volumes/c\$/Temp/
Olorin:Temp ron$ ls -l
total 1
rwx——@ 1 ron  staff  21 Jul 23 02:51 file1.txt

Looks like a normal output for ls, but look just to the right of the permissions block and you’ll see an ‘@’ symbol.  This is the ls command telling you that that file has an extended attribute.

Extended attributes is the *NIX name for metadata not usually interpreted by the filesystem, unlike typical attributes like size and permissions. Extended attributes allow the operating system and applications to apply their own metadata to file that will usually stay “stuck” to the file when copied to other volumes that support extended attributes. (great writeup here: https://en.wikipedia.org/wiki/Extended_file_attributes)

The ls command shows you a file has extended attributes.  If we run it again with another option, @, we’ll see more:

Olorin:Temp ron$ ls -l@
total 1
rwx——@ 1 ron  staff  21 Jul 23 03:33 file1.txt
    ads.txt 49

The xattr command can view names and contents, create and delete extended attributes. And as you’ve probably guessed by now, the Mac operating system treats ADS as just another extended attribute, so we can use xattr to access ADS as well!

Using xattr with no options will give us the name:

Olorin:Temp ron$ xattr file1.txt
ads.txt

If we run xattr with the -l option, it lists the name and the contents:

Olorin:Temp ron$ xattr -l file1.txt
ads.txt: This is the contents of an alternate data stream.

What if the ADS is a binary file? Can we access those as well?  Turns out, we can! 

I’ll create a binary ADS on the Windows side just by copying an executable into the ADS, in this case, our beloved netcat.

Back to the Mac:

Olorin:Temp ron$ ls -l@
total 1
rwx——@ 1 ron  staff  21 Jul 23 03:33 file1.txt
    ads.txt 49
    nc.exe 59392
Olorin:Temp ron$ xattr
file1.txt
ads.txt
nc.exe

So we can see from both ls and xattr that file1.txt has two ADS attached.  Can we view the contents?

Olorin:Temp ron$ xattr -l file1.txt
ads.txt: This is the contents of an alternate data stream. nc.exe:
00000000  4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00  |MZ…………..|
00000010  B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00  |……..@…….|
00000020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |…………….|
00000030  00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00  |…………….|
00000040  0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68  |……..!..L.!Th|
00000050  69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F  |is program canno|
00000060  74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20  |t be run in DOS |
00000070  6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00  |mode….$…….|
00000080  50 45 00 00 4C 01 04 00 B9 8E AE 34 00 00 00 00  |PE..L……4….|
00000090  00 00 00 00 E0 00 0F 01 0B 01 05 00 00 98 00 00  |…………….|
000000A0  00 62 00 00 00 00 00 00 00 4C 00 00 00 10 00 00  |.b…….L……|
000000B0  00 B0 00 00 00 00 40 00 00 10 00 00 00 02 00 00  |……@………|
000000C0  04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00  |…………….|
000000D0  00 30 01 00 00 04 00 00 00 00 00 00 03 00 00 00  |.0…………..|
000000E0  00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00  |…………….|
000000F0  00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00  |…………….|
00000100  00 20 01 00 3C 00 00 00 00 00 00 00 00 00 00 00  |. ..<………..|
00000110  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |…………….|
00000120  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |…………….|
00000130  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |…………….|
00000140  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |…………….|
00000150  00 00 00 00 00 00 00 00 A0 21 01 00 64 01 00 00  |………!..d…|
00000160  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |…………….|
00000170  00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00  |………text…|
00000180  70 97 00 00 00 10 00 00 00 98 00 00 00 04 00 00  |p……………|
00000190  00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60  |………… ..`| …
(many, many, lines followed this)

Well, yes, but it’s kind of messy.  (note though the characteristic MZ right at the beginning, the magic number that clues us in that this is a Windows portable executable file.)

Let’s use some other options on xattr.

The -p option prints the contents of a specific extended attribute, just by specifying the name in the command:

Olorin:Temp ron$ xattr -p
ads.txt file1.txt
This is the contents of an alternate data stream.

Using -p on the binary file gives us

Olorin:Temp ron$ xattr -p nc.exe file1.txt
4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00
B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00
0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68
69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F
74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20
6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00
50 45 00 00 4C 01 04 00 B9 8E AE 34 00 00 00 00
00 00 00 00 E0 00 0F 01 0B 01 05 00 00 98 00 00
00 62 00 00 00 00 00 00 00 4C 00 00 00 10 00 00
00 B0 00 00 00 00 40 00 00 10 00 00 00 02 00 00
04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
00 30 01 00 00 04 00 00 00 00 00 00 03 00 00 00
00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00
00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00
00 20 01 00 3C 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 0 …

Much cleaner: we have the raw bytes in hexadecimal format.   We can now use another *NIX stalwart tool to extract the binary file, xxd.

Most *NIX versions include xxd, a command line tool that can convert bytes for display in hex format and convert hex formatted bytes back to binary data that can be used as the original.  We’re going to use the options on xxd that allows the hex stream by itself to be reassembled and converted, -r to reverse from hex and -p to accept plain streams of hex without offsets in the left column.

Olorin:Temp ron$ xattr -p nc.exe file1.txt | xxd -r -p > /tmp/nc.exe
Olorin:Temp ron$ ls -l /tmp/nc.exe
rw-r–r— 1 ron wheel  59392 Jul 23 03:53 /tmp/nc.exe

And if I check the sha1 hash for the extracted data I can see it’s the exact same file – the hash matches what I calculated in Windows from the original copy of nc.exe:

Olorin:Temp ronshasum /tmp/nc.exe
57f0839433234285cc9df96198a6ca58248a4707  /tmp/nc.exe

I can even create an ADS using xattr -w

Olorin:Temp ron$ xattr -w ads2.txt “This is also an alternate data stream.” file1.txt

Olorin:Temp ron$ ls -l@
total 1
rwx——@ 1 ron  staff  21 Jul 23 03:33 file1.txt
    ads.txt 49
    ads2.txt   38
    nc.exe 59392

And going back to my Windows machine:

Of course, the final thing we might want to try is get rid of an ADS, which xattr can do with the -d option:

Olorin:Temp ron$ xattr -d ads2.txt file1.txt
Olorin:Temp ron$ ls -l@
total 1
rwx——@ 1 ron  staff  21 Jul 23 03:33 file1.txt
    ads.txt 49
    nc.exe 59392

So, what could we use this capability for?  If we can connect via SMB, we can pull data from  an ADS, we can add a new ADS, and we can use it to delete ADS from a file.  One particular use case as a pentester (or attacker) might be to modify the Zone.Identifier for a file in the Downloads directory or get rid of the Zone.Identifier entirely to obscure the origin of a file on a system. Or, as fellow instructor Mick Douglas suggests, use this capability to look  for interesting DLP tags.

On the DFIR side, you could use this technique to remotely look for these files using command line tools on your Mac.  This appears to have an interesting advantage: accessing the file using xattr over SMB seems to not change access or modified times. I just noticed this – it’s not fully tested, but when I created an ADS using the xattr command over SMB, the write time didn’t change, but when I used the type command at the cmd.exe prompt, it did. You can see in the screen shots above that when I added the ADS file1.txt:nc.exe, the modified time changed to 02:33 AM, but when I added the ADS file1.txt:ads2.txt, it did not change the file modified time. File created and access times weren’t changed by any operations on ADS, regardless of whether they were done on the Windows command line or by xattr via SMB.  More testing on this oddity is warranted!

I hope this was an interesting diversion, and if you find this helpful, please let me know in the comments or drop me a message!

*I’d love to give full credit to the original blog I learned about xattr from, but I didn’t bookmark it.  If I find it again, I’ll be sure to post a link here to give credit where credit is due!

ron hamann, Janky Robot Security, LLC