对于我的项目,我正在对部分代码执行一种校验和操作以保护它,因此不希望其模板容易可见,因此需要混淆。
我在网上搜索了很多,并阅读了描述混淆定义、类型等的论文。但似乎没有关于混淆 x86 汇编代码的教程。有人可以建议一个简单的算法/工具吗?
我已经阅读了关于插入虚拟代码、更改指令的顺序和其他技术的内容,但它们似乎是完全随机的,即插入多少虚拟代码是无止境的,等等。
有人至少可以指导我采取正确的方法吗?
对于我的项目,我正在对部分代码执行一种校验和操作以保护它,因此不希望其模板容易可见,因此需要混淆。
我在网上搜索了很多,并阅读了描述混淆定义、类型等的论文。但似乎没有关于混淆 x86 汇编代码的教程。有人可以建议一个简单的算法/工具吗?
我已经阅读了关于插入虚拟代码、更改指令的顺序和其他技术的内容,但它们似乎是完全随机的,即插入多少虚拟代码是无止境的,等等。
有人至少可以指导我采取正确的方法吗?
您不应该混淆“代码保护”和“代码混淆”。“代码保护”技术的目标是识别代码修改(您提到了校验和),并在识别出篡改代码时采取适当的方法,例如崩溃或提供错误的结果。反调试措施也属于这一类。
二进制中的“代码混淆”旨在用笨拙且通常无用的代码(从简单的 jmp 链到更复杂的结构)使调查者(和反汇编者)蒙蔽。大多数代码混淆技术会导致一些代码膨胀,必须考虑混淆和性能之间的权衡。这里有两个“在野外”发现的混淆示例。
mov si, si
mov esp, ebp
jnz loc_abcd
xchg edi, esi
mov cl, cl
xchg esi, edi
mov di, di
jz loc_dcba ; followed by a jmp to loc_abcd
cpuid
ret
在这个例子中,唯一的“真实”语句是 mov esp, ebp。
lea rsp, [rsp+8]
jmp qword ptr[rsp-8]
可以找到更多、更复杂的例子。如果你想深入研究这个问题,你需要练习,就像所有的 SW 倒车一样。获取受保护和/或混淆的二进制文件,如游戏或加密狗保护器和火车。在文献中(例如 Chris Eagle 出色的 IdaPro 书),您也可能会发现一些混淆结构。
玩得开心!
正如评论中提到的,查看第 5 章以PDF
Practical Reverse Engineering
获得一些想法。
垃圾代码插入:
jmp label
<junk>
label:
<real code>
基于操作系统的控制间接:
push addr_seh_handler
push fs:[0]
mov fs:[0], esp
xor eax, eax
mov [eax], 1234h
<junk code>
addr_seh_handler:
<continue execution here>
pop fs:[0]
add esp, 4
基于处理器的控制间接:
call target_addr
<junk code>
target_addr:
add esp, 4
通过身份的算术替换:
-x = ~x + 1 (by definition of two's complement)
rotate left(x,y) = (x << y) | (x >> (bits(x)-y))
rotate right(x,y) = (x >> y) | (x << (bits(x)-y))
x-1 = ~-x
x+1 = - x
基于模式的混淆:
push reg32
变成
push imm32
mov dword ptr [esp], reg32
更多基于模式的例子在这里。
如果您不想手动混淆代码,这是“成熟”的方法:
在哪里:
操作 IR 代码比操作本机代码容易得多。然而,学习 llvm 的工作原理以及如何使用其类进行更改并非易事。