Skip to content

wabzsy/gonut

Repository files navigation

Gonut

English | 中文

Before using Gonut for the first time, you need to understand: "What is Donut?"

What is Donut?

Donut is a position-independent code that enables in-memory execution of VBScript, JScript, EXE, DLL files and dotNET assemblies. A module created by Donut can either be staged from a HTTP server or embedded directly in the loader itself. The module is optionally encrypted using the Chaskey block cipher and a 128-bit randomly generated key. After the file is loaded and executed in memory, the original reference is erased to deter memory scanners. The generator and loader support the following features:

  • Compression of input files with aPLib and LZNT1, Xpress, Xpress Huffman via RtlCompressBuffer.
  • Using entropy for API hashes and generation of strings.
  • 128-bit symmetric encryption of files.
  • Overwriting native PE headers.
  • Storing native PEs in MEM_IMAGE memory.
  • Patching Antimalware Scan Interface (AMSI) and Windows Lockdown Policy (WLDP).
  • Patching Event Tracing for Windows (ETW).
  • Patching command line for EXE files.
  • Patching exit-related API to avoid termination of host process.
  • Multiple output formats: C, Ruby, Python, PowerShell, Base64, C#, Hexadecimal, and UUID string.

There are dynamic and static libraries for both Linux and Windows that can be integrated into your own projects. There's also a python module which you can read more about in Building and using the Python extension.

Note: Support for Xpress Huffman was temporarily removed in Donut v1.0.

To understand in more detail what Donut is and how Donut works, you can visit: https://github.com/TheWover/donut

2. Main components of Donut

The Generator compresses and encrypts files of formats such as VBScript, JScript, EXE, DLL files, and .NET assemblies based on input parameters, concatenates them with the shellcode of the Loader, and finally generates the final shellcode to be used.

The Loader is essentially a shellcode template. When executed in memory, it will decrypt and decompress the original payload (vbs, js, exe, dll, etc.) into memory and execute the payload according to the parameters provided by the Generator.

Bypassing operations such as AMSI, WLDP, ETW are executed by the Loader.

3. What can Donut be used for?

If you have correctly understood most of the content mentioned earlier, you don't need to pay attention to this section. Otherwise, you can simply regard Donut as a PE-to-Shellcode tool, which has additional features such as encryption, compression, bypassing AMSI, WLDP, ETW, stealthy invocation of system APIs compared to other tools (such as pe_to_shellcode, etc.), and can better evade AV, EDR's memory detection and behavior detection.

What is Gonut?

Gonut is a cross-platform implementation of Donut's Generator, written in pure Go without CGO, and supports most mainstream systems (Windows, Linux, macOS, etc.) and architectures (i386, amd64, arm, Apple silicon, etc.).

Note again: Gonut is just a cross-platform implementation of Donut's Generator and does not include Donut's Loader.

Why Gonut exists

  • Donut's Generator can only run on Windows and Linux systems.
  • The behavior of Donut's Generator under Linux is not completely consistent with that under Windows. (#45)
  • Donut's Generator does not support Xpress, LZNT1 compression under Linux.
  • Currently, it is impossible to compile Donut under Arm architecture on Windows and Linux.
  • Donut's Generator cannot be used under macOS (M-series chips).
  • Let more people know about Donut, a seriously underrated project.

To solve the above problems, Gonut was born.

Goals of Gonut

  • Have behavior consistent with Donut on Windows across all systems (Windows, Linux, macOS, etc.) except for the compression feature (for more details, see the Differences between Gonut and Donut's Generator).
  • Provide a better user experience.

Not Goals of Gonut

  • Since Gonut is completely dependent on Donut's Loader, it will not add features that Donut does not have (or explicitly states it does not support).

Differences between Gonut and Other Similar Projects

Donut recommends two third-party implementations of Generators:

However, these two projects have not been updated for a long time, do not support the latest version (v1.0) of Donut Loader, and do not support common functions such as Decoy, ETW Bypass, compression, specified output formats, etc.

Differences between Gonut and Donut's Generator

  1. Difference in compression function: Since Donut uses the non-open source aPLib compression function and Microsoft's RtlCompressBuffer function, both of which cannot be perfectly reproduced on non-Windows systems, currently Gonut can only try to simulate these two compression algorithms and compression formats.
  2. Added output formats: Golang, Rust, etc.

How to Use Gonut

For various reasons, Gonut currently does not intend to provide precompiled binary files, which means that if you want to use Gonut, you will need to install the most basic Golang development environment or Docker runtime environment.

Building via Docker

git clone https://github.com/wabzsy/gonut

cd gonut

docker build -t gonut .

# docker run --rm -it -v `pwd`:/opt gonut -h

Installation via go install

go install -v github.com/wabzsy/gonut/gonut@latest

Building from source

git clone https://github.com/wabzsy/gonut

cd gonut/gonut

go build -v

Usage

Much the same as Donut's usage. The following table lists switches supported by the command line version of the Gonut:

Switch Argument type Description
-n, --modname string Module name for HTTP staging.
If entropy is enabled, this is generated randomly.
-s, --server string Server that will host the Donut module.
Credentials may be provided in the following format:
https://username:password@192.168.0.1/
-e, --entropy int Entropy:
1=None
2=Use random names
3=Random names + symmetric encryption
(default 3)
-a, --arch int Target architecture:
1=x86
2=amd64
3=x86+amd64
(default 3)
-o, --output string Output file to save loader.
(default: loader.[format])
-f, --format int Output format:
1=Binary
2=Base64
3=C
4=Ruby
5=Python
6=Powershell
7=C#
8=Hex
9=UUID
10=Golang
11=Rust
(default 1)
-y, --oep int Create thread for loader and continue execution at <addr> supplied.
(eg. 0xdeadbeef)
-x, --exit int Exit behaviour:
1=Exit thread
2=Exit process
3=Do not exit or cleanup and block indefinitely
(default 1)
-c, --class string Optional class name. (required for .NET DLL, format: namespace.class)
-d, --domain string AppDomain name to create for .NET assembly.
If entropy is enabled, this is generated randomly.
-i, --input string Input file to execute in-memory.
-m, --method string Optional method or function for DLL.
(a method is required for .NET DLL)
-p, --args string Optional parameters/command line inside quotations for DLL method/function or EXE.
-w, --unicode Command line is passed to unmanaged DLL function in UNICODE format.
(default is ANSI)
-r, --runtime string CLR runtime version. MetaHeader used by default or v4.0.30319 if none available.
-t, --thread Execute the entrypoint of an unmanaged EXE as a thread.
-z, --compress int Pack/Compress file:
1=None
2=aPLib [experimental]
3=LZNT1 (RTL) [experimental, Windows only]
4=Xpress (RTL) [experimental, Windows only]
5=LZNT1 [experimental]
6=Xpress [experimental, recommended]
(default 1)
-b, --bypass int Bypass AMSI/WLDP/ETW:
1=None
2=Abort on fail
3=Continue on fail
(default 3)
-k, --headers int Preserve PE headers:
1=Overwrite
2=Keep all
(default 1)
-j, --decoy string Optional path of decoy module for Module Overloading.
-v, --verbose verbose output. (debug mode)
-h, --help help for gonut
--version version for gonut

Payload Requirements

The same as Donut, see Payload Requirements for details.

Disclaimer

The same as Donut, see Disclaimer for details.

We are not responsible for any misuse of this software or technique. Gonut is provided as a demonstration of CLR Injection and in-memory loading 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. In the event EDR or AV products are capable of detecting Gonut via signatures or behavioral patterns, we will not update Gonut to counter signatures or detection methods. To avoid being offended, please do not ask.