Search code examples
cgccassemblymacrosinline

Metamorphic Example Code


So I've been working on implementing the metamorphic code example from James Holderness found here: Metamorphic Code Examples.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#define PUSH 0x50
#define POP 0x58
#define MOV 0xB8
#define NOP 0x90

#define ADD 0x01
#define AND 0x21
#define XOR 0x31
#define OR  0x09
#define SBB 0x19
#define SUB 0x29

#define JUNK asm __volatile__(PUSH,NOP,NOP,NOP,NOP,NOP,NOP,NOP,NOP,POP)
#define JUNKLEN 8

const unsigned char prefixes[] = {ADD, AND, XOR, OR, SBB, SUB, 0};
unsigned char *code;
int codelen;

void readCode(const char *filename)
{
    FILE *fp = fopen(filename, "rb");       JUNK;
    fseek(fp, 0L, SEEK_END);            JUNK;
    codelen = ftell(fp);
    code = malloc(codelen);             JUNK;
    fseek(fp, 0L, SEEK_SET);
    fread(code, codelen, 1, fp);            JUNK;
}

void writeCode(const char *filename)
{
    FILE *fp;
    int lastOffset = strlen(filename) - 1;
    char lastChar = filename[lastOffset];
    char *newFileName = strdup(filename);       JUNK;
    lastChar = '0' + (isdigit(lastChar)?(lastChar - '0' + 1) %10:0);
    newFileName[lastOffset] = lastChar;
    fp = fopen(newFileName, "wb");          JUNK;
    fwrite(code, codelen, 1, fp);           JUNK;
    fclose(fp);
    free(newFileName);
}

int writeInstruction(unsigned reg, int offset, int space)
{
    if (space < 2) {
        code[offset] = NOP;         JUNK;
        return 1;
    } else if (space < 5 || rand() % 2 == 0) {
        code[offset] = prefixes[rand() % 6];    JUNK;
        code[offset + 1] = 0xC0 + rand() % 8 * 8 + reg; JUNK;
        return 2;
    } else {
        code[offset] = MOV + reg;       JUNK;
        *(short *)(code + offset + 1) = rand();
        *(short *)(code + offset + 3) = rand(); JUNK;
        return 5;
    }
}

int readInstruction(unsigned reg, int offset)
{
    unsigned c1 = code[offset];
    if (c1 == NOP)
        return 1;               JUNK;
    if (c1 == MOV + reg)
        return 5;               JUNK;
    if (strchr(prefixes, c1)) {
        unsigned c2 = code[offset + 1];     JUNK;
        if (c2 >= 0xC0 && c2 <= 0xFF && (c2 & 7) == reg)
            return 2;           JUNK;
    }                       JUNK;
    return 0;
}

void replaceJunk(void)
{
    int i, j, inc, space;
    srand(time(NULL));              JUNK;

    for (i = 0; i < codelen - JUNKLEN - 2; i++) {
        unsigned start = code[i];
        unsigned end = code[i + JUNKLEN + 1];
        unsigned reg = start - PUSH;

        if (start < PUSH || start >= PUSH + 8)
            continue;           JUNK;
        if (end != POP + reg)
            continue;           JUNK;
        if (reg == 4)
            continue;

        j = 0;                  JUNK;
        while (inc = readInstruction(reg, i + 1 + j))
            j = j + inc;
        if (j != JUNKLEN)
            continue;           JUNK;

        reg = rand() % 7;           JUNK;
        reg += (reg >= 4);
        code[i] = PUSH + reg;           JUNK;
        code[i + JUNKLEN + 1] = POP + reg;  JUNK;

        space = JUNKLEN;
        j = 0;
        while (space) {
            inc = writeInstruction(reg, i + 1 + j, space);  JUNK;
            j = j + inc;
            space = space - inc;        JUNK;
        }
        printf("%d\n", i);          JUNK;
    }
}

int main(int argc, char *argv[])
{
    readCode(argv[0]);              JUNK;
    replaceJunk();                  JUNK;
    writeCode(argv[0]);             JUNK;

    return 0;
}

I'm attempting to compile using GCC (version 6.3.0) on Raspbian 4.9 but the compile keeps failing and issuing errors "undefined reference to __emit__. Now I know this is because emit is a Borland C Compiler macro and so I've consequently attempted to implement similar functionality using the asm volatile macro found here (Implementing Borland's __emit__ macro in GCC).

How can I change the code to work with GCC? I've tried a number of different uses of asm volatile but nothing seems to work. I expect that most of the #defines will have to change, I just don't know the correct way to do it.


Solution

  • You can put arbitrary bytes at the location of an asm block using the .byte directive like this:

    asm __volatile__(".byte 0x50, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x58\n");
    

    Here's a live example on godbolt, including the far right pane which shows that it decompiled fine into a push rax, eight nops, and pop rax.

    See more about the .byte directive here.

    However, this will still not work on the Raspberry Pi because the opcodes appear to for x86. You will have to change them to the corresponding ARM opcodes. Furthermore, the GCC is a highly optimizing compiler, and you cannot manipulate the C stack in the way this code did with the old Borland C compiler.