Skip to content
Obfuscationadvanced

Control-Flow Flattening

Replacing a function's natural branching with a single dispatcher loop driven by a state variable, destroying the original control-flow graph that decompilers rely on.

Control-flow flattening rewrites a function into a while (state) switch (state) dispatcher. Every original basic block becomes a case that computes the next state value, so the decompiler sees one giant loop instead of the real CFG.

Shape

c
int state = 0x1A2B;
while (state != DONE) {
  switch (state) {
    case 0x1A2B: /* block A */ state = cond ? 0x77F0 : 0x0C31; break;
    case 0x77F0: /* block B */ state = 0x4ED2; break;
    /* ... */
  }
}

Recovering the original flow

  • Symbolic execution of the dispatcher recovers the state-transition graph (e.g. D-810, HexRaysDeob, or custom miasm/Triton scripts).
  • Identify the state variable feeding the switch, enumerate reachable case values, then stitch blocks back into a real CFG.
  • Frequently paired with opaque predicates to make the transitions harder to constant-fold.
Votes

Comments(0)