Skip to content

Bogus control flow — bcf

Inserts opaque predicates (conditions that always evaluate one way, but are hard to prove so statically) and injects fake edges into the CFG, confusing decompilers and CFG analysis tools.

Options

Key Default Range Meaning
prob 30 0–100 Site probability (%).
loop 1 1–10 Number of application rounds.
maxBlocks / max 5000 0–100000 Hard maximum block count (safety valve).

Example

__attribute__((annotate("obf: bcf(prob=40,loop=1,maxBlocks=4000)")))
int f(int x) { return x * 3 + 7; }

On the shared 18-block sample, bcf expands the CFG from 18 to 86 blocks with 135 opaque predicates — the graph an analyst sees no longer matches the real control flow.

Opaque-predicate strength vs symbolic execution

Simple opaque predicates can be defeated by a symbolic-execution / DSE attack that proves the dead edge unreachable. Combine bcf with sdiff / shield and, for high-value code, virtualisation (vm). See Resilience benchmarks.

Watch IR growth

bcf multiplies blocks quickly, especially with loop>1 or after split. Use the IR budget knobs and maxBlocks to keep size in check.