PolymorphicEngine
Barry Initial commit 646db1c (4 years, 2 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;
+}