Skip to content

Control Flow Flattening

Pascal Junod edited this page Nov 24, 2013 · 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 code flattening
  • -mllvm -funcFLA="func1,func2,func3": if code flattening is activated, apply it only on functions func1, func2 and func3
  • -mllvm -perFLA=20: if code flattening is activated, apply it with a probability of 20% on each function

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 :

main_c

After the flattening, we get the following instruction flow:

main_c_fla

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

Clone this wiki locally