명령어 대체 기법 (Instructions substitution)
해당 난독화 기법의 목표는 덧셈, 뺄셈, 또는 부울 대수 연산과 같은 표준 이진 연산에 대해 기능적으로 동일하지만 더 복잡한 명령어 시퀀스로 대체하는 것이다. 여러 동등한 명령어 시퀀스를 선택할 수 있을 때, 임의로 하나의 명령어 시퀀스를 선택한다. 이러한 종류의 난독화는 비교적 직관적이고, 생성된 코드를 쉽게 역난독화가 가능하기 때문에 많은 보안을 추가하지 않는다. 하지만, 의사 난수 발생기(pseudo-random generator)가 다른 값으로 시드된다면 명령어 대체 기법은 생성된 이진수에서 다양성을 가져온다. 현재 LLVM 4.0을 기반으로 한 OLLVM에서는 부동 소수점 값에 대해서 반올림 오류와 불필요한 숫자 부정확성을 가져올 수 있어 정수 연산자에 대해서만 적용이 가능하다.
다음과 같은 컴파일러 옵션으로 난독화가 가능하다.
-mllvm -sub : 명령어 대체 기법 활성화
-mllvm -sub_loop=3 : 해당 패스가 활성화 되었을 때, 하나의 함수에 3회 적용한다.
각 명령어에 대해 다음과 같은 대체 기법이 적용 가능하다.
1. 덧셈 연산 (Addition)
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
2. 뺄셈 연산 (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
3. AND 연산
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
4. OR 연산
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
5. XOR 연산
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