Jump to content
YOUR-AD-HERE
HOSTING
TOOLS
SERVICE

Locked Donut


0x1

Recommended Posts

Donut generates x86 or x64 shellcode from VBScript, JScript, EXE, DLL (including .NET Assemblies) files.

This is the hidden content, please


This shellcode can be injected into an arbitrary Windows processes for in-memory execution.
Given a supported file type, parameters and an entry point where applicable (such as Program.Main), it produces position-independent shellcode that loads and runs entirely from memory. A module created by donut can either be staged from a URL or stageless by being embedded directly in the shellcode. Either way, the module is encrypted with the Chaskey block cipher and a 128-bit randomly generated key.
After the file is loaded through the PE/ActiveScript/CLR loader, the original reference is erased from memory to deter memory scanners. For .NET Assemblies, they are loaded into a new Application Domain to allow for running Assemblies in disposable AppDomains.

It can be used in several ways.

As a Standalone Tool

Donut can be used as-is to generate shellcode from VBS/JS/EXE/DLL files or .NET Assemblies. A Linux and Windows executable and a Python module are provided for loader generation. The Python documentation can be found [here](https://github.com/TheWover/donut/blob/master/docs/2019-08-21-Python_Extension.md). The command-line syntax is as described below.

Spoiler
This is the hidden content, please

 

 Bypasses

Donut includes a bypass system for AMSI and other security features. Currently we bypass:

  • AMSI in .NET v4.8
  • Device Guard policy preventing dynamicly generated code from executing

You may customize our bypasses or add your own. The bypass logic is defined in loader/bypass.c.

Each bypass implements the DisableAMSI fuction with the signature BOOL DisableAMSI(PDONUT_INSTANCE inst), and comes with a corresponding preprocessor directive. We have several #if defined blocks that check for definitions. Each block implements the same bypass function. For instance, our first bypass is called BYPASS_AMSI_A. If donut is built with that variable defined, then that bypass will be used.

Why do it this way? Because it means that only the bypass you are using is built into loader.exe. As a result, the others are not included in your shellcode. This reduces the size and complexity of your shellcode, adds modularity to the design, and ensures that scanners cannot find suspicious blocks in your shellcode that you are not actually using.

Another benefit of this design is that you may write your own AMSI bypass. To build Donut with your new bypass, use an if defined block for your bypass and modify the makefile to add an option that builds with the name of your bypass defined.

If you wanted to, you could extend our bypass system to add in other pre-execution logic that runs before your .NET Assembly is loaded.

Additional features.

These are left as exercises to the reader. I would personally recommend:

  • *Add environmental keying
  •  Make donut polymorphic by obfuscating *loader* every time shellcode is generated
  •  Integrate donut as a module into your favorite RAT/C2 Framework

Disclaimers

  •  No, we will not update donut to counter signatures or detections by any AV.
  •  We are not responsible for any misuse of this software or technique. Donut is provided as a demonstration of CLR Injection through shellcode in order to provide red teamers a way to emulate adversaries and defenders a frame of reference for building analytics and mitigations. This inevitably runs the risk of malware authors and threat actors misusing it. However, we believe that the net benefit outweighs the risk. Hopefully that is correct.

 How it works

 Procedure for Assemblies

Donut uses the Unmanaged CLR Hosting API to load the Common Language Runtime. If necessary, the Assembly is downloaded into memory. Either way, it is decrypted using the Chaskey block cipher. Once the CLR is loaded into the host process, a new AppDomain will be created using a random name unless otherwise specified. Once the AppDomain is ready, the .NET Assembly is loaded through AppDomain.Load_3. Finally, the Entry Point specified by the user is invoked with any specified parameters.

The logic above describes how the shellcode generated by donut works. That logic is defined in *loader.exe*. To get the shellcode, *exe2h* extracts the compiled machine code from the *.text* segment in *loader.exe* and saves it as a C array to a C header file. *donut* combines the shellcode with a Donut Instance (a configuration for the shellcode) and a Donut Module (a structure containing the .NET assembly, class name, method name and any parameters).

Refer to MSDN for documentation on the Undocumented CLR Hosting API:

This is the hidden content, please

For a standalone example of a CLR Host, refer to Casey Smith's AssemblyLoader repo:

This is the hidden content, please

Detailed blog posts about how donut works are available at both Odzhan's and TheWover's blogs. Links are at the top of the README.

Procedure for ActiveScript/XSL

The details of how Donut loads scripts and XSL files from memory have been detailed by Odzhan in a

This is the hidden content, please

Procedure for PE LoadingThe details of how Donut loads PE files from memory have been detailed by Odzhan in a

This is the hidden content, please

Only PE files with relocation information (.reloc) are supported. TLS callbacks are only executed upon process creation.

More info && Download

This is the hidden content, please

Edited by dEEpEst
Link repaired
Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.