您需要的是操作码功能的代数描述,以及一组允许您确定等效操作的代数定律。
然后,对于每条指令,您查找其代数描述(作为示例,
一个
XOR eax,mem[ecx]
其代数等价为
eax exclusive_or mem[ecx]
使用这些代数等价物枚举代数等价物,例如:
a exclusive_or b ==> (a and not b) or (b and not a)
为您的 XOR 指令生成等效的代数语句
eax exclusive_or mem[ecx] ==> (eax and not mem[ecx]) or (mem[ecx] and not eax)
您可以对此应用更多代数定律,例如德摩根定理:
a or b ==> not (not a and not b)
to get
(not (not (eax and not mem[ecx])) and (not (mem[ecx] and not eax)))
此时,您已经有了代数计算的规范,可以执行
和原来的一样。这就是你的蛮力。
现在你必须通过匹配哪些指令来将其“编译”为机器指令
就按这个说的做。与任何编译器一样,您可能希望优化
生成的代码(两次获取 mem[ecx] 没有意义)。 (所有这些都很难......它是一个代码生成器!)
生成的代码序列类似于:
mov ebx, mem[ecx]
mov edx, ebx
not edx
and edx, eax
not eax
and eax, ebx
not eax
or eax, edx
这是需要手动建造的大量机械。
另一种方法是利用程序转换系统,该系统允许您将源到源的转换应用于代码。然后,您可以将“等效项”编码为直接在代码上重写。
这些工具之一是我们的DMS 软件再造工具包.
DMS 采用语言定义(本质上是 EBNF),自动实现解析器、AST 构建器和 Prettyprinter(反解析器,将 AST 转回有效的源文本)。
[DMS 目前没有 ASM86 的 EBNF,但有数十个针对各种
已为 DMS 构建了复杂的语言,其中包括多种用于各种非 x86 汇编器的语言
因此,您必须将 ASM86 EBNF 定义为 DMS。这非常简单;数据管理系统
有一个非常强大的解析器生成器]。
使用它,DMS 将允许您直接在代码上编写源转换。您可以编写以下转换来直接实现 XOR 等价和德摩根定律:
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";
在名为“free_register”的元过程中添加一些额外的魔法来确定寄存器
在代码中的那个点(AST 匹配)是空闲的。 (如果您不想这样做,请使用堆栈顶部
就像您在示例中所做的那样,到处都是临时的)。
您需要进行大量重写来覆盖您想要混淆的所有情况,以及寄存器和内存操作数的组合。
然后,可以要求转换引擎在代码中的每个点随机应用这些转换一次或多次以对其进行扰乱。
你可以看到一个DMS 应用一些代数变换的完整示例。