变形示例代码

时间:2017-10-18 04:35:54

标签: c gcc assembly macros inline

所以我一直在努力实现James Holderness的变形代码示例:Metamorphic Code Examples

public void Test()
{
    AppLog.Logger = Substitute.For<ILogger>(); // NSubstitute

    var logMock = new Mock<ILogger>();         // Moq
    AppLog.Logger = logMock.Object;            // Moq 

    SomeMethodToTest();

    AppLog.Logger.Recieved(1).LogSomething(...); // NSubstitute

    logMock.Verify(x => x.LogSomething(...));    // Moq
}

我正在尝试使用Raspbian 4.9上的GCC(版本6.3.0)进行编译,但编译仍然失败并发出错误“未定义引用#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; } 。现在我知道这是因为 emit 是一个Borland C编译器宏,因此我尝试使用此处找到的asm volatile 宏来实现类似的功能(Implementing Borland's __emit__ macro in GCC)。

如何更改代码以使用GCC?我已尝试过asm volatile 的多种不同用途,但似乎没有任何效果。我希望大多数#defines都必须改变,我只是不知道正确的方法。

1 个答案:

答案 0 :(得分:3)

您可以使用asm指令将任意字节放在.byte块的位置,如下所示:

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

此处&#39; sa live example on godbolt,包括最右边的窗格,显示它已正确反编译为push rax,8 noppop rax

详细了解.byte指令here

然而,这仍然不适用于Raspberry Pi,因为操作码似乎适用于x86。您必须将它们更改为相应的ARM操作码。此外,GCC是一个高度优化的编译器,你不能像使用旧的Borland C编译器那样操作C堆栈。