OLLVM使用

ollvm是一个基于llvm的开源项目,利用llvm会生成IR中间代码并通过pass进行优化的特点,通过增加Pass来对代码进行优化.但这种优化是为了让代码更加复杂,达到混淆的目的.主要有以下3种混淆手段:

  1. 指令替换(Substitution)
  2. 虚假控制流(Bogus Control Flow)
  3. 控制流平坦化(Control Flow Flattening)

下面按照官方给的例子,来进行ollvm特性的学习.

https://github.com/obfuscator-llvm/obfuscator/wiki/Features

指令替换(sub)

原理:将一条运算指令,替换为多条等价运算指令.

测试代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
//luoTst.c
#include <stdio.h>
int main(int argc, char** argv) {
  int n = argc + 2;
  if(n >= 0){
    printf("hello ollvm\r\n");
  }
  else{
    printf("hello World\r\n");
  }
  return 0;
}

使用下述命令进行编译,会等价替换1次

1
clang -mllvm -sub luoTst.c -o luoTst_sub

等价替换1

使用下述命令进行编译,会等价替换3次

1
clang -mllvm -sub -mllvm -sub_loop=3 luoTst.c -o luoTst_sub3

等价替换2

虚假控制流(bcf)

原理:克隆一个真实块,并随机替换其中的一些指令,然后用一个永远为真的条件建立一个分支,克隆后的块是不会被执行的.

测试代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//luoTst.c
#include <stdlib.h>
int main(int argc, char** argv) {
  int a = atoi(argv[1]);
  if(a == 0)
    return 1;
  else
    return 10;
  return 0;
}

上述代码转成中间语言表示如下:

虚假控制流2

经过虚假控制流Pass处理后,流程可能如下:

虚假控制流3

这里我们使用如下命令使用进行编译,在IDA中看下代码.

1
clang -mllvm -bcf luoTst.c -o luoTst_bcf

虚假控制流1

控制流平坦化(fla)

原理:先实现一个永真循环,然后在这个循环中放入switch语句,将代码中除了开始块的所有BasicBlock放入这个switch语句的不同case中,通过修改switch的条件,来实现BasicBlock之间的跳转.

测试代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//luoTst.c
#include <stdlib.h>
int main(int argc, char** argv) {
  int a = atoi(argv[1]);
  if(a == 0)
    return 1;
  else
    return 10;
  return 0;
}

上述代码经过控制流平坦化Pass处理后,代码会转成如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdlib.h>
int main(int argc, char** argv) {
  int a = atoi(argv[1]);
  int b = 0;
  while(1) {
    switch(b) {
      case 0:
        if(a == 0)
          b = 1;
        else
          b = 2;
        break;
      case 1:
        return 1;
      case 2:
        return 10;
      default:
        break;
    }
  }
  return 0;
}

未经过处理前的流程如下:

控制流平坦化1

经过处理后的流程如下:

控制流平坦化2

接下来我们使用如下命令进行编译,在IDA中体会下:

1
clang -mllvm -fla luoTst.c -o luoTst_fla

控制流平坦化3

控制流平坦化4

上面的编译选项比较简单,生成的代码,从IDA反汇编结果来看好像还可以,下面使用如下命令进行编译,来体会下控制流平坦化的强大.

1
clang -mllvm -fla -mllvm -split -mllvm -split_num=10 luoTst.c -o luoTst_fla_split10

控制流平坦化5

函数注解

可以使用注解的方式对指定函数进行指定的混淆方式.

测试代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//luoTst.c 
#include <stdlib.h>
#include <stdio.h>
int fun1(int a, int b) __attribute((__annotate__(("fla"))));
int fun2(int a, int b) __attribute((__annotate__(("nofla"))));
int main(int argc, char** argv) __attribute((__annotate__(("bcf"))));

int fun1(int a, int b){
  if(a + b > 10){
    return 10;
  }else{
    return 100;
  }
}

int fun2(int a, int b){
   if(a - b > 10){
    return 5;
  }else{
    return 50;
  }
}

int main(int argc, char** argv) {
  if(argc > 2){
    printf("hello world\n");
  }else{
    printf("hello ollvm\n");
  }
  printf("fun1:%d\n", fun1(argc, 6));
  printf("fun2:%d\n", fun2(argc, 8));
  return 0;
}

使用如下命令进行编译即可:

1
clang luoTst.c -o luoTst

参考链接

obfuscator


相关内容

0%