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.
JUNK
sequences inserted verbatim by theasm
macro. As long as the compiler emits those sequences faithfully, it should find them. It then rewrites those sequences in such a way that it is still effectively a no-op, but with new instructions. I don't see any big issues to making this work. There is a small chance of false positives: falsely finding theJUNK
signature. – Mechanism__emit__
with anasm
block. – Mechanism-O0
.) – Suziesuzukipush
andpop
by definition don't "use" the red-zone since they adjustrsp
. The red-zone is the 128-byte area belowrsp
that it is safe to use without adjusting the stack pointer, butpush
andpop
do adjust it, so they are always safe in this respect. – Mechanismpush %%rbp
/pop %%rbp
clobbers something gcc spilled to-8(%rsp)
. – Suziesuzukiasm
! I would have hoped that gcc wouldn't keep spilled stuff in the redzone across anasm
call, but I guess that would hurt performance for the small number of inline blocks that want to do that. Perhaps they could add a clobber for it. It's a limitation of treating the asm totally opaquely - if they could only look into the block and see thepush
... (yes, I know that theasm
blocks don't work that way, the text is basically emitted directly into the .S output). – MechanismJUNK
tosub rsp, 128; push rax; ... pop rax; add rsp 128
so you are sure you are avoiding any clobber of the redzone. – Mechanismcall
from inline asm (which is highly questionable anyway; gcc or clang will sometimes optimize astatic
function definition to assume things that are true for the only visible call sites, e.g. not returning unused struct members. Although I think by passing a function-pointer as an asm operand you guarantee a proper func def.) – Suziesuzuki