Skip to content

Repository files navigation

Fritter

The evasive cousin of Donut.

Fritter is a heavily modified fork of TheWover and Odzhan's Donut shellcode generator. It generates position-independent shellcode for in-memory execution of VBScript, JScript, EXE, DLL, and .NET assemblies, with a focus on evasion and signature resistance. The codebase is x64-only.

What's different

Lots. Fritter strips out features that aren't commonly needed and replaces internals that have become well-signatured over the years. The crypto, compression, hashing, and API resolution layers have all been reworked among many other areas.

Polymorphism and evasion is the design goal. Every output is unique, and every build of the tool is itself unique. There are two distinct layers:

Per-output randomization: applied each time fritter is invoked. The entry stub, the polymorphic decoder, the encryption keys, and many structural elements within the generated shellcode are regenerated from new entropy on every PIC build.

Per-build randomization: applied each time fritter itself is compiled. Cipher and hash rotation constants, API resolution table layout, shim-side string scrambling, PEB-walk directions, post-execution wipe patterns, and several structural axes inside the loader and shim are baked at compile time.

At runtime, Fritter minimizes the executable footprint of the loader. The loader is partitioned into individually encrypted functions, each with its own PE section, XOR key, and dispatcher. Only one function's bytes are in plaintext at any given moment. The earlier VEH sliding-window model has been retired in favor of this dispatch model.

!! Build from source is strongly recommended !!

This matters. The pre-built binaries available for testing in releases share their per-build constants across all users of the binary.

Build your own copy. The per-build axes are re-randomized on every make invocation:

# Linux, static-musl ELF, no runtime libc dependency
# Requires: build-essential, mingw-w64, musl-tools
make -f Makefile.linux release

# Windows (MSVC), recommended on Windows
nmake -f Makefile.msvc

On Windows, MSVC is the recommended toolchain. It lays each loader function into its own page-aligned PE section, which is what the N>1 per-function dispatch model needs. mingw currently emits everything into a single .text and therefore runs one entry covering the entire loader with one XOR key (functionally identical to MSVC output, but only one dispatcher of polymorphism instead of many). If you don't have Visual Studio, build under WSL with Makefile.linux; it cross-compiles the Windows loader via mingw-w64.

Each make runs tools/gen_poly to emit fresh per-build constants and tools/gen_api_shuffle to permute the API resolution table. The resulting fritter binary is itself unique with different cipher constants, different hash constants, a different API table layout, different shim-side string scrambling, and so on. Every shellcode generated by that binary will then share those per-build constants but vary on the per-output axes.

Usage

A /test folder is included with calc.exe and inject_local64.exe to test Fritter. To rebuild the test hosts yourself: nmake -f Makefile.msvc harness, or make -f Makefile.linux harness under WSL.

fritter [options] -i <EXE/DLL/VBS/JS>

  INPUT
    -i, --input  <path>       Input file to execute in-memory
    -p, --args   <args>       Parameters / command line for target
    -c, --class  <name>       Class name (required for .NET DLL)
    -m, --method <name>       Method or function for DLL
    -r, --runtime <ver>       CLR runtime version
    -w, --unicode             Pass command line as UNICODE
    -t, --thread              Run unmanaged EXE entrypoint as thread

  OUTPUT
    -o, --output <path>       Output file (default: loader.bin)
    -f, --format <1-8>        1=Bin 2=B64 3=C 4=Ruby 5=Py 6=PS 7=C# 8=Hex
    -x, --exit   <1-3>        1=Thread (default) 2=Process 3=Block
    -y, --fork   <offset>     Fork thread, continue at RVA offset

  LOADER
    -e, --entropy <1-3>       1=None 2=Random names 3=Names+Crypto (default)
    -k, --headers <1-2>       1=Overwrite (default) 2=Keep all
    -g, --chunked <0-1>       (deprecated; dispatch shim is always used)
    -d, --domain  <name>      AppDomain name for .NET
    -j, --decoy   <path>      Decoy module for Module Overloading

  STAGING
    -n, --modname <name>      Module name for HTTP staging
    -s, --server  <url>       Server URL (supports basic auth)

Examples

fritter -i payload.exe
fritter -i implant.dll -m RunMain -p "arg1 arg2"
fritter -i payload.exe -g 0 -k 2 -o out.bin

Architecture (many implementations are not listed here)

A Fritter shellcode payload is structured as nested layers, each one decrypting or staging the next:

  1. Entry stub. A randomized junk prefix of variable length, an RSP-alignment routine generated per output, and a generative trampoline. Based on the discipline of Shikata Ga Nai.

  2. Polymorphic XOR decoder. Two-pass-assembled. Register allocation drawn from a pool by Fisher-Yates shuffle. Key length picked per output. Junk inserted between every real instruction. The hot loop's movable instruction groups are reordered within correctness constraints.

  3. Dispatch shim. Replaces the earlier VEH sliding-window shim. Flips the loader region RW->RWX, then hands control to the loader entry. Under N>1 dispatch, each call is routed through a per-function thunk into a per-function dispatcher that decrypts, runs, and wipes on return. Every dispatcher's opcode layout varies per build (see CHANGELOG v1.3).

  4. Loader. PE in-memory mapper. Resolves APIs by hash, maps the embedded PE via section APIs, applies imports / relocations / TLS callbacks, invokes the entrypoint, then wipes. PEB walk direction, post-exec wipe byte, structural salt sites in MainProc, are all randomized per build.

  5. Cleanup. Wipes loader pages with a per-build byte pattern, erases the instance, and exits via thread or process termination per -x. No VEH handler or context struct to scrub.

Residual footprint after execution is one small RWX page where the dispatch shim ran. In thread mode the mapped PE section is intentionally left intact so CRT callbacks have continuations.

Credits

Fritter is built on the work of TheWover and Odzhan, whose original Donut project made position-independent shellcode generation accessible and practical. Their architecture, loader design, and PIC framework are the foundation everything here is built on. The PE mapping, .NET hosting, and script execution paths are largely their work, retained and respected.

License

BSD 3-Clause. See LICENSE.

About

Fritter is a heavily modified fork of TheWover and Odzhan's Donut shellcode generator.

Resources

Stars

246 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages