Control Flow Obfuscation
Protection ID: control_flow
Control Flow Obfuscation restructures the logic of your methods so that decompilers cannot reconstruct the original program flow. The code executes identically but its structure is transformed to resist static analysis.
Configuration
{
"protections": {
"control_flow": "medium"
}
}{
"protections": {
"control_flow": "medium"
}
}Available levels: "light", "medium", "aggressive".
How It Works
Decompilers reconstruct program logic by analyzing the branching structure of the compiled code. They trace conditional jumps, loops, and function calls to produce readable pseudo-code that closely resembles the original source.
Control Flow Obfuscation breaks this analysis by transforming the structure of methods. Sequential logic is reorganized so that the relationship between code blocks is no longer apparent from the binary. Decompilers produce output that is technically correct but extremely difficult to follow, with convoluted branching that obscures the original algorithm.
Before Shield
func processOrder(_ order: Order) -> OrderResult {
let items = order.validatedItems()
let subtotal = items.reduce(0) { $0 + $1.price }
let tax = subtotal * taxRate
let total = subtotal + tax
if total > minimumForDiscount {
applyDiscount(&total)
}
return gateway.charge(total)
}func processOrder(_ order: Order) -> OrderResult {
let items = order.validatedItems()
let subtotal = items.reduce(0) { $0 + $1.price }
let tax = subtotal * taxRate
let total = subtotal + tax
if total > minimumForDiscount {
applyDiscount(&total)
}
return gateway.charge(total)
}After Shield (Conceptual)
func processOrder(_ order: Order) -> OrderResult {
var state = 0
var items, subtotal, tax, total, result
while true {
switch state {
case 0: items = order.validatedItems(); state = 3
case 1: return result
case 2: total = subtotal + tax; state = (total > minimumForDiscount) ? 5 : 4
case 3: subtotal = items.reduce(0) { $0 + $1.price }; state = 6
case 4: result = gateway.charge(total); state = 1
case 5: applyDiscount(&total); state = 4
case 6: tax = subtotal * taxRate; state = 2
}
}
}func processOrder(_ order: Order) -> OrderResult {
var state = 0
var items, subtotal, tax, total, result
while true {
switch state {
case 0: items = order.validatedItems(); state = 3
case 1: return result
case 2: total = subtotal + tax; state = (total > minimumForDiscount) ? 5 : 4
case 3: subtotal = items.reduce(0) { $0 + $1.price }; state = 6
case 4: result = gateway.charge(total); state = 1
case 5: applyDiscount(&total); state = 4
case 6: tax = subtotal * taxRate; state = 2
}
}
}The logic is identical but the flow is no longer sequential, making static analysis significantly harder.
Intensity Levels
| Level | Impact | Use Case |
|---|---|---|
light | Minimal performance overhead | General application protection |
medium | Balanced protection and performance | Most production applications |
aggressive | Maximum obfuscation | High-security applications, proprietary algorithms |
Higher intensity levels apply more complex transformations and produce output that is harder to analyze, with a corresponding increase in binary size and a small performance overhead.
When to Use
Control flow obfuscation is recommended for methods containing business logic, algorithms, or security-sensitive code paths. It is especially effective when combined with Symbol Renaming and Opaque Predicates.
Related
- Opaque Predicates - Add confusing conditional branches
- Dead Code Injection - Insert unreachable code paths
- Protections Overview - All available protections