PolymorphicEngine
Barry Initial commit 646db1c (3 years, 5 months ago)diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..5ffb3bb --- /dev/null +++ b/src/main.c @@ -0,0 +1,155 @@ +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> + +/* Config */ +#define NAME_PREFIX "poly_" /* Copies' names start with */ +#define NAME_PREFIX_LENGTH 5 /* Length of prefix */ +#define NAME_AFFIX_LENGTH 11 /* Number of random chars after prefix */ +#define KEY_SIZE 8 /* Size of encryption key */ + +#define ENCRYPTED __attribute__((noinline, section(".encrypted"))) + +/* Linked values */ +extern unsigned char binaryStart[]; +extern unsigned char encryptedStart[]; +extern unsigned char encryptedEnd[]; + +/* Keys */ +const uint8_t act[KEY_SIZE] = {}, /* Operators */ + key[KEY_SIZE] = {}; /* Operands */ + +/* Functions */ +int encrypted_main(int argc, char **argv); + +/* Traditional main function */ +int +main(int argc, char **argv) +{ + size_t i, mask; + void *aligned; + uint8_t *code = (uint8_t *) encryptedStart; + long pageSize = sysconf(_SC_PAGESIZE); + + /* Make memory writable */ + if (pageSize <= 0) + return 1; + mask = pageSize - 1; + aligned = (void *) ((size_t) code & ~mask); + if (mprotect(aligned, (encryptedEnd - encryptedStart) + pageSize, PROT_READ|PROT_WRITE|PROT_EXEC)) + return 1; + + /* Decrypt our code */ + for (i = 0; i < (encryptedEnd - encryptedStart); i++) { + switch (act[i % KEY_SIZE]) { + case 0: + code[i] ^= key[i % KEY_SIZE]; + break; + case 1: + code[i] -= key[i % KEY_SIZE]; + break; + case 2: + code[i] += key[i % KEY_SIZE]; + break; + } + } + + /* Run the decrypted code */ + return encrypted_main(argc, argv); +} + +/* Copy a file */ +ENCRYPTED +void +copy_file(char *src, char *dst) +{ + FILE *self, *child; + char data[1024]; + size_t n, m; + + /* Open files */ + self = fopen(src, "rb"); + child = fopen(dst, "wb"); + if (self == NULL || child == NULL) + exit(EXIT_FAILURE); + + /* Copy contents across */ + do { + n = fread(data, 1, sizeof(data), self); + if (n) + m = fwrite(data, 1, n, child); + else + m = 0; + } while ((n > 0) && (n == m)); + if (m) + exit(EXIT_FAILURE); + + /* Close files */ + fclose(self); + fclose(child); +} + +/* Encrypted main */ +ENCRYPTED +int +encrypted_main(int argc, char **argv) +{ + char filename[NAME_PREFIX_LENGTH + NAME_AFFIX_LENGTH + 1] = NAME_PREFIX, + /* Possible characters in file name */ + alpha[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + uint8_t dKey[KEY_SIZE], dAct[KEY_SIZE], data, *code = (uint8_t *) encryptedStart; + FILE *child; + size_t i; + + /* Seed the random function */ + srand(time(NULL)); + + /* Duplicate file */ + for (i = NAME_PREFIX_LENGTH; i < sizeof(filename)-1; i++) + filename[i] = alpha[rand() % sizeof(alpha)]; + copy_file(argv[0], filename); + chmod(filename, 0777); + + /* Open child file */ + child = fopen(filename, "r+"); + if (child == NULL) + exit(EXIT_FAILURE); + + /* Generate a new key */ + for (i = 0; i < KEY_SIZE; i++) { + dAct[i] = rand() % 3; + dKey[i] = rand() % 256; + } + /* Write keys */ + fseek(child, (unsigned long int) (act - binaryStart), SEEK_SET); + fwrite(dAct, 1, KEY_SIZE, child); + fseek(child, (unsigned long int) (key - binaryStart), SEEK_SET); + fwrite(dKey, 1, KEY_SIZE, child); + + /* Encrypt our code */ + fseek(child, (unsigned long int) (encryptedStart - binaryStart), SEEK_SET); + for (i = 0; i < (encryptedEnd - encryptedStart); i++) { + data = code[i]; + switch (dAct[i % KEY_SIZE]) { + case 0: + data ^= dKey[i % KEY_SIZE]; + break; + case 1: + data += dKey[i % KEY_SIZE]; + break; + case 2: + data -= dKey[i % KEY_SIZE]; + break; + } + fwrite(&data, 1, 1, child); + } + + /* Close file and exit */ + fclose(child); + + return 0; +}