OLLVM提供三种混淆机制:
- 控制流平坦化(control flow flattening)
- 虚假控制流程(instruction substitution)
- 指令替换(bogus control flow)
控制流平坦化
基本思想主要是通过一个主分发器来控制程序基本块的执行流程
经过控制流平坦化后
这样可以模糊基本块之间的前后关系,增加程序分析的难度
用IDA查看未经过控制流平坦化的控制流程图(CFG)
经过控制流平坦化后
通过分析可以发现原始的执行逻辑只在真实块以及序言和retn块中,其中会产生分支的真实块中主要是通过CMOV指令来控制跳转到哪一个分支,常见的分析工具有angr
参考资料:利用符号执行去除控制流平坦化 - 博客 - 腾讯安全应急响应中心 (tencent.com)
虚假控制流程
在代码块前添加一个判断代码块来改变CFG,永真或永假判断使进程直接跳转到原代码块,并将整个代码内容被随机生成的垃圾指令填满,增加逆向成本
指令替换
使用复杂的指令代替简单的二元运算(如加减法、或、异或)
加法
· a = b - (-c)
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = sub i32 0, %1
%3 = sub nsw i32 %0, %2
· a = -(-b + (-c))
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = sub i32 0, %0
%3 = sub i32 0, %1
%4 = add i32 %2, %3
%5 = sub nsw i32 0, %4
· r = rand (); a = b + r; a = a + c; a = a - r
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = add i32 %0, 1107414009
%3 = add i32 %2, %1
%4 = sub nsw i32 %3, 1107414009
· r = rand (); a = b - r; a = a + b; a = a + r
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = sub i32 %0, 1108523271
%3 = add i32 %2, %1
%4 = add nsw i32 %3, 1108523271
Subtraction
· a = b + (-c)
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = sub i32 0, %1
%3 = add nsw i32 %0, %2
· r = rand (); a = b + r; a = a - c; a = a - r
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = add i32 %0, 1571022666
%3 = sub i32 %2, %1
%4 = sub nsw i32 %3, 1571022666
· r = rand (); a = b - r; a = a - c; a = a + r
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = sub i32 %0, 1057193181
%3 = sub i32 %2, %1
%4 = add nsw i32 %3, 1057193181
逻辑与
· a = b & c => a = (b ^ ~c) & b
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = xor i32 %1, -1
%3 = xor i32 %0, %2
%4 = and i32 %3, %0
逻辑或
· a = b | c => a = (b & c) | (b ^ c)
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = and i32 %0, %1
%3 = xor i32 %0, %1
%4 = or i32 %2, %3
异或
· a = a ^ b => a = (~a & b) | (a & ~b)
%0 = load i32* %a, align 4
%1 = load i32* %b, align 4
%2 = xor i32 %0, -1
%3 = and i32 %1, %2
%4 = xor i32 %1, -1
%5 = and i32 %0, %4
%6 = or i32 %3, %5