Skip to content

Control Flow Flattening

R1kk3r edited this page Jun 29, 2017 · 7 revisions

Description

The purpose of this pass is to completely flatten the control flow graph of a program.

For a detailed explanation of the control flow flattening technique, see for instance the paper of T László and Á Kiss, Obfuscating C++ programs via control flow flattening, Annales Univ. Sci. Budapest., Sect. Comp. 30 (2009) 3-19.

Note however that our algorithm fully flattens the control flow, which is not the case of the one of László and Kiss.

Available Compiler Options

  • -mllvm -fla: activates control flow flattening
  • -mllvm -split: activates basic block splitting. Improve the flattening when applied together.
  • -mllvm -split_num=3: if the pass is activated, applies it 3 times on each basic block. Default: 1

Implemented Technique

Here is an example. Consider this very simple C program :

#include <stdlib.h>
int main(int argc, char** argv) {
  int a = atoi(argv[1]);
  if(a == 0)
    return 1;
  else
    return 10;
  return 0;
}

The flattening pass will transform this code into this one :

#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;
}

As one can see, all basic blocks are split and put into an infinite loop and the program flow is controlled by a switch and the variable b.

Here, it's what it looks like for the control flow generated before the flattening :

Without fla

After the flattening, we get the following instruction flow:

With fla

As one can see, the main difference between the example in pure C, the IR version is completely flattened.

Clone this wiki locally