diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2020-10-05 21:19:18 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2020-10-05 21:34:24 +0200 |
commit | 180ad72e3f6d0efd01a38800efc3ed67e07b9592 (patch) | |
tree | 1938cec760a15cfa38e9ff50e5f1ff21006aae4f | |
parent | 77d148bc55d1f87c5f6eb55e099c72008423a27f (diff) |
Added support for entropy calculation.
* Currently used for encryption on function level.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | Makefile | 23 | ||||
-rw-r--r-- | funccrypt.c | 186 | ||||
-rw-r--r-- | utils.h | 51 |
3 files changed, 181 insertions, 79 deletions
@@ -22,12 +22,11 @@ NF64 := elf64 endif STRIP := strip LBITS := $(shell getconf LONG_BIT) -CFLAGS += -Wall -O0 -g +CFLAGS += -Wall -O0 -g3 OCFLAGS := -fno-stack-protector -fno-pie -ggdb -static ifeq ($(BUILD_MINGW32),) OCFLAGS += -zexecstack -znorelro endif -ECFLAGS += -Wall -O2 -ggdb X86_FLAGS = -m32 -mpreferred-stack-boundary=2 X64_FLAGS = -m64 -mpreferred-stack-boundary=4 SOURCES = $(wildcard *.c) @@ -42,21 +41,21 @@ endif main: $(TARGETS) exec_payload: exec_payload.c - $(CC) $(ECFLAGS) -m32 -o $@$(SF) $< + $(CC) $(CFLAGS) -m32 -o $@$(SF) $< ifneq ($(SF),) $(LN) -f -s $@$(SF) $@ endif exec_payload_x64: exec_payload.c - $(CC) $(ECFLAGS) -m64 -o $@$(SF) $< + $(CC) $(CFLAGS) -m64 -o $@$(SF) $< exec_payload_bin.o: exec_payload $(STRIP) -s $<$(SF) $(AS) -f$(NF32) -o $@ exec_crypter.asm exec_crypter: exec_payload_bin.o exec_crypter.c - $(CC) $(ECFLAGS) -m32 -D_NOTASKID=1 -o $@.o -c $@.c - $(CC) $(ECFLAGS) -m32 -D_NOTASKID=1 -o $@ $(patsubst %.c,%.o,$^) + $(CC) $(CFLAGS) -m32 -D_NOTASKID=1 -o $@.o -c $@.c + $(CC) $(CFLAGS) -m32 -D_NOTASKID=1 -o $@ $(patsubst %.c,%.o,$^) ifneq ($(SF),) $(LN) -f -s $@$(SF) $@ endif @@ -66,14 +65,14 @@ exec_payload_x64_bin.o: exec_payload_x64 $(AS) -f$(NF64) -o $@ exec_crypter_x64.asm exec_crypter_x64: exec_payload_x64_bin.o exec_crypter.c - $(CC) $(ECFLAGS) -m64 -D_NOTASKID=1 -o $@.o -c exec_crypter.c - $(CC) $(ECFLAGS) -m64 -D_NOTASKID=1 -o $@ exec_payload_x64_bin.o exec_crypter_x64.o + $(CC) $(CFLAGS) -m64 -D_NOTASKID=1 -o $@.o -c exec_crypter.c + $(CC) $(CFLAGS) -m64 -D_NOTASKID=1 -o $@ exec_payload_x64_bin.o exec_crypter_x64.o -funccrypt: funccrypt.c - $(CC) $(ECFLAGS) -m32 -o $@ $< +funccrypt: funccrypt.c utils.h + $(CC) $(CFLAGS) -m32 -o $@ $< -lm -funccrypt_x64: funccrypt.c - $(CC) $(ECFLAGS) -m64 -o $@ $< +funccrypt_x64: funccrypt.c utils.h + $(CC) $(CFLAGS) -m64 -o $@ $< -lm debug: $(MAKE) -C . CFLAGS="-g" diff --git a/funccrypt.c b/funccrypt.c index e5d8c0b..1367005 100644 --- a/funccrypt.c +++ b/funccrypt.c @@ -1,3 +1,4 @@ +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -5,7 +6,11 @@ #include <stdint.h> #include <errno.h> #include <sys/mman.h> /* PROT_* */ +#include <string.h> /* strdup() */ +#include "utils.h" + +//#define VERBOSE 1 #ifndef __GNUC__ #error "Unknown compiler; Only GCC supports `asm goto'." @@ -29,7 +34,7 @@ typedef struct crypt_header { #define CRYPT_FUNC_MAXSIZ 0x100 #define CRYPT_FUNC(fn) \ - crypt_func((void *)fn, 0) + crypt_func((void *)fn, 0, NULL, NULL) #define CRYPT_PROLOGUE(fn) \ crypt_return __cr; \ { \ @@ -83,39 +88,42 @@ static const char *crypt_strs[] = { }; -static crypt_return crypt_func(void *fn_start, int do_check); +static crypt_return crypt_func(void *fn_start, int do_check, struct crypt_header ** const func_crypt_header, + size_t * const func_body_size); static void printHexBuf(uint8_t *buf, size_t siz, size_t chars_per_line); -static int crypted_fn(int arg0, char *arg1, void *arg2) +static int some_fn(int arg0, char *arg1, void *arg2) { - CRYPT_PROLOGUE(crypted_fn); + CRYPT_PROLOGUE(some_fn); int i; - printf("I'm decrypted ..\n"); + printf("I'm decrypted .. args: %d, %s, %p\n", arg0, arg1, arg2); for (i = 0; i < 32; ++i) printf("%d ", i); puts(""); - CRYPT_EPILOGUE(crypted_fn); + CRYPT_EPILOGUE(some_fn); return 0x66; } -static void crypted_fn2(void) +static void another_fn(void) { - CRYPT_PROLOGUE(crypted_fn2); + CRYPT_PROLOGUE(another_fn); printf("Another decrypted fn..\n"); - CRYPT_EPILOGUE(crypted_fn2); + CRYPT_EPILOGUE(another_fn); } -CRYPT_FNDEF(crypted_fn3, void *arg0, int arg1, const char *arg2) +CRYPT_FNDEF(fndef_fn, void *arg0, int arg1, const char *arg2) { - printf("Yet another cryptable fn.. "); + printf("Yet another cryptable fn.. args: %p, %d, %s", arg0, arg1, arg2); /* generate some nonsense machine instructions */ printf("."); printf("."); printf("."); printf("."); printf("\n"); } -CRYPT_FNEND(crypted_fn3); +CRYPT_FNEND(fndef_fn); -static crypt_return crypt_func(void *fn_start, int do_check) +static crypt_return crypt_func(void *fn_start, int do_check, + struct crypt_header ** const func_crypt_header, + size_t * const func_body_size) { size_t i; enum crypt_return cret = CRET_ERROR; @@ -123,15 +131,15 @@ static crypt_return crypt_func(void *fn_start, int do_check) uint8_t *pro, *epi, *mbuf; const uint32_t prologue_marker = 0xC0DEC0DE; const uint32_t epilogue_marker = 0xCAFECAFE; - crypt_header *hdr; - size_t crypt_size; + crypt_header *hdr = NULL; + size_t crypt_size = 0; printf("Fn: %p\n", fnbuf); for (i = 0; i < CRYPT_FUNC_MAXSIZ; ++i) { if (cret == CRET_ERROR && *(uint32_t *) &fnbuf[i] == prologue_marker) { -#if 0 +#if VERBOSE printf("Prologue Marker: %p\n", &fnbuf[i]); #endif pro = &fnbuf[i]; @@ -140,7 +148,7 @@ static crypt_return crypt_func(void *fn_start, int do_check) if (cret == CRET_PROLOGUE && *(uint32_t *) &fnbuf[i] == epilogue_marker) { -#if 0 +#if VERBOSE printf("Epilogue Marker: %p\n", &fnbuf[i]); #endif epi = &fnbuf[i]; @@ -153,23 +161,24 @@ static crypt_return crypt_func(void *fn_start, int do_check) i >= sizeof *hdr) { cret = CRET_CHECK; -#if 0 +#if VERBOSE printf("Prologue: "); printHexBuf(pro - 9, 13, 13); printf("Epilogue: "); printHexBuf(epi, 4, 4); #endif hdr = (crypt_header *)(pro + sizeof(prologue_marker) - sizeof *hdr); - if (do_check) { - return hdr->crypted == 0x00 - ? CRET_CHECK_PLAIN - : CRET_CHECK_ENCRYPTED; - } - crypt_size = epi - (pro + sizeof(prologue_marker)) - 1; - - if (i && - (hdr->crypted == 0x00 || hdr->crypted == 0xFF) && - (long int)crypt_size < sysconf(_SC_PAGESIZE)) + crypt_size = epi - (pro + sizeof(prologue_marker)); + if (do_check) + { + if (hdr->crypted == 0x00) { + cret = CRET_CHECK_PLAIN; + } else { + cret = CRET_CHECK_ENCRYPTED; + } + } else if (i && + (hdr->crypted == 0x00 || hdr->crypted == 0xFF) && + (long int)crypt_size < sysconf(_SC_PAGESIZE)) { mbuf = (uint8_t *)( (long int)hdr & ~(sysconf(_SC_PAGESIZE) - 1) ); if (!mprotect(mbuf, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE|PROT_EXEC)) @@ -191,6 +200,13 @@ static crypt_return crypt_func(void *fn_start, int do_check) } } + if (func_crypt_header) { + *func_crypt_header = hdr; + } + if (func_body_size) { + *func_body_size = crypt_size; + } + return cret; } @@ -207,51 +223,87 @@ static void printHexBuf(uint8_t *buf, size_t siz, size_t chars_per_line) printf("\n"); } +static void calcAndPrintEntropy(struct crypt_header * const func_crypt_header, + size_t const func_body_size) +{ + printf("Entropy of %p with size %zu: %lf\n", func_crypt_header, func_body_size, + entropy_from_buffer((uint8_t *)func_crypt_header->func_body, func_body_size)); +} + int main(void) { + struct crypt_header * hdr = NULL; + size_t func_body_size = 0; crypt_return cret; srand(time(NULL)); - printf("Before Encryption:\n"); - printf("crypted_fn:\n"); - printHexBuf((uint8_t *)crypted_fn, 160, 32); - printf("crypted_fn2:\n"); - printHexBuf((uint8_t *)crypted_fn2, 160, 32); - printf("crypted_fn3:\n"); - printHexBuf((uint8_t *)crypted_fn3, 160, 32); - - printf("\nAfter Encryption:\n"); - - cret = crypt_func((void *)crypted_fn, 1); - printf("crypted_fn check return val: %s\n", crypt_strs[cret]); - if (cret == CRET_CHECK_PLAIN) - printf("crypted_fn return val: %s\n", - crypt_strs[ crypt_func((void *)crypted_fn, 0) ]); - - cret = crypt_func((void *)crypted_fn2, 1); - printf("crypted_fn2 check return val: %s\n", crypt_strs[cret]); - if (cret == CRET_CHECK_PLAIN) - printf("crypted_fn2 return val: %s\n", - crypt_strs[ crypt_func((void *)crypted_fn2, 0) ]); - - cret = crypt_func((void *)crypted_fn3, 1); - printf("crypted_fn3 check return val: %s\n", crypt_strs[cret]); - if (cret == CRET_CHECK_PLAIN) - printf("crypted_fn3 return val: %s\n", - crypt_strs[ crypt_func((void *)crypted_fn3, 0) ]); - - printf("crypted_fn:\n"); - printHexBuf((uint8_t *)crypted_fn, 160, 32); - printf("crypted_fn2:\n"); - printHexBuf((uint8_t *)crypted_fn2, 160, 32); - printf("crypted_fn3:\n"); - printHexBuf((uint8_t *)crypted_fn3, 160, 32); - - printf("\noutput:\n"); - printf("crypted_fn: 0x%X\n", crypted_fn(0, NULL, NULL)); - crypted_fn2(); - crypted_fn3(NULL, (unsigned int)-1, "TEST"); + cret = crypt_func((void *)some_fn, 1, &hdr, &func_body_size); + + printf("some_fn check return val: %s\n", crypt_strs[cret]); + calcAndPrintEntropy(hdr, func_body_size); + printf("some_fn unencrypted:\n"); + printHexBuf((uint8_t *)hdr->func_body, func_body_size, 32); + + if (cret == CRET_CHECK_PLAIN) { + cret = crypt_func((void *)some_fn, 0, &hdr, &func_body_size); + assert(cret == CRET_OK); + + printf("some_fn encryption return val: %s\n", crypt_strs[cret]); + calcAndPrintEntropy(hdr, func_body_size); + printf("some_fn encrypted:\n"); + printHexBuf((uint8_t *)hdr->func_body, func_body_size, 32); + } + + puts("\n"); + + cret = crypt_func((void *)another_fn, 1, &hdr, &func_body_size); + + printf("another_fn check return val: %s\n", crypt_strs[cret]); + calcAndPrintEntropy(hdr, func_body_size); + printf("another_fn unencrypted:\n"); + printHexBuf((uint8_t *)hdr->func_body, func_body_size, 32); + + if (cret == CRET_CHECK_PLAIN) { + cret = crypt_func((void *)another_fn, 0, &hdr, &func_body_size); + assert(cret == CRET_OK); + + printf("another_fn return val: %s\n", crypt_strs[cret]); + calcAndPrintEntropy(hdr, func_body_size); + printf("another_fn encrypted:\n"); + printHexBuf((uint8_t *)hdr->func_body, func_body_size, 32); + } + + puts("\n"); + + cret = crypt_func((void *)fndef_fn, 1, &hdr, &func_body_size); + + printf("fndef_fn check return val: %s\n", crypt_strs[cret]); + calcAndPrintEntropy(hdr, func_body_size); + printf("fndef_fn unencrypted:\n"); + printHexBuf((uint8_t *)hdr->func_body, func_body_size, 32); + + if (cret == CRET_CHECK_PLAIN) { + cret = crypt_func((void *)fndef_fn, 0, &hdr, &func_body_size); + assert(cret == CRET_OK); + + printf("fndef_fn return val: %s\n", crypt_strs[cret]); + calcAndPrintEntropy(hdr, func_body_size); + printf("fndef_fn encrypted:\n"); + printHexBuf((uint8_t *)hdr->func_body, func_body_size, 32); + } + + puts("\n"); + + printf("\n[output]\n"); + printf("some_fn:\n"); + char * blah = strdup("BLAH"); + printf("return value: 0x%X\n", some_fn(0, blah, NULL)); + free(blah); + printf("\nanother_fn:\n"); + another_fn(); + printf("\nfndef_fn:\n"); + fndef_fn(NULL, (unsigned int)-1, "TEST"); return 0; } @@ -0,0 +1,51 @@ +#ifndef UTILS_H +#define UTILS_H 1 + +#include <math.h> +#include <stdlib.h> +#include <unistd.h> + +#define MAXLEN 961 // maximum string length + +static inline size_t makehist(unsigned char const * const buf, ssize_t * const hist, size_t len) { + ssize_t wherechar[256]; + size_t i, histlen; + histlen = 0; + for (i = 0; i < 256; i++) + wherechar[i] = -1; + for (i = 0; i < len; i++) { + if (wherechar[buf[i]] == -1) { + wherechar[(int)buf[i]] = histlen; + histlen++; + } + hist[wherechar[(int)buf[i]]]++; + } + return histlen; +} + +static inline double entropy(ssize_t * const hist, size_t histlen, size_t len) { + size_t i; + double H; + H = 0.0; + for (i = 0; i < histlen; i++) { + H -= (double)hist[i] / len * log2((double)hist[i] / len); + } + return H; +} + +static inline double entropy_from_buffer(unsigned char const * const buffer, size_t size) +{ + ssize_t * const hist_array = malloc(size * sizeof(*hist_array)); + + if (!hist_array) { + return -1.0; + } + + size_t hist_length = makehist(buffer, hist_array, size); + double entr = entropy(hist_array, hist_length, size); + + free(hist_array); + return entr; +} + +#endif |