mirror of https://github.com/qwqdanchun/donut.git
update python bindings for msvc and docs
This commit is contained in:
parent
7d2cfa0aea
commit
e39e57ab57
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -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
|
||||
|
|
30
README.md
30
README.md
|
@ -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
26
donut.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
29
format.c
29
format.c
|
@ -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++){
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
8
setup.py
8
setup.py
|
@ -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]
|
||||
|
||||
|
|
Loading…
Reference in New Issue