$npx -y skills add meltedinhex/analyst-ai-pack --skill defeating-control-flow-flatteningDefeats control-flow-flattening obfuscation by identifying the dispatcher/state-
| 1 | # Defeating Control-Flow Flattening |
| 2 | |
| 3 | ## When to Use |
| 4 | |
| 5 | - A function is flattened (a dispatcher loop switching on a state variable, with original blocks as |
| 6 | switch cases) and you need to recover the original control flow. |
| 7 | - You are reversing OLLVM-style or similar flattening. |
| 8 | |
| 9 | **Do not use** this on non-flattened code — confirm the dispatcher/state-variable pattern first. |
| 10 | This skill analyzes disassembly/CFG data statically and executes nothing. |
| 11 | |
| 12 | ## Prerequisites |
| 13 | |
| 14 | - A disassembled function's basic-block/edge data (e.g., exported from Ghidra/IDA/Binary Ninja as |
| 15 | JSON). |
| 16 | |
| 17 | ## Workflow |
| 18 | |
| 19 | ### Step 1: Detect the flattening structure |
| 20 | |
| 21 | ```bash |
| 22 | python scripts/analyst.py detect cfg.json |
| 23 | ``` |
| 24 | |
| 25 | Identifies a dispatcher block (high in-degree, switch/compare on a state variable) and the relay/ |
| 26 | case blocks that all branch back to it. |
| 27 | |
| 28 | ### Step 2: Recover state transitions |
| 29 | |
| 30 | Track the constant assigned to the state variable in each case to determine the successor block, |
| 31 | rebuilding the true edges. |
| 32 | |
| 33 | ### Step 3: Reconstruct the original CFG |
| 34 | |
| 35 | Emit the deflattened successor mapping (case → next case) for re-annotation in the disassembler. |
| 36 | |
| 37 | ### Step 4: Verify |
| 38 | |
| 39 | Confirm the recovered flow has a single entry, sane successors, and no orphan blocks. |
| 40 | |
| 41 | ## Validation |
| 42 | |
| 43 | - The dispatcher is identified by in-degree and state-variable comparison. |
| 44 | - Each case's next-state constant maps to a real successor block. |
| 45 | - The reconstructed CFG covers all original (non-relay) blocks. |
| 46 | |
| 47 | ## Pitfalls |
| 48 | |
| 49 | - State variable computed (not a constant) — requires emulation/symbolic execution. |
| 50 | - Multiple dispatchers or nested flattening. |
| 51 | - Opaque predicates and bogus blocks inflating the case set. |
| 52 | |
| 53 | ## References |
| 54 | |
| 55 | - See [`references/api-reference.md`](references/api-reference.md) for the deflattener. |
| 56 | - OLLVM and ATT&CK T1027 references (linked in frontmatter). |