It’s no secret that Casey Smith’s research into bypasses has changed how nearly everyone in the industry approaches testing and circumventing application whitelisting solutions. You could argue that one of his more prolific findings is how to abuse MSBuild’s inline tasks as a method of executing code. We at FortyNorth Security commonly face application whitelisting solutions in hardened environments and have used MSBuild, amongst other candidates, to circumvent their protection.
Due to commonly encountering the need for an application whitelisting bypass (and its effectiveness even on systems without application whitelisting solutions) we decided to automate using MSBuild, specifically in this case to run PowerShell namespaces via MSBuild (thanks @djhohnstein for the edit), based off a script from Chris Ross (@xorrior). Our choice was to use Aggressor since Cobalt Strike is a platform we commonly use for our assessments. We wanted our script to be able to do the following:
- Run a single PowerShell command via MSBuild
- Execute a function within a PowerShell script via MSBuild
- Perform either of the above both locally or remotely
This blog post will quickly cover some of the key points of how we completed this task and ended up with four additional commands registered within Beacon. You can review both scripts within our Github repo Aggressor Assessor here (there’s also an alternative version to accomplish the same overall goal within @MrUn1k0d3r’s Github Repo here, written by @ramen0x3f). Once you load either script from the AggressorAssessor repo into Cobalt Strike, you will have new commands available in the help menu when you type “help”. These new options are shown below with their own help menu.
How Do You Use These MSBuild Scripts?
If we wanted to use MSBuild to run the cmdlet “Get-Process”, you just need to type “msbuild_cmd Get-Process”. Since you are running this on the local host, you will also get the output from this command.
The same concept extends to running a PowerShell script on the same system via MSBuild. The only difference is that you are providing the path to the PowerShell script you want to run (on your local system) and the PowerShell cmdlet you are running.
Finally, how about the ability to do all of this, but remotely? The good thing is: it’s essentially the same steps (different Beacon commands – remote_msbuild_cmd and remote_msbuild_script). The only difference is that you need to provide the IP address or hostname of the system you are targeting. For example, the command below demonstrates running “Get-Process” remotely on a system and storing the output on disk.
How Do The Scripts Work?
These scripts largely operate the same way. They all use the XML file from Chris Ross and modify its contents to be able to run the command, or script, that we are trying to run. The general process is as follows:
- The XML file is built locally on the attacker’s system, and then uploaded to the victim system to C:\Users\Public\Documents\trusteddata.xml
- MSBuild.exe is copied from its original location into C:\Users\Public\Documents\svchost.exe via PowerPick
- PowerPick then runs the copied and renamed MSBuild and instructs it to interpret the trusteddata.xml file
- After execution, PowerPick then removes the trusteddata.xml and svchost.exe files
The primary difference between the local execution and the remote execution is the manner in which MSBuild is run. For remote execution, the “trusteddata.xml” is uploaded to the remote system via a UNC path and then MSBuild is triggered to run via WMI. Outside of these differences, it’s largely the same.
If you are interested in additional application whitelisting bypass techniques, be sure to register for our free webinar on the topic. Additionally, this is the type of material we will be covering in our BlackHat USA class, amongst much more information. Click here to learn about what we will be teaching, and we hope to see you in Las Vegas!