We recently performed an Insider Threat red team engagement, posing as employees within the company. We were provided with all the benefits of a regular employee (except salary :)) with legitimate access, accounts and thin clients. This posed some interesting challenges in terms of operating tradecraft in what was a mature, well secured environment. In particular, the company had an extremely strict whitelisting deployment using a commercial workspace whitelisting solution. It was not possible therefore to just introduce your favourite tools and arbitrarily run PowerShell scripts or executables. There were however some small chinks in the armour that stood out to us and provided us an opportunity to operate effectively. In this blog post we will release SharpPack, a tool developed to provide an opportunity to introduce tooling to environments where you may be restricted from operating.
Most of our favourite tools in the red team arsenal are developed in DotNet or PowerShell and there exists numerous ways to execute these from memory when operating from your implant such as CobaltStrike’s powerpick and execute-assembly methods. In our use case, we were operating without an implant but still wanted to reap the benefits of GhostPack, Internal Monologue et al and therefore we had to get a little more creative with our tradecraft. As previously noted, we were operating in an environment with tight application whitelisting so recompiling and obfuscating our chosen tools was just not an option. We did however observe two notable opportunities to get code execution as the environment made heavy use of VBScript (thanks Tanium :)) and locally created Office Macro enabled documents.
Our initial idea was to introduce our own toolkit to the environment in an encrypted form, then load and execute the tools from memory. The method we chose to hide our toolkit from AntiVirus’ prying eyes was to use an encrypted ZIP file. This was relatively simple to accomplish thanks to SharpZipLib; an example of how we unpacked the archive and retrieved the chosen executable is shown below:
Once the target file had been retrieved from the archive and held in memory we need to execute it. In-memory execution of DotNet assembly is well documented and already wildly abused by red teamers using CSharp’s Assembly.Load() method as we show below which will execute the EntryPoint of a DotNet binary:
SharpPack has a RunDotNet() helper method that will decrypt and retrieve the chosen binary, execute it and store the result inside a file.
Our initial approach for executing a PowerShell script was using System.Management.Automation’s Runspaces; this worked well in our environment as the version of PowerShell installed did not support any of the protections available in more recent versions such as ScriptBlock logging, AMSI and Constrained Language Mode. However, after the engagement we wanted this to be reusable in other environments so we began to explore alternate solutions. Following some discussions with Ryan Cobb we were pointed to a much more elegant solution courtesy of Ryan’s SharpSploit project and inspired by Lee Holmes work on evading ScriptBlock logging and Matt Graeber’s amsiInitFailed AMSI bypass.
The SharpSploit solution was almost exactly what we needed and the modified version is presented below:
As we already have CSharp execution, this approach will use reflection to disable AMSI using Matt’s amsiInitFailed method which we discussed in detail in one of our previous blog posts. Event tracing is then disabled by setting the System.Management.Automation.Tracing.PSEtwLogProvider etwProvider field to null.
To summarise, combining this functionality we have a DotNet library that is capable of reading either a DotNet binary or PowerShell script from an encrypted zip archive and executing it in memory. It should be noted that the filename and extension of the archive are also irrelevant.
The next step to understand, is how to execute the library in an opsec safe manner while still considering application whitelisting. I previously mentioned that in the environment we were working in, we recognised code execution was possible through both VBS and Office Macros. Fortunately, this opened the opportunity for us to execute tools using SharpPack with one of two approaches; using James Forshaw’s DotNetToJScript or using a managed DLL export. I’ll cover both these approaches now.
I’ve described DotNetToJScript extensively in previous posts and in particular how it’s used in our SharpShooter tool so I won’t dwell on this concept too long. Essentially, you can take the compiled DLL and convert it to VBS using DotNetToJScript which uses BinaryFormatter as a primitive to execute DotNet code from VBScript. First, the SharpPack library should be run through DotNetToJScript as follows:
The resultant VBS will then need to be modified to execute your chosen tools, this can simply be done by modifying the VBS to execute the aforementioned RunPowerShell() or RunDotNet() methods, an example is shown below which will execute the Get-IPAddress cmdlet from PowerView from inside the encrypted zip:
The second method i’ll discuss is using the managed DLL export trick described by my colleague Adam Chester on his blog. In this scenario we’ll compile SharpPack to an unmanaged DLL, then access it from an Office VBA macro via COM.
Firstly, as described in Adam’s blog post you can export from the DLL using the DllExport package from Denis Kuzmin; in this case we can export a class and make it accessible via COM using an IDispatch interface to provide a full SharpPack object:
Compiling the DLL we can now find we have an export that returns the SharpPack class:
There’s a number of options for accessing the DLL, though as mentioned let’s take look at how this can be done using an Office VBA macro:
In the above we make the CreateDotNetObject function accessible to VBA by declaring it as a library function, then execute it to retrieve a SharpPack object, where it’s possible to execute any of the class methods such as RunDotNet().
Understanding how your tools work is an essential part of forming a red teamer’s tradecraft. If we start to analyse this approach, we’ll find that we’re working solely inside Excel’s process space. The SharpPack DLL will be loaded by Excel, noting that the name and extension are irrelevant, and the DotNet or PowerShell scripts are executed from within Excel itself, without spawning any additional processes. This in itself is fairly significant, as it avoids any suspicious parent child relationships being formed:
As noted by Adam in his blog post, this is accomplished because a full copy of the .NET Common Language Runtime (CLR) is loaded in to the process, providing unrestricted access to the power of the .NET framework:
As such, depending on what you attempt to execute, from an EDR perspective this technique is relatively opsec safe.
SharpPack can be downloaded from the MDSec ActiveBreach github page.
This blog post was written by Dominic Chell.