自动x86指令混淆

Pol*_*ial 7 obfuscation x86 assembly automation

我正在研究一个x86 asm混淆器,它将英特尔语法代码作为字符串,并输出一组混淆的等效的操作码.

这是一个例子:

mov eax, 0x5523
or eax, [ebx]
push eax
call someAPI
Run Code Online (Sandbox Code Playgroud)

变成这样的东西:

mov eax, 0xFFFFFFFF ; mov eax, 0x5523
and eax, 0x5523     ;
push [ebx]          ; xor eax, [ebx]
or [esp], eax       ;
pop eax             ;
push 12345h         ; push eax
mov [esp], eax      ;
call getEIP         ; call someAPI
getEIP:             ;
add [esp], 9        ;
jmp someAPI         ;
Run Code Online (Sandbox Code Playgroud)

这只是一个例子,我没有检查过这不会搞砸标志(它可能会).

现在我有一个XML文档,列出了指令模板(例如push e*x)和可以使用的替换指令列表.

我正在寻找的是一种自动生成操作码序列的方法,该操作码产生与输入相同的结果.我不介意做一个受过良好教育的强盗,但我不确定我是怎么做到的.

Ira*_*ter 15

您需要的是代码描述操作的代数,以及一组允许您确定等效操作的代数定律.

然后对于每条指令,你查找它的代数描述(为了一个例子,一个

 XOR  eax,mem[ecx]
Run Code Online (Sandbox Code Playgroud)

其代数等价

 eax exclusive_or mem[ecx]
Run Code Online (Sandbox Code Playgroud)

使用那些代数等价物枚举代数等价,例如:

 a exclusive_or b ==> (a and not b) or (b and not a)
Run Code Online (Sandbox Code Playgroud)

为您的XOR指令生成等效的代数语句

 eax exclusive_or mem[ecx] ==> (eax and not mem[ecx]) or (mem[ecx] and not eax)
Run Code Online (Sandbox Code Playgroud)

你可以对此应用更多的代数定律,例如de morgans定理:

 a or b ==> not (not a and not b)
Run Code Online (Sandbox Code Playgroud)

要得到

(not (not (eax and not mem[ecx])) and (not (mem[ecx] and not eax)))
Run Code Online (Sandbox Code Playgroud)

此时,您有一个代数计算的规范,它将与原始数据做同样的事情.有你的蛮力.

现在,您必须通过匹配说明将与此说明相关的内容,将其"编译"为机器指令.像任何编译器一样,您可能希望优化生成的代码(两次获取mem [ecx]没有意义).(所有这些很难...它是一个代码生成器!)生成的代码序列将是这样的:

mov ebx, mem[ecx]
mov edx, ebx
not edx
and edx, eax
not eax
and eax, ebx
not eax
or eax, edx
Run Code Online (Sandbox Code Playgroud)

这是手动构建的很多机器.

另一种方法是利用程序转换系统,允许您将源到源转换应用于代码.然后,您可以将"等价"编码为直接重写代码.

其中一个工具是我们的DMS软件再造工具包.

DMS采用语言定义(基本上作为EBNF),自动实现解析器,AST构建器和prettyprinter(反解析器,将AST转换回有效的源文本).[DMS目前不具有ASM86的EBNF,而是几十EBNFs各种复杂的汉语语言的已建立DMS包括一些杂项非x86汇编所以你必须定义ASM86 EBNF到DMS.这非常简单; DMS有一个非常强大的解析器生成器].

使用它,DMS将允许您直接在代码上编写源代码转换.您可以编写以下转换,直接实现XOR等效和DeMorgan定律:

  domain ASM86;

  rule obfuscate_XOR(r: register, m: memory_access):instruction:instruction
  =  " XOR \r, \m " 
      rewrites to
     " MOV \free_register\(\),\m
       NOT \free_register\(\)
       AND \free_register\(\),\r 
       NOT \r
       AND \r,\m
       OR \r,\free_register\(\)";

 rule obfuscate_OR(r1: register, r2: register):instruction:instruction
 = " OR \r1, \r2"
     rewrites to
    " MOV \free_register\(\),\r1
      NOT \free_register\(\)
      AND \free_register\(\),\r2
      NOT \r2
      AND \r1,\r2
      NOT \r1";
Run Code Online (Sandbox Code Playgroud)

在一个称为"free_register"的元过程中有一些额外的魔法,它确定代码中那些(AST匹配)的寄存器是空闲的.(如果您不想这样做,请像在示例中一样使用堆栈顶部作为临时位置).

你需要一堆重写来覆盖你想要混淆的所有情况,其中包含寄存器和内存操作数的组合.

然后可以要求转换引擎在代码中的每个点处随机地应用这些转换一次或多次以对其进行加扰.

您可以看到应用DMS的一些代数变换完整工作示例.