diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2019-04-13 19:23:34 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2019-04-13 19:23:34 +0200 |
commit | 6dd2d7148cf142f91886b5dc8cba7b9d1cc0766a (patch) | |
tree | b1512e4b8e21a1add5b81620edbb5488ba582932 | |
parent | a7de36e0225748e7d97ce32905c9a4efc19d0b19 (diff) |
encrypt and decrypt c funcs at runtime
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | funccrypt.c | 148 |
1 files changed, 130 insertions, 18 deletions
diff --git a/funccrypt.c b/funccrypt.c index cce1e11..9235b0f 100644 --- a/funccrypt.c +++ b/funccrypt.c @@ -1,59 +1,116 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> +#include <time.h> #include <stdint.h> +#include <errno.h> +#include <sys/mman.h> /* PROT_* */ -#define CRYPT_PROLOGUE \ + +/* Force GCC struct for MingW compilers and pack them, + * which means the struct is 1-byte aligned. + */ +#define GCC_PACKED __attribute__((packed, gcc_struct)) + +typedef struct crypt_header { + uint64_t key; + uint8_t crpyted; + uint32_t marker; + uint64_t func_body[0]; +} GCC_PACKED crypt_header; + +#define CRYPT_FUNC(fn) \ + crypt_func((void *)fn) +#define CRYPT_PROLOGUE(fn) \ { \ + CRYPT_FUNC(fn); \ asm volatile goto("jmp %l0 \n" \ : : : : cr_prologue); \ asm volatile( \ - ".byte 0xDE, 0xC0, 0xDE, 0xC0; \n" \ + ".byte " \ + /* key: */ "0x00, 0x00, 0x00, 0x00," \ + "0x00, 0x00, 0x00, 0x00," \ + /* crypted: */ "0x00," \ + /* marker: */ "0xDE, 0xC0, 0xDE, 0xC0; \n" \ ); \ } \ cr_prologue: { -#define CRYPT_EPILOGUE \ +#define CRYPT_EPILOGUE(fn) \ } { \ asm volatile goto("jmp %l0 \n" \ : : : : cr_epilogue); \ asm volatile( \ - ".byte 0xFE, 0xCA, 0xFE, 0xCA; \n" \ + ".byte " \ + /* Insert encryption gap, so we can find the end marker, + * while the function body is encrypted. + */ \ + "0x00, 0x00, 0x00, 0x00," \ + "0x00, 0x00, 0x00, 0x00," \ + /* marker: */ "0xFE, 0xCA, 0xFE, 0xCA; \n" \ ); \ } \ cr_epilogue: \ - asm volatile("nop; \n"); + CRYPT_FUNC(fn); + +#define CRYPT_FNDEF(name, ...) \ + void name( __VA_ARGS__ ) { \ + CRYPT_PROLOGUE( name ); +#define CRYPT_FNEND(name) \ + CRYPT_EPILOGUE(name); \ + } + typedef enum crypt_return { - CRET_ERROR, CRET_PROLOGUE, CRET_EPILOGUE + CRET_ERROR, CRET_PROLOGUE, CRET_EPILOGUE, CRET_CHECK, CRET_OK } crypt_return; +static const char *crypt_strs[] = { + "ERROR", "PROLOGUE", "EPILOGUE", "CHECK", "OK" +}; + + +static crypt_return crypt_func(void *fn_start); +static void printHexBuf(uint8_t *buf, size_t siz, size_t chars_per_line); static int crypted_fn(int arg0, char *arg1, void *arg2) { - CRYPT_PROLOGUE + CRYPT_PROLOGUE(crypted_fn); int i; printf("I'm decrypted ..\n"); for (i = 0; i < 32; ++i) printf("%d ", i); puts(""); - CRYPT_EPILOGUE + CRYPT_EPILOGUE(crypted_fn); return 0x66; } static void crypted_fn2(void) { - CRYPT_PROLOGUE + CRYPT_PROLOGUE(crypted_fn2); printf("Another decrypted fn..\n"); - CRYPT_EPILOGUE + CRYPT_EPILOGUE(crypted_fn2); +} + +CRYPT_FNDEF(crypted_fn3, void *arg0, int arg1, const char *arg2) +{ + printf("Yet another cryptable fn.. "); + /* generate some nonsense machine instructions */ + printf("."); printf("."); printf("."); printf("."); + printf("\n"); } +CRYPT_FNEND(crypted_fn3); static crypt_return crypt_func(void *fn_start) { - int i; + size_t i; enum crypt_return cret = CRET_ERROR; uint8_t *fnbuf = (uint8_t *) fn_start; + uint8_t *pro, *epi, *mbuf; const uint32_t prologue_marker = 0xC0DEC0DE; const uint32_t epilogue_marker = 0xCAFECAFE; + crypt_header *hdr; + size_t crypt_size; printf("Fn: %p\n", fnbuf); for (i = 0; i < 0x100; ++i) { @@ -61,46 +118,101 @@ static crypt_return crypt_func(void *fn_start) *(uint32_t *) &fnbuf[i] == prologue_marker) { printf("Prologue Marker: %p\n", &fnbuf[i]); + pro = &fnbuf[i]; cret = CRET_PROLOGUE; } else if (cret == CRET_PROLOGUE && *(uint32_t *) &fnbuf[i] == epilogue_marker) { printf("Epilogue Marker: %p\n", &fnbuf[i]); + epi = &fnbuf[i]; cret = CRET_EPILOGUE; break; } } + if (cret == CRET_EPILOGUE && + i >= sizeof *hdr) + { + cret = CRET_CHECK; +#if 0 + printf("Prologue: "); + printHexBuf(pro - 9, 13, 13); + printf("Epilogue: "); + printHexBuf(epi, 4, 4); +#endif + hdr = (crypt_header *)(pro + sizeof(prologue_marker) - sizeof *hdr); + crypt_size = epi - (pro + sizeof(prologue_marker)) - 1; + + if (i && + (hdr->crpyted == 0x00 || hdr->crpyted == 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)) + { + if (hdr->crpyted == 0x00) { + hdr->crpyted = 0xFF; + hdr->key = (uint64_t) rand() << 32; + hdr->key |= rand(); + } + for (i = 0; i < crypt_size / 0x8; ++i) { + hdr->func_body[i] ^= hdr->key; + } + + if (!mprotect(mbuf, sysconf(_SC_PAGESIZE), PROT_READ|PROT_EXEC)) + cret = CRET_OK; + } + } + } + return cret; } static void printHexBuf(uint8_t *buf, size_t siz, size_t chars_per_line) { - int i; + size_t i; for (i = 0; i < siz; ++i) { printf("%02X ", buf[i]); if ((i+1) % chars_per_line == 0) printf("\n"); } - printf("\n"); + if ((i) % chars_per_line != 0) + printf("\n"); } int main(void) { + srand(time(NULL)); + + printf("Before Encryption:\n"); printf("crypted_fn:\n"); - printHexBuf((uint8_t *)crypted_fn, 32, 16); + printHexBuf((uint8_t *)crypted_fn, 160, 32); printf("crypted_fn2:\n"); - printHexBuf((uint8_t *)crypted_fn2, 32, 16); + printHexBuf((uint8_t *)crypted_fn2, 160, 32); + printf("crypted_fn3:\n"); + printHexBuf((uint8_t *)crypted_fn3, 160, 32); - printf("crypt_func:\n"); - crypt_func((void *)crypted_fn); - crypt_func((void *)crypted_fn2); + printf("\nAfter Encryption:\n"); + printf("crypted_fn return val: %s\n", + crypt_strs[ crypt_func((void *)crypted_fn) ]); + printf("crypted_fn2 return val: %s\n", + crypt_strs[ crypt_func((void *)crypted_fn2) ]); + printf("crypted_fn3 return val: %s\n", + crypt_strs[ crypt_func((void *)crypted_fn3) ]); + + 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"); return 0; } |