PolymorphicEngine
Barry Changing default config 8a21c42 (4 years, 2 months ago)
#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 6 /* 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 function */
ENCRYPTED
int
encrypted_main(int argc, char **argv)
{
char filename[NAME_PREFIX_LENGTH + NAME_AFFIX_LENGTH + 1] = NAME_PREFIX,
/* Possible characters in filename */
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)-1)];
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;
}