diff options
author | segfault <segfault@secmail.pro> | 2019-04-13 21:14:59 +0200 |
---|---|---|
committer | segfault <segfault@secmail.pro> | 2019-05-01 01:41:39 +0200 |
commit | 21144d5cb548f8fad5583e77fcce51e2e0a707e9 (patch) | |
tree | 9b2b8b5d55b3fb891999fde24882508643c83e81 |
initial commit
Signed-off-by: segfault <segfault@secmail.pro>
-rw-r--r-- | Makefile | 52 | ||||
-rw-r--r-- | example.c | 69 | ||||
-rw-r--r-- | funccrypt.c | 143 | ||||
-rw-r--r-- | funccrypt.h | 77 |
4 files changed, 341 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fec0abc --- /dev/null +++ b/Makefile @@ -0,0 +1,52 @@ +MAKE := make +CC32 := gcc -m32 +CC64 := gcc -m64 +ifneq ($(WIN32),) +CC32 := i686-w64-mingw32-gcc +SF32 := .exe +endif +ifneq ($(WIN64),) +CC64 := x86_64-w64-mingw32-gcc +SF64 := .exe +endif +RM := rm +CFLAGS := -Wall -std=gnu99 -Os +ifneq ($(NOPASTA),) +CFLAGS += -D_NOPASTA=1337 +endif +ifneq ($(DEBUG),) +CFLAGS += -g -D_DEBUG=1 +else +CFLAGS += -s +endif +ifneq ($(STATIC),) +CFLAGS += -static -ffunction-sections -fdata-sections -flto +endif +ifneq ($(SF32),) +INTERP32 := wine +endif +ifneq ($(SF64),) +INTERP64 := wine +endif + + +all: example_x86$(SF32) example_x64$(SF64) + +example_x86$(SF32): funccrypt.h funccrypt.c example.c + $(CC32) $(CFLAGS) $^ -o $@ + +example_x64$(SF64): funccrypt.h funccrypt.c example.c + $(CC64) $(CFLAGS) $^ -o $@ + +test: all + test -x example_x86$(SF32) && $(INTERP32) ./example_x86$(SF32) + test -x example_x64$(SF64) && $(INTERP64) ./example_x64$(SF64) + +full: + -$(MAKE) all + -$(MAKE) all WIN32=1 WIN64=1 + -$(MAKE) test + -$(MAKE) test WIN32=1 WIN64=1 + +clean: + $(RM) -f example_x86$(SF32) example_x64$(SF64) diff --git a/example.c b/example.c new file mode 100644 index 0000000..b2f7e89 --- /dev/null +++ b/example.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <time.h> + +#include "funccrypt.h" + + +static int crypted_fn(int arg0, char *arg1, void *arg2) +{ + CRYPT_PROLOGUE(crypted_fn); + int i; + printf("I'm decrypted ..\n"); + for (i = 0; i < 32; ++i) + printf("%d ", i); + puts(""); + CRYPT_EPILOGUE(crypted_fn); + + return 0x66; +} + +static void crypted_fn2(void) +{ + CRYPT_PROLOGUE(crypted_fn2); + printf("Another decrypted fn..\n"); + 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); + +int main(void) +{ + 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"); + 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; +} diff --git a/funccrypt.c b/funccrypt.c new file mode 100644 index 0000000..de51405 --- /dev/null +++ b/funccrypt.c @@ -0,0 +1,143 @@ +#include <stdio.h> +#include <unistd.h> +#ifdef __linux__ +#include <sys/mman.h> /* PROT_* */ +#else +#include <windows.h> +#endif + +#include "funccrypt.h" + +const char *crypt_strs[] = { + "ERROR", "PROLOGUE", "EPILOGUE", "CHECK", "OK" +}; + + +void printHexBuf(uint8_t *buf, size_t siz, size_t chars_per_line) +{ + size_t i; + + for (i = 0; i < siz; ++i) { + printf("%02X ", buf[i]); + if ((i+1) % chars_per_line == 0) + printf("\n"); + } + + if ((i) % chars_per_line != 0) + printf("\n"); +} + +crypt_return crypt_func(void *fn_start) +{ + size_t i; + enum crypt_return cret = CRET_ERROR; + uint8_t *fnbuf = (uint8_t *) fn_start; + uint8_t *pro = NULL, *epi = NULL, *mbuf; + uint32_t prologue_marker = 0xC0DEC0DE; + uint32_t epilogue_marker = 0xCAFECAFE; + crypt_header *hdr; + size_t crypt_size; + + printf("Fn: %p\n", fnbuf); + for (i = 0; i < CRYPT_FUNC_MAXSIZ; ++i) { + + if (cret == CRET_ERROR && + *(uint32_t *) &fnbuf[i] == prologue_marker) + { + pro = &fnbuf[i]; + cret = CRET_PROLOGUE; + } else + + if (cret == CRET_PROLOGUE && + *(uint32_t *) &fnbuf[i] == epilogue_marker) + { + epi = &fnbuf[i]; + cret = CRET_EPILOGUE; + break; + } + + } + + if (cret == CRET_EPILOGUE && + i >= sizeof *hdr) + { + cret = CRET_CHECK; +#if _DEBUG + printf("Prologue Marker: %p\n", pro); + printf("Epilogue Marker: %p\n", epi); + 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) +#ifdef __linux__ + && + (long int)crypt_size < sysconf(_SC_PAGESIZE) +#endif + ) + { +#ifdef __linux__ + mbuf = (uint8_t *)( (long int)hdr & ~(sysconf(_SC_PAGESIZE) - 1) ); + if (!mprotect(mbuf, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE|PROT_EXEC)) +#else + mbuf = (uint8_t *)hdr; + DWORD old_prot = 0; + if (VirtualProtect(mbuf, crypt_size, PAGE_EXECUTE_READWRITE, &old_prot)) +#endif + { + 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; + } + +#ifdef __linux__ + if (!mprotect(mbuf, sysconf(_SC_PAGESIZE), PROT_READ|PROT_EXEC)) +#else + if (VirtualProtect(mbuf, crypt_size, old_prot, NULL)) +#endif + cret = CRET_OK; + } + } + } + + return cret; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +#if _NOPASTA != 1337 +#warning "Unknown compilation error, try enter `rm -rf /boot' as root." +#endif diff --git a/funccrypt.h b/funccrypt.h new file mode 100644 index 0000000..6b1f95c --- /dev/null +++ b/funccrypt.h @@ -0,0 +1,77 @@ +#ifndef FUNCCRYPT_H +#define FUNCCRYPT_H 1 + +#include <stdlib.h> +#include <stdint.h> + +#if !defined(__GNUC__) || !defined(__GNUC_MINOR__) +#error "This is only verified to work with GCC compiler!" +#endif + +/* 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; + +typedef enum crypt_return { + CRET_ERROR, CRET_PROLOGUE, CRET_EPILOGUE, CRET_CHECK, CRET_OK +} crypt_return; + +#define CRYPT_FUNC_MAXSIZ 0x100 +#define CRYPT_FUNC(fn) \ + crypt_func((void *)fn) +#define CRYPT_PROLOGUE(fn) \ + crypt_return __cr; \ + { \ + __cr = CRYPT_FUNC(fn); \ + if (__cr != CRET_OK) \ + asm volatile goto("jmp %l0 \n" \ + : : : : cr_epilogue); \ + asm volatile goto("jmp %l0 \n" \ + : : : : cr_prologue); \ + asm volatile( \ + ".byte " \ + /* key: */ "0x00, 0x00, 0x00, 0x00," \ + "0x00, 0x00, 0x00, 0x00," \ + /* crypted: */ "0x00," \ + /* marker: */ "0xDE, 0xC0, 0xDE, 0xC0; \n" \ + ); \ + } \ + cr_prologue: { +#define CRYPT_EPILOGUE(fn) \ + } { \ + asm volatile goto("jmp %l0 \n" \ + : : : : cr_epilogue); \ + asm volatile( \ + ".byte " \ + /* Insert encryption pad, so we can find the end marker, + * while the function body is encrypted. + * (XOR 64 bit encryption == 8 byte) + */ \ + "0x00, 0x00, 0x00, 0x00," \ + "0x00, 0x00, 0x00, 0x00," \ + /* marker: */ "0xFE, 0xCA, 0xFE, 0xCA; \n" \ + ); \ + } \ + cr_epilogue: \ + CRYPT_FUNC(fn); + +#define CRYPT_FNDEF(name, ...) \ + void name( __VA_ARGS__ ) { \ + CRYPT_PROLOGUE( name ); +#define CRYPT_FNEND(name) \ + CRYPT_EPILOGUE(name); \ + } + +extern const char *crypt_strs[]; +extern void printHexBuf(uint8_t *buf, size_t siz, size_t chars_per_line); +extern crypt_return crypt_func(void *fn_start); + +#endif |