aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsegfault <segfault@secmail.pro>2019-04-13 21:14:59 +0200
committersegfault <segfault@secmail.pro>2019-05-01 01:41:39 +0200
commit21144d5cb548f8fad5583e77fcce51e2e0a707e9 (patch)
tree9b2b8b5d55b3fb891999fde24882508643c83e81
initial commit
Signed-off-by: segfault <segfault@secmail.pro>
-rw-r--r--Makefile52
-rw-r--r--example.c69
-rw-r--r--funccrypt.c143
-rw-r--r--funccrypt.h77
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