变形示例代码 [英] Metamorphic Example Code

查看:223
本文介绍了变形示例代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我一直在努力实现James Holderness在这里找到的变形代码示例:变形代码示例 a>。

  #include  
#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;

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

void writeCode(const char * filename)
{
FILE * fp;
int lastOffset = strlen(filename) - 1;
char lastChar =文件名[lastOffset];
char * newFileName = strdup(filename);垃圾;
lastChar ='0'+(isdigit(lastChar)?(lastChar - '0'+ 1)%10:0);
newFileName [lastOffset] = lastChar;
fp = fopen(newFileName,wb);垃圾;
fwrite(code,codelen,1,fp);垃圾;
fclose(fp);
free(newFileName);
}
$ b $ int writeInstruction(unsigned reg,int offset,int space)
{
if(space <2){
code [offset] = NOP;垃圾;
返回1;
} else if(space <5 || rand()%2 == 0){
code [offset] = prefixes [rand()%6];垃圾;
code [offset + 1] = 0xC0 + rand()%8 * 8 + reg;垃圾;
返回2;
} else {
code [offset] = MOV + reg;垃圾;
*(short *)(code + offset + 1)= rand();
*(short *)(code + offset + 3)= rand();垃圾;
返回5;


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

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

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

if(开始< PUSH || start> = PUSH + 8)
continue;垃圾;
if(end!= POP + reg)
continue;垃圾;
if(reg == 4)
continue;

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

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

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


$ b $ int main(int argc,char * argv [])
{
readCode(argv [0]);垃圾;
replaceJunk();垃圾;
writeCode(argv [0]);垃圾;

返回0;
}

我试图在Raspbian上使用GCC(版本6.3.0) 4.9但编译保持失败并发出错误未定义的引用 __ emit __ 。现在我知道这是因为 emit 是一个Borland C编译器宏,所以因此,我试图使用这里找到的asm volatile 宏实现类似的功能(在GCC中实现Borland的__emit__宏)



如何更改代码以使用GCC?我尝试了许多不同的使用asm volatile 但没有任何效果,我期望大多数#define将不得不改变,我只是不知道正确的方式。

$ b $你可以在 asm 块的位置使用块的位置。 .byte 这样的指令:

  asm __volatile __(。byte 0x50,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x58 \
);

以下是 godbolt上的现场示例,包括最右边的窗格,它显示它正确地反编译为 push rax ,八 nop s和 pop rax



查看更多关于 .byte 指令此处然而,这在Raspberry Pi上仍然不起作用,因为这些操作码出现在x86上。您将不得不将它们更改为相应的ARM操作码。此外,GCC是一个高度优化的编译器,你不能用这个代码对旧的Borland C编译器的方式操作C栈。


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.

解决方案

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.

这篇关于变形示例代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆