Function Obfuscation
These are the obfuscation techniques that can be applied to functions. Most of your obfuscation needs will be met by one or more of these features.
Mutation Engine
The Mutation Engine is CodeDefender’s proprietary obfuscation pass that transforms simple instruction sequences into tightly-coupled, high-entropy logic using a wide variety of x86-64 instructions.
Unlike traditional mutation strategies seen in other protectors—which are often vulnerable to dead store elimination or can be simplified through constant folding—our engine is designed to emit no trivially removable or foldable code. This makes static cleanup extremely difficult, even for automated analysis tools.
The generated mutations are intentionally fragile: removing even a single instruction from the sequence will break the logic.
Key Benefits
- Breaks Modern Tools: Successfully disrupts analysis pipelines in IDA Pro, Ghidra, Binary Ninja, Angr, icicle-emu, and similar frameworks.
- Minimal Performance Overhead: Carefully engineered to introduce negligible runtime overhead, enabling you to apply this pass across all functions without impacting usability.
- Semantic Complexity: Forces deobfuscators to build complete semantic models of each instruction, significantly increasing the effort and time required for reverse engineering.
Mixed Boolean Arithmetic
The Mixed Boolean Arithmetic (MBA) pass rewrites arithmetic and logical operations in the IR into complex expressions composed of mixed boolean and arithmetic sub-expressions.
This technique leverages mathematical identities and redundancies to generate expressions that are semantically equivalent to the original operation but structurally far more complex. These transformations are specifically designed to resist simplification by symbolic execution engines and decompilers.
Key Benefits
-
Combines Well with Other Passes: When layered with the Mutation Engine or control flow flattening, MBA can dramatically increase reverse engineering difficulty.
-
Obfuscates Semantics: Even simple operations like
x + ycan be rewritten into dozens of terms involving XOR, AND, OR, and addition. The usage of opaque values and large constants disrupts public MBA simplifiers (Synthesis explodes in time when more variables are used). -
Fully Customizable: Expression depth and template selection can be tuned to balance between obfuscation strength and performance impact.
Opaque Block Duplication
This pass increases control-flow complexity by splitting basic blocks and introducing opaque predicates. The opaque predicate is designed to look realistic while being semantically irrelevant. It is built from:
- Function argument registers:
RCX,RDX,R8,R9 - Stack arguments, discovered via stack analysis
- Constant values, randomly chosen from a pool that includes:
NTSTATUSerror codes- PE header signatures and section names
- Cryptographic algorithm IDs
- Hash function initialization vectors (MD5, SHA-1, SHA-256, SHA-512)
- Miscellaneous “red herring” constants
Although both branches of the predicate ultimately converge to the same execution state, static analysis tools interpret them as divergent paths, which makes the control-flow graph appear far more complex and irregular.
Subsequent obfuscation passes will then mutate each duplicated branch differently, so the two paths no longer look identical in form even though they are equivalent in behavior. This makes it significantly harder for an analyst (or automated deobfuscator) to distinguish between genuine control flow and fabricated diversions.
Furthermore, because the transformation can be applied recursively, blocks can be split and re-split multiple times. This recursive layering produces an exponential growth in opaque branches, resulting in an increasingly dense and misleading control-flow graph that resists both structural and symbolic simplification.
Key Benefits
- Realistic Predicates: Conditions are built from function arguments and plausible constants (NTSTATUS, crypto, PE signatures), making them hard to distinguish from genuine program logic. Existing solutions create simple, easily to solve opaque predicates. This pass will require an attacker to perform whole program analysis.
- Asymmetric Obfuscation: Subsequent passes transform each duplicate differently, so the two branches no longer appear identical, blurring the line between “real” and “opaque.”
- Runtime Variability: Because predicates use live inputs and randomized choices, different branches may be taken at runtime across executions or inputs.
Loop Encode Semantics
The Loop-Encoded Semantics pass takes simple, easily recognizable operations—such as Add, Sub, And, Xor, etc—and transforms them into semantically equivalent loops with no statically determinable bounds.
Rather than computing results in a single instruction, this pass encodes the logic using iterative, opaque-state loops. These loops intentionally lack clear trip counts, termination conditions, or symbolic bounds, which causes symbolic execution engines and static analyzers to stall, over-approximate, or completely misinterpret the semantics.
Key Benefits
- Kills Symbolic Execution: By removing analyzable loop bounds, engines like Angr, SymExec, and Ghidra’s p-code evaluator can’t evaluate or inline the loop body correctly.
- Combinatorially Powerful: When combined with MBA, control-flow flattening, or the Mutation Engine, loop-encoded operations become nearly impossible to pattern match.
Indirect Control Flow Obfuscation
This pass transforms all conditional branches—including standard JCC instructions and loop-related branches like JECXZ, LOOP, etc.—into indirect jumps via registers or memory. Every conditional transfer of control is rewritten so that its destination is no longer statically visible in the instruction stream.
Unlike traditional branching, this pass does not rely on the EFLAGS register. Instead, each branch condition is expanded by this pass in our intermediate representation (IR) as explicit logic, typically through branchless programming techniques to assign the target address followed by an indirect jump.
Additional logic is injected into these branch statements to thwart symbolic execution engines. We make it very difficult for an attacker to determine all possible branch destinations.
This pass also obscures all data references and rewrites call instructions as indirect calls. This ensures that both code and data access patterns are concealed from static analysis.
By eliminating direct conditional branches and decoupling control flow from architectural flags, this transformation breaks conventional control flow recovery techniques and enables more aggressive obfuscation layering.
Key Benefits
- Flagless Execution: Conditions are modeled directly in IR, removing reliance on
EFLAGSand defeating flag-based brute force attacks to uncover branch targets. - Composable with Other Passes: Since the conditional logic is expressed in IR, it can be layered with obfuscation passes.
- Static Analysis Disrupted: Static recovery of control flow is prevented making tools such as
IDA Pro,Ghidra, andBinjauseless.
Only one iteration of this pass is allowed per function. For best results, carefully plan the obfuscation pipeline—decide which passes should run before and after this one to maximize effectiveness and compatibility.
Obscure References
This pass obscures all direct references to code and data, disrupting disassembler heuristics and breaking cross-reference tracking in tools like IDA Pro, Ghidra, and Binary Ninja.
It is automatically included in the Indirect Control Flow Obfuscation pass, but can also be used independently if your goal is to obfuscate only call targets and data references—without transforming conditional or unconditional branches.
Key Benefits
- Breaks cross-reference graphs in static analysis tools
- Hides call targets, disrupting function-level reverse engineering
- Conceals data pointers that may expose configuration or constants
- Compatible with control-flow flattening and mutation passes
- Lightweight alternative to full control-flow obfuscation when only reference hiding is desired
Lea Encode Immediates
Lea Encode Immediates is a small transformation pass that rewrites immediate constants into equivalent Lea + Sub instruction sequences. Instead of leaving raw immediates in the code, the pass encodes them via pointer/offset-style operations so the resulting SSA values can be used by later passes to further obfuscate or transform the program.
Key Benefits
- Normally, Lea instructions only appear when code actually computes a memory address. Introducing Lea sequences for immediates increases semantic diversity, so the presence of a Lea is no longer a reliable signal that a section of code references some module data.
Split Basic Blocks
Split Basic Blocks is a lightweight transformation pass that splits selected basic blocks into two sequential blocks. The original block is replaced by a top half that ends with an unconditional jump to the newly-created bottom half, which then contains the remainder of the original instructions and the original terminator. This creates extra control-flow edges and intermediate basic blocks that downstream control-flow obfuscation or transformation passes can latch onto.
The pass is safe to run repeatedly and to interleave with other transformation passes.
Obscure Constant Pass
The Obscure Constant Pass is a lightweight compiler pass designed to statically obscure constants in code. This pass modifies constants to make them less recognizable in the compiled output, but it does not prevent them from being rematerialized at runtime. For stronger protection against runtime rematerialization, use the Constant Suppression instead.
Usage
The Obscure Constant Pass is most effective when used in combination with the Constant Suppression. It targets constants that the Constant Suppression cannot protect, such as those that may still be rematerialized at runtime. For example:
mov [rsp+0x10], 0xDEADBEEF
In this case, the constant 0xDEADBEEF cannot be fully obscured by Constant Suppression due to potential runtime rematerialization. However, Obscure Constant Pass can statically obscure this constant, making it less identifiable in the compiled code.
Important Considerations
The Obscure Constant Pass must be applied after the Constant Suppression. The Constant Suppression performs aggressive constant folding, which can undo the obfuscation introduced by Obscure Constant Pass if run afterward.
Key Features
- Statically obscures constants to reduce their readability in compiled code.
- Complements
Constant Suppressionfor cases where constants cannot be fully protected. - Lightweight and easy to integrate into existing compiler pipelines.
Limitations
- Does not prevent runtime rematerialization of constants.
- Must be carefully sequenced with other passes to avoid unintended interactions.
For optimal results, ensure that Obscure Constant Pass is used as part of a broader obfuscation strategy, alongside Constant Suppression and other relevant passes.
Anti-Emulator Pass
This pass injects obfuscated initialization code at the very start of functions it is applied to. The purpose is to detect and disrupt emulation environments such as QEMU, Unicorn Engine, Qiling, and other similar tools.
- When the function is executed under an emulator, the injected code causes it to enter an infinite loop, effectively halting automated analysis and defeating tools like unxorer for IDA, Unicorn Engine, Qiling, and Demigod.
- When running on a real CPU, the pass has minimal to no effect and the function behaves normally.
Key Benefits
- This pass does not use any operating system API calls or require any specific execution environment. It will work in usermode, kernelmode, UEFI, in a hypervisor, SMM, etc.
Constant Suppression
The Constant Suppression pass ensures that sensitive constants are never materialized in registers or memory during runtime. Instead of computing or loading a constant directly, all IR nodes that interact with constants are rewritten to avoid exposing the literal value—if semantically possible.
This is particularly valuable in black-box functions that manipulate secrets, such as cryptographic keys, hashes, or obfuscated control data. By eliminating literal constants from runtime traces, this pass prevents both static inspection and dynamic analysis tools from recognizing key values that could aid reverse engineering.
Certain constants—such as 0 and 1—are structurally necessary in some computations and may still appear, depending on the logic. Additionally, if a constant must be passed to an external function or explicitly written to memory (e.g., due to API semantics), rematerialization may be unavoidable.
This pass operates on a best-effort basis: while many constants can be fully suppressed through transformation, no guarantee is made that all constants will remain entirely hidden in all contexts.
Key Benefits
-
Eliminates Telltale Values: Prevents values like
0x1000193(FNV prime) or0x67452301(MD5 IV) from showing up in registers or memory, which are often used by analysts to identify algorithmic intent. -
Novel Constant Obfuscation: Most commercial virtualizers still leak constants in registers or memory. CodeDefender's Constant Suppression avoids this entirely by transforming the IR before codegen.
IDA Decompiler Crasher
The IDA Decompiler Crasher pass is designed to fatally disrupt IDA Pro’s decompiler engine, rendering it incapable of analyzing protected functions. When applied, this transformation injects carefully crafted constructs that exploit internal assumptions in the decompiler’s logic—causing it to crash instantly when attempting to lift the function into pseudocode.
This technique is compatible with all known versions of IDA Pro, including the latest commercial releases.
To observe the effect:
- Apply the pass to a target function.
- Open the binary in IDA Pro.
- Navigate to the protected function and press
F5. - The decompiler will crash immediately, halting analysis.
This feature requires you apply this pass as the very last pass!
An example of the outcome is shown below:

Any further analysis, decompilation, etc., results in this pop-up message: