update python bindings for msvc and docs

This commit is contained in:
odzhan 2019-12-19 13:07:53 +00:00
parent 7d2cfa0aea
commit e39e57ab57
10 changed files with 80 additions and 64 deletions

View File

@ -5,25 +5,23 @@ All notable changes to this project will be documented in this file.
### Added
* The -e switch can be used to disable entropy and/or encryption. Options are: 1=none, 2=generate random names, 3=generate random names + encrypt.
* The -z switch on Windows specifies compression of the file. Supported algorithms are 1=none, 2=aPLib or 3=LZNT1, 4=Xpress and 5=Xpress Huffman via the RtlCompressBuffer API. See donut.c!get_file_info.
* The -f switch specifies the output format.
binary, base64, c, ruby, python, powershell and hex stored in encode.c. Base64 strings are copied to the clipboard on Windows.
* The -t switch tells the loader to run unmanaged entrypoint for EXE as a thread. Attempts to replace exit-related API in Import Address Table with RtlExitUserThread.
* The -n switch can be used to specify name of module for HTTP staging.
* The -s switch specifies HTTP server to download module from.
* The -y switch is experimental and may be removed from future versions. It creates a new thread for the loader and continues executing at a specific address or Original Entry Point (OEP).
* The -x switch can be used to specify how loader terminates. Useful if user wants to terminate the host process.
* If the user uses the -p switch to specify parameters for an unmanaged EXE file, the Command line read by GetCommandLineA, GetCommandLineW, __getmainargs, __wgetmainargs, _acmdln, _wcmdln, __argv and __wargv are replaced.
* The -w switch tells the loader to convert parameters/command line to UNICODE before passing to unmanaged DLL function.
* 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.
* 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.
* 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.
* 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.
* The -n switch can be used to specify name of module for HTTP staging. If entropy is enabled, this is generated randomly.
* The -s switch specifies the HTTP server to download module from.
* 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.
* The -x switch can be used to specify how loader terminates. 1=exit thread, 2=exit process.
* 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.
* The -w switch tells the loader to convert parameters to UNICODE before passing to unmanaged DLL function.
* C# generator by n1xbyte: https://github.com/n1xbyte/donutCS
* Go generator by awgh https://github.com/Binject/go-donut
* Added support for aPLib. Since there's no source code for the compressor, this may be removed in future.
### Changed
* 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.
* The -u switch to specify URL for HTTP stager is replaced with -s switch to prepare for DNS stager.
* The -u switch to specify URL for HTTP stager is replaced with -s switch to prepare for a DNS stager.
* The -f switch to specify input file is now used to specify output format of loader.
### Removed

View File

@ -1,6 +1,6 @@
# Using Donut
![Alt text](https://github.com/TheWover/donut/blob/master/img/donut.PNG?raw=true "An ASCII donut")
![Alt text](https://github.com/TheWover/donut/blob/master/img/donut.PNG?raw=true "An ASCII donut")
Version: 0.9.3 *please submit issues and requests for v1.0 release*
@ -12,7 +12,7 @@ v0.9.2 release blog post: https://thewover.github.io/Bear-Claw/
## Introduction
Donut generates x86 or x64 shellcode from VBScript, JScript, EXE, DLL (including .NET Assemblies) files. This shellcode can be injected into an arbitrary Windows process for in-memory execution. Given a supported file type, parameters and an entry point where applicable (such as Program.Main), it produces position-independent shellcode that loads and runs entirely from memory. A module created by donut can either be staged from a URL or stageless by being embedded directly in the shellcode. Either way, the module is encrypted with the Chaskey block cipher and a 128-bit randomly generated key. After the file is loaded through the PE/ActiveScript/CLR loader, the original reference is erased from memory to deter memory scanners. For .NET Assemblies, they are loaded into a new Application Domain to allow for running Assemblies in disposable AppDomains.
Donut generates x86 or x64 shellcode from VBScript, JScript, EXE, DLL (including .NET Assemblies) files. This shellcode can be injected into an arbitrary Windows process for in-memory execution. Given a supported file type, parameters and an entry point where applicable (such as Program.Main), it produces position-independent shellcode that loads and runs entirely from memory. A module created by donut can either be staged from a HTTP server or stageless by being embedded directly in the shellcode. Either way, the module is encrypted with the Chaskey block cipher and a 128-bit randomly generated key. After the file is loaded through the PE/ActiveScript/CLR loader, the original reference is erased from memory to deter memory scanners. For .NET Assemblies, they are loaded into a new Application Domain to allow for running Assemblies in disposable AppDomains.
It can be used in several ways.
@ -49,7 +49,7 @@ Donut can be used as-is to generate shellcode from VBS/JS/EXE/DLL files or .NET
-w Command line is passed to unmanaged DLL function in UNICODE format. (default is ANSI)
-r <version> CLR runtime version. MetaHeader used by default or v4.0.30319 if none available.
-t Create new thread for entrypoint of unmanaged EXE.
-z <engine> Pack/Compress file. 1=none, 2=aPLib
-z <engine> Pack/Compress file. 1=none, 2=aPLib, 3=LZNT1, 4=Xpress, 5=Xpress Huffman
examples:
@ -79,42 +79,50 @@ git clone http://github.com/thewover/donut
cd donut
```
## Linux
## GNU Compiler Collection (GCC)
Simply run make to generate an executable, static and dynamic libraries.
Compiling the loader on Linux without MinGW installed is currently not supported.
Simply run make to build the generator, static and dynamic libraries. If you need to track down problems, use the debug label.
```
make
make clean
make debug
```
## Windows
## Microsoft Visual Studio
Start a Microsoft Visual Studio Developer Command Prompt and `` cd `` to donut's directory. The Microsft (non-gcc) Makefile can be specified with ``` -f Makefile.msvc ```. The makefile provides the following commmands to build donut:
```
nmake -f Makefile.msvc
nmake clean -f Makefile.msvc
nmake debug -f Makefile.msvc
```
## MinGW-64
The loader, generator, dynamic and static libraries can be compiled if MinGW-64 is installed.
```
make -f Makefile.mingw
make debug -f Makefile.mingw
```
## As a Library
donut can be compiled as both dynamic and static libraries for both Linux (*.a* / *.so*) and Windows(*.lib* / *.dll*). It has a simple API that is described <a href="https://github.com/TheWover/donut/blob/master/docs/api.md">here</a>. Three exported functions are provided: ``` int DonutCreate(PDONUT_CONFIG c) ```, ```int DonutDelete(PDONUT_CONFIG c)``` and ```const char* DonutError(int error)```.
Donut can be compiled as both dynamic and static libraries for both Linux (*.a* / *.so*) and Windows(*.lib* / *.dll*). It has a simple API that is described <a href="https://github.com/TheWover/donut/blob/master/docs/api.md">here</a>. Three exported functions are provided: ``` int DonutCreate(PDONUT_CONFIG c) ```, ```int DonutDelete(PDONUT_CONFIG c)``` and ```const char* DonutError(int error)```.
## As a Python Module
Donut can be installed and used as a Python module. To install Donut from your current directory, use pip for Python3.
```
pip install .
pip3 install .
```
Otherwise, you may install Donut as a Python module by grabbing it from the PyPi repostiory.
```
pip install donut-shellcode
pip3 install donut-shellcode
```
## Bypasses

26
donut.c
View File

@ -433,7 +433,7 @@ int compress_file(PDONUT_CONFIG c) {
DPRINT("Original file size : %"PRId32 " | Compressed : %"PRId32, fi.len, fi.zlen);
DPRINT("File size reduced by %"PRId32"%%", file_diff(fi.zlen, fi.len));
}
DPRINT("Leaving with %" PRId32, err);
DPRINT("Leaving with error : %" PRId32, err);
return err;
}
@ -579,7 +579,7 @@ cleanup:
DPRINT("Unmapping input file due to errors.");
unmap_file();
}
DPRINT("Leaving with %" PRId32, err);
DPRINT("Leaving with error : %" PRId32, err);
return err;
}
@ -781,7 +781,7 @@ cleanup:
DPRINT("Releasing memory due to errors.");
free(mod);
}
DPRINT("Leaving with %" PRId32, err);
DPRINT("Leaving with error : %" PRId32, err);
return err;
}
@ -1039,7 +1039,7 @@ cleanup:
DPRINT("Releasing memory for module due to errors.");
free(c->mod);
}
DPRINT("Leaving with %" PRId32, err);
DPRINT("Leaving with error : %" PRId32, err);
return err;
}
@ -1062,12 +1062,12 @@ static int save_file(const char *path, void *data, int len) {
out = fopen(path, "wb");
if(out != NULL) {
DPRINT("Writing %" PRId32 " bytes of %p which has %"PRId32 " bytes available to %s", len, data, _msize(data), path);
DPRINT("Writing %d bytes of %p which has %zd bytes available to %s", len, data, _msize(data), path);
fwrite(data, 1, len, out);
fclose(out);
} else err = DONUT_ERROR_FILE_ACCESS;
DPRINT("Leaving with %" PRId32, err);
DPRINT("Leaving with error : %" PRId32, err);
return err;
}
@ -1136,7 +1136,7 @@ static int save_loader(PDONUT_CONFIG c) {
switch(c->format) {
case DONUT_FORMAT_BINARY: {
DPRINT("Saving loader as raw data");
DPRINT("Saving loader as binary");
fwrite(c->pic, 1, c->pic_len, fd);
err = DONUT_ERROR_SUCCESS;
break;
@ -1169,7 +1169,7 @@ static int save_loader(PDONUT_CONFIG c) {
break;
}
fclose(fd);
DPRINT("Leaving with %" PRId32, err);
DPRINT("Leaving with error : %" PRId32, err);
return err;
}
@ -1278,12 +1278,12 @@ static int build_loader(PDONUT_CONFIG c) {
* OUTPUT : Donut error code.
*/
static int validate_loader_cfg(PDONUT_CONFIG c) {
int url_len;
uint32_t url_len;
DPRINT("Validating loader configuration.");
if(c == NULL || c->input[0] == 0) {
DPRINT("No configuration or file provided.");
DPRINT("No configuration or input file provided.");
return DONUT_ERROR_INVALID_PARAMETER;
}
@ -1340,7 +1340,7 @@ static int validate_loader_cfg(PDONUT_CONFIG c) {
return DONUT_ERROR_INVALID_URL;
}
// invalid length?
url_len = strlen(c->server);
url_len = (uint32_t)strlen(c->server);
if(url_len <= 8) {
DPRINT("URL length : %" PRId32 " is invalid.", url_len);
@ -1537,7 +1537,7 @@ int DonutCreate(PDONUT_CONFIG c) {
if(err != DONUT_ERROR_SUCCESS) {
DonutDelete(c);
}
DPRINT("Leaving with %" PRId32, err);
DPRINT("Leaving with error : %" PRId32, err);
return err;
}
@ -1575,6 +1575,8 @@ int DonutDelete(PDONUT_CONFIG c) {
free(c->pic);
c->pic = NULL;
}
unmap_file();
DPRINT("Leaving.");
return DONUT_ERROR_SUCCESS;
}

View File

@ -57,11 +57,11 @@ static void chaskey(void *mk, void *p) {
}
// encrypt/decrypt data in counter mode
void donut_encrypt(void *mk, void *ctr, void *data, size_t len) {
void donut_encrypt(void *mk, void *ctr, void *data, uint32_t len) {
uint8_t x[CIPHER_BLK_LEN],
*p=(uint8_t*)data,
*c=(uint8_t*)ctr;
int i, r;
uint32_t i, r;
while(len) {
// copy counter+nonce to local buffer
@ -81,7 +81,7 @@ void donut_encrypt(void *mk, void *ctr, void *data, size_t len) {
len -= r; p += r;
// update counter
for(i=CIPHER_BLK_LEN;i>0;i--)
for(i=CIPHER_BLK_LEN;(int)i>0;i--)
if(++c[i-1]) break;
}
}

View File

@ -55,8 +55,7 @@ static int b64_encode(
const void *src, uint32_t inlen,
void *dst, uint32_t *outlen)
{
uint32_t len, x;
int i = 0;
uint32_t i, len, x;
uint8_t *in = (uint8_t*)src, *out = (uint8_t*)dst;
// check arguments
@ -96,11 +95,11 @@ static int b64_encode(
// add null terminator
*out = 0;
// calculate output length by subtracting 2 pointers
*outlen = (out - (uint8_t*)dst);
*outlen = (uint32_t)(out - (uint8_t*)dst);
return 1;
}
int base64_template(void *pic, uint64_t pic_len, FILE *fd) {
int base64_template(void *pic, uint32_t pic_len, FILE *fd) {
uint32_t outlen;
void *base64;
@ -147,8 +146,8 @@ int base64_template(void *pic, uint64_t pic_len, FILE *fd) {
return DONUT_ERROR_SUCCESS;
}
int c_ruby_template(void * pic, uint64_t pic_len, FILE* fd){
uint64_t j;
int c_ruby_template(void * pic, uint32_t pic_len, FILE* fd){
uint32_t j;
uint8_t *p = (uint8_t*)pic;
fprintf(fd, "unsigned char buf[] = \n");
@ -169,8 +168,8 @@ int c_ruby_template(void * pic, uint64_t pic_len, FILE* fd){
return DONUT_ERROR_SUCCESS;
}
int py_template(void * pic, uint64_t pic_len, FILE* fd){
uint64_t j;
int py_template(void * pic, uint32_t pic_len, FILE* fd){
uint32_t j;
uint8_t *p = (uint8_t*)pic;
fprintf(fd, "buf = \"\"\n");
@ -191,8 +190,8 @@ int py_template(void * pic, uint64_t pic_len, FILE* fd){
return DONUT_ERROR_SUCCESS;
}
int powershell_template(void * pic, uint64_t pic_len, FILE* fd){
uint64_t j;
int powershell_template(void * pic, uint32_t pic_len, FILE* fd){
uint32_t j;
uint8_t *p = (uint8_t*)pic;
fprintf(fd, "[Byte[]] $buf = ");
@ -204,11 +203,11 @@ int powershell_template(void * pic, uint64_t pic_len, FILE* fd){
return DONUT_ERROR_SUCCESS;
}
int csharp_template(void * pic, uint64_t pic_len, FILE* fd){
uint64_t j;
int csharp_template(void * pic, uint32_t pic_len, FILE* fd){
uint32_t j;
uint8_t *p = (uint8_t*)pic;
fprintf(fd, "byte[] my_buf = new byte[%" PRId64"] {\n", pic_len);
fprintf(fd, "byte[] my_buf = new byte[%" PRId32"] {\n", pic_len);
for(j=0; j < pic_len; j++){
fprintf(fd, "0x%02x", p[j]);
@ -219,8 +218,8 @@ int csharp_template(void * pic, uint64_t pic_len, FILE* fd){
return DONUT_ERROR_SUCCESS;
}
int hex_template(void * pic, uint64_t pic_len, FILE* fd){
uint64_t j;
int hex_template(void * pic, uint32_t pic_len, FILE* fd){
uint32_t j;
uint8_t *p = (uint8_t*)pic;
for(j=0; j < pic_len; j++){

View File

@ -32,6 +32,11 @@
#ifndef DONUT_H
#define DONUT_H
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_DEPRECATE
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

View File

@ -51,7 +51,7 @@
extern "C" {
#endif
void donut_encrypt(void *mk, void *ctr, void *data, size_t len);
void donut_encrypt(void *mk, void *ctr, void *data, uint32_t len);
#define donut_decrypt(mk,ctr,data,len) donut_encrypt(mk,ctr,data,len)

View File

@ -38,12 +38,12 @@
extern "C" {
#endif
int base64_template(void *pic, uint64_t pic_len, FILE *fd);
int c_ruby_template(void *pic, uint64_t pic_len, FILE *fd);
int py_template(void *pic, uint64_t pic_len, FILE* fd);
int powershell_template(void *pic, uint64_t pic_len, FILE *fd);
int csharp_template(void *pic, uint64_t pic_len, FILE *fd);
int hex_template(void *pic, uint64_t pic_len, FILE *fd);
int base64_template(void *pic, uint32_t pic_len, FILE *fd);
int c_ruby_template(void *pic, uint32_t pic_len, FILE *fd);
int py_template(void *pic, uint32_t pic_len, FILE* fd);
int powershell_template(void *pic, uint32_t pic_len, FILE *fd);
int csharp_template(void *pic, uint32_t pic_len, FILE *fd);
int hex_template(void *pic, uint32_t pic_len, FILE *fd);
#ifdef __cplusplus
}

View File

@ -13,7 +13,7 @@
#include "mmap.h"
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
void *mmap(void *start, uint32_t length, int prot, int flags, int fd, off_t offset)
{
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
return MAP_FAILED;

View File

@ -8,7 +8,7 @@ static_lib_dir = 'lib'
libraries = []
library_dirs = ['lib']
extra_compile_args = []
extra_link_args = ['-Llib']
extra_link_args = []
extra_objects = []
include_dirs = ['include']
sources = ['donut.c',
@ -18,10 +18,14 @@ sources = ['donut.c',
'loader/clib.c',
'donutmodule.c']
if sys.platform == 'win64':
if sys.platform == 'win32':
libraries.extend(static_libraries)
library_dirs.append(static_lib_dir)
extra_objects = []
elif sys.platform == 'win64':
libraries.extend(static_libraries)
library_dirs.append(static_lib_dir)
extra_objects = []
else: # POSIX
extra_objects = ['{}/{}.a'.format(static_lib_dir, l) for l in static_libraries]