aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2020-10-05 21:19:18 +0200
committerToni Uhlig <matzeton@googlemail.com>2020-10-05 21:34:24 +0200
commit180ad72e3f6d0efd01a38800efc3ed67e07b9592 (patch)
tree1938cec760a15cfa38e9ff50e5f1ff21006aae4f
parent77d148bc55d1f87c5f6eb55e099c72008423a27f (diff)
Added support for entropy calculation.
* Currently used for encryption on function level. Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--Makefile23
-rw-r--r--funccrypt.c186
-rw-r--r--utils.h51
3 files changed, 181 insertions, 79 deletions
diff --git a/Makefile b/Makefile
index ba7fbf9..e5bc779 100644
--- a/Makefile
+++ b/Makefile
@@ -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;
}
diff --git a/utils.h b/utils.h
new file mode 100644
index 0000000..fa0e2e0
--- /dev/null
+++ b/utils.h
@@ -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