Skip to content

Annotating code

A practical cheat-sheet for marking functions. For why it works this way, see Concepts → Annotation model; for every key, the Annotation grammar.

The pattern

__attribute__((annotate("obf: <passes>")))     // C / C++
[[clang::annotate("obf: <passes>")]]           // C++ attribute form

A macro keeps it readable and greppable:

#define OBF(spec) __attribute__((annotate("obf: " spec)))

OBF("mba(prob=70), bcf(prob=30)")
int f(int x) { return x * 3 + 7; }

Copy-paste recipes

Expression-level only — cheap, fast.

OBF("mba(prob=40), substitution(loop=1), sdiff(prob=25), split(num=4)")
int light(int x) { return x * 3 + 7; }

Structural + post-hardening.

OBF("mba(prob=70), bcf(prob=30), flattening(minBlocks=3), shield, adec")
int heavy(int x, int y) { return x ^ y; }

Virtualise — replaces the whole body. Pre-obfuscate first for a harder lift.

OBF("mba(preset=high), bcf(prob=30), vm(preset=max)")
int secret(int key, int data) { return key ^ (data + 0xDEAD); }
OBF("strenc(minlen=4,cipher=chacha)")
void banner(void) { puts("confidential"); }

OBF("constenc(prob=100,minAbs=4)")
int gate(int serial) { return serial ^ 0xC0FFEE; }

Fold same-group= functions into one super-function.

OBF("fmerge(group=core,launderSel=1)") int  parse_hdr(const char *p, int n){ return n; }
OBF("fmerge(group=core,launderSel=1)") long crc_step(long acc, int b){ return acc; }

Rules that bite

  • Only annotated functions change. main and everything else is untouched unless marked.
  • Order in the annotation doesn't matter — the driver reorders topologically. "obf: vm, mba" runs mba then vm.
  • vm and flattening conflict — never both on one function.
  • Stacking annotations is safe — multiple annotate on one function merge (enablement additive, params last-wins).
  • Keys use no dashesmaxSites, not max-sites.

Confirm it parsed

opt -passes=obf-dump-config -S app.ll -o /dev/null -obf-verbose -obf-seed=1

If a pass you wrote isn't listed, the spec didn't parse — check parentheses and key names. Next: Quickstart runs the full compile loop.