Excel 4.0 (XLM) Macro Generator for injecting DLLs and EXEs into memory.
_______ ______ _____ _ _ ____ _
| ____\ \/ / ___| ____| | _ __ | |_| _ \ ___ _ __ _ _| |_
| _| \ / | | _| | | | '_ \| __| | | |/ _ \| '_ \| | | | __|
| |___ / \ |___| |___| |___| | | | |_| |_| | (_) | | | | |_| | |_
|_____/_/\_\____|_____|_____|_| |_|\__|____/ \___/|_| |_|\__,_|\__|
by @JoeLeonJr (@FortyNorthSec)
EXCELntDonut is a XLM (Excel 4.0) macro generator. Start with C# source code (EXE) and end with a XLM (Excel 4.0) macro that will execute your code in memory. XLM (Excel 4.0) macros can be saved in .XLS files.
chmod +x install.sh
./install.sh
What is installed?
If you'd like to run EXCELntDonut as just a python script, you'll need to setup a virtual environment with two packages "pandas" and "donut-shellcode". Additionally, you'll need to apt-get install mono-complete and call the drive.py script using python3. We recommend just using the ./install.sh bash script, but it's up to you.
Usage:
$ EXCELntDonut -f exe_source.cs -r System.Windows.Forms.dll --sandbox --obfuscate
Flags:
(required)
-f path to file containing your C# soure code (exe only)
-r References needed to compile your C# code (same ones for when using mcs to compile on Linux)
(ex: -r 'System.Management')
(optional)
-o output filename
--sandbox
Perform basic sandbox checks. This will be updated as new approaches are discovered.
--obfuscate
Perform basic macro obfuscation.
You provide a C# file containing your payload (like an EXE with a main method that executes a cobalt strike beacon payload). That C# file is compiled using MCS into two .NET assemblies: x86 and x64. After compilation, the awesome tools Donut (for x86) and CLRvoyance (for x64) convert each assembly into position independent shellcode. Next, all nullbytes are removed, since XLM (Excel 4.0) macros don't play nicely with nullbytes and the payload is chunked into lines with no more than 255 characters (for x86) or 10 characters (for x64).
Once the shellcode is prepared, it's combined with basic process injection functions (VirtualAlloc, WriteProcessMemory and CreateThread) as well as an architecture check function to determine which payload (x86 or x64) to run on the target system. If you elect to execute sandbox checks or basic obfuscation, then those functions will update your macro. Finally, the output is placed in a CSV file (saved as .txt).
Once you have the output file from EXCELntDonut, open the output file in a text editor and copy the entirety of it (Ctrl-A, Ctrl-S). Open up Excel on a Windows VM, right-click on "Sheet 1" and select "Insert". Choose "MS Excel 4.0 Macro". Go to cell A1 and paste the EXCELntDonut output. All the data will likely be pasted in one column. The data is semi-colon separated ";". Go to the "Data" tab and then click "Text-to-columns". Select "Delimited" and on the next screen select "Semicolon" and then click "Finish". The macro will spread across the appropriate columns and rows.
(Note - if you selected the "--obfuscate" flag, you'll need to scroll horizontally quite a bit to find your actual code, since part of the obuscation logic moves the macro into a random section of the worksheet).
We recommend two things at this point:
Save the file (.xls) and try opening it up. It should automatically execute your payload.
These checks are based on what actual threat actors are using in their malware.
=FORMULA(D3&D23&D54&D23&D44,E45)
The FORMULA function allows us to place a formula, which can later be executed, into another cell. So in this case, we put the process injection instructions and then use the FORMULA function to place the actual function into another cell to be executed. This avoids defenders conducting static analysis from seeing things like "VirtualAlloc".
root@excelntdonut-test:/opt# EXCELntDonut -f test.cs
_______ ______ _____ _ _ ____ _
| ____\ \/ / ___| ____| | _ __ | |_| _ \ ___ _ __ _ _| |_
| _| \ / | | _| | | | '_ \| __| | | |/ _ \| '_ \| | | | __|
| |___ / \ |___| |___| |___| | | | |_| |_| | (_) | | | | |_| | |_
|_____/_/\_\____|_____|_____|_| |_|\__|____/ \___/|_| |_|\__,_|\__|
by @JoeLeonJr (@FortyNorthSec)
[i] Generating your x86 .NET assembly.
warning CS8001: SDK path could not be resolved
test.cs(2,14): error CS0234: The type or namespace name `Management' does not exist in the namespace `System'. Are you missing an assembly reference?
This error most likely means you're missing a reference assembly during compilation using mono. To fix this, simply pass in the namespace mentioned into the -r flag. In this case, we'd add -r 'System.Management' to the command line. The new command would be:
root@excelntdonut-test:/opt# EXCELntDonut -f test.cs -r 'System.Management'
root@excelntdonut-test:/opt# EXCELntDonut -f test.cs -r System.Management
_______ ______ _____ _ _ ____ _
| ____\ \/ / ___| ____| | _ __ | |_| _ \ ___ _ __ _ _| |_
| _| \ / | | _| | | | '_ \| __| | | |/ _ \| '_ \| | | | __|
| |___ / \ |___| |___| |___| | | | |_| |_| | (_) | | | | |_| | |_
|_____/_/\_\____|_____|_____|_| |_|\__|____/ \___/|_| |_|\__,_|\__|
by @JoeLeonJr (@FortyNorthSec)
[i] Generating your x86 .NET assembly.
warning CS8001: SDK path could not be resolved
error CS0006: Metadata file `System.Management' could not be found
[x] Error in generating x86 .NET assembly using MCS. See error message above.
This error should not pop up unless you run EXCELntDonut without using the install.sh bash script. In that case, you'll need to manually install mono-complete. This will download the relevant dependencies. You can install it using apt like this:
apt-get install mono-complete
root@kali:~/Desktop# EXCELntDonut -f test.cs
_______ ______ _____ _ _ ____ _
| ____\ \/ / ___| ____| | _ __ | |_| _ \ ___ _ __ _ _| |_
| _| \ / | | _| | | | '_ \| __| | | |/ _ \| '_ \| | | | __|
| |___ / \ |___| |___| |___| | | | |_| |_| | (_) | | | | |_| | |_
|_____/_/\_\____|_____|_____|_| |_|\__|____/ \___/|_| |_|\__,_|\__|
by @JoeLeonJr (@FortyNorthSec)
[i] Generating your x86 .NET assembly.
error CS5001: Program `_excelntdonut_GJAoNuVPMcX.exe' does not contain a static `Main' method suitable for an entry point
[x] Error in generating x86 .NET assembly using MCS. See error message above.
At the moment, EXCELntDonut only allows C# files with payloads in the Main function.
Here are some Yara rules to start with by @InQuest:
Look for a very hidden sheet
https://github.com/InQuest/yara-rules/blob/master/Excel_Hidden_Macro_Sheet.rule
Look for the Auto_Open string
https://github.com/Neo23x0/signature-base/blob/master/yara/general_officemacros.yar
There's a lot of posts about using OLEDUMP.py to review XLM files. Consider this one:
https://clickallthethings.wordpress.com/2020/04/06/covid-19-excel-4-0-macros-and-sandbox-detection/
This wouldn't even be on our radar without the fantastic work done by the folks at Outflank (@outflanknl). Special thanks to @StanHacked for his insight during this project. Also, equally, this project would not be possible without Donut (by @TheWover and @odzhan) and the related python library (by @byt3bl33d3r). Related, the team at Accenture created CLRvoyance, which solved some x64 issues we couldn't figure out with Donut + XLM 4.0 macros. Finally, thanks to Philip Tsukerman with Cybereason for the awesome research on making XLM macros compatible with 64-bit versions of Excel.
We are not responsible for misuse of this tool. This tool was generated for educational and authorized-testing purposes to demonstrate how C# source code can be injected into memory using a XLM (Excel 4.0) macro. The ultimate goal of this project is to (1) provide red teamers another phishing payload option to emulate what actual adversaries are currently using, and (2) provide defenders a frame of reference for building analytics and mitigations. Without a tool to quickly generate this type of payload, we believe defenders will not be adequately prepared for what's actually coming their way. Please act responsibly.
Please see the license file in this folder. Please note that this tool incorporates two other open source tools including Donut and CLRvoyance.