Documentation

Go to Portal Website

Control Flow Obfuscation

PlanPlatformsMASVS
TeamAndroidMASVS-RESILIENCE-3

Overview

Control Flow Obfuscation protects Android application bytecode from static analysis and reverse engineering by inserting opaque predicates and dead code branches into method bodies. Opaque predicates are conditional statements whose outcome is known at compile time but appears dynamic to static analysis tools—they create unreachable code paths that confuse decompilers and disassemblers while having zero runtime impact on actual program execution.

This technique is conceptually based on the control flow flattening and bogus control flow transformations popularized by Obfuscator-LLVM (O-LLVM), adapted for Dalvik/ART bytecode at the Smali level.

How It Works

The control operates on decompiled Smali bytecode (produced by apktool) during the build pipeline. For each non-framework method in the application:

  1. Register Allocation: Allocates one additional scratch register by incrementing the .locals count, ensuring the injected code does not clobber live values
  2. Injection Point Selection: Randomly selects return instructions (50% probability per method) as insertion points—predicates are injected before the return to guarantee they remain in reachable control flow
  3. Opaque Predicate Construction: Inserts always-false conditional branches:
   const/4 v<scratch>, 0x0      # Set scratch register to 0
   if-nez v<scratch>, :opq_d_<id>  # Branch if non-zero (never taken)
   goto :opq_s_<id>             # Skip dead code

   :opq_d_<id>                  # Dead code path
   nop
   nop
   goto :opq_s_<id>

   :opq_s_<id>                  # Continue normal execution
   return-void                   # Original return instruction
  1. Label Uniqueness: Generates unique labels using a random session ID combined with a per-file counter to prevent collisions across methods
  2. Decompiler Confusion: The injected branches appear as legitimate control flow to disassemblers and decompilers, introducing false edges in control flow graphs that obscure program logic

Scope and Limits

Threats Mitigated

This control provides defense-in-depth alongside other obfuscation controls (InstructionSubstitution, ArithmeticEncoding, DeadCodeInjection, EncryptStrings) to raise the cost of reverse engineering.

Caveats

Support Matrix

PlatformMinimum VersionStatusNotes
AndroidAll API Levels✅ SupportedOperates on Smali bytecode
iOSN/A❌ Not SupportediOS uses different obfuscation strategies

How to Enable the Control

Navigate to Code Obfuscation from the AppTego portal, and expand the Control Flow Obfuscation section. Under this section you will find the Control Flow Obfuscation control. Click Enable to apply it to the next protected build.

API Configuration Example

{
  "ControlFlowObfuscation": {
    "protection": true
  }
}

This control has no runtime detection or MessagePrompt configuration—it is a build-time transformation only.

Usage Notes

When to Enable

Enable ControlFlowObfuscation for applications that:

When to Disable

Consider disabling if:

Compatibility

Together, these controls form a comprehensive anti-reverse-engineering defense for Android applications.