# OLLVM Deobfuscation Workflow: A 7-Step Guide to Reversing Obfuscator-LLVM Binaries

> Master OLLVM deobfuscation with this 7-step workflow. Learn to reverse Obfuscator-LLVM binaries using angr, plugins, and specialized tools for readable control flow.

- Repository: [ZhaoXu/reverse-skill](https://github.com/zhaoxuya520/reverse-skill)
- Tags: how-to-guide
- Published: 2026-08-20

---

**The OLLVM deobfuscation workflow is a layered pipeline that starts with generic symbolic execution in angr, applies environment-specific plugins (D‑810, obpo-plugin, ollvm-breaker), then uses specialized unflatteners, MBA simplifiers, and optional dynamic tracing to fully restore readable control flow.**

The **OLLVM deobfuscation workflow** documented in the `zhaoxuya520/reverse-skill` repository provides reverse engineers with a systematic, tool-agnostic approach to dismantling binaries protected by Obfuscator-LLVM and its modern derivatives. This community-curated methodology, detailed in [[`skills/reverse-engineering/references/ollvm-deobfuscation.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/references/ollvm-deobfuscation.md)](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/references/ollvm-deobfuscation.md), breaks down the problem into discrete stages—from initial identification to final verification—allowing analysts to mix and match tools based on their environment and the specific OLLVM variant encountered.

## Step 1: Identify OLLVM Protection Patterns

Before running any deobfuscation tool, confirm that the binary actually uses OLLVM protection. The repository maintains a pattern database in [[`skills/reverse-engineering/patterns.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/patterns.md)](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/patterns.md) to accelerate this identification.

Look for these classic OLLVM signatures:

- **Control-flow flattening**: `while(1){switch}` dispatch loops that replace sequential execution with state machines
- **Mixed-boolean-arithmetic (MBA)**: Obfuscated expressions combining arithmetic and boolean operations
- **Opaque predicates**: Always-true or always-false conditions designed to confuse symbolic execution
- **Indirect branches**: Jumps computed at runtime rather than static targets
- **VM-style constructs**: Bytecode interpreters hiding the original program logic

For quick detection, grep for the flattening pattern or reference the routing table entry that links these patterns to the full deobfuscation guide.

```bash

# Quick pattern search across a codebase

grep -R "while(1){switch}" ./suspected_binary/

```

## Step 2: Select the Right Deobfuscation Framework

The `reverse-skill` repository tracks a hierarchy of deobfuscation tools, each optimized for different environments. According to the routing matrix in [[`skills/routing.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/routing.md)](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/routing.md) (lines 225–227), these are the primary options:

- **D‑810 / d810‑ng** – Pattern-based deobfuscator for IDA Pro; historically the "original" OLLVM plugin
- **obpo-plugin** – Hex-Rays microcode cloud plugin; considered the most powerful for commercial workflows
- **ollvm-unflattener (Miasm)** – Pure-Python symbolic execution specifically for flattening removal
- **ollvm-breaker (Binary Ninja)** – BN-centric unflattener for analysts using Vector35's platform
- **angr Deobfuscator** – Fully scriptable symbolic execution with no GUI dependency
- **deollvm** – Unicorn-based runtime emulator optimized for ARM64 targets

Choose based on your disassembler and whether you need interactive or automated processing.

## Step 3: Execute the Generic Deobfuscator Pipeline

The repository provides a ready-made **angr Deobfuscator** analysis that serves as the recommended first pass. As implemented in the reference workflow (lines 258–363 of [[`ollvm-deobfuscation.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/ollvm-deobfuscation.md)](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/references/ollvm-deobfuscation.md)), this analysis automatically:

1. Detects flattening dispatch loops in the control flow graph
2. Simplifies MBA expressions to native arithmetic
3. Removes opaque predicates by proving their constant truth values
4. Normalizes indirect branches to direct jumps where possible

```python
import angr

# Load binary without auto-loading libraries for faster analysis

proj = angr.Project('ollvm_protected.bin', auto_load_libs=False)

# Target the entry point or specific function (e.g., 'main')

func_addr = proj.entry

# Run the built-in Deobfuscator analysis

deob = proj.analyses.Deobfuscator(func=func_addr)

print('[+] Deobfuscation completed')
print(f'[+] Simplified {len(deob.modified_blocks)} basic blocks')

```

The resulting intermediate representation is significantly cleaner and imports cleanly into any disassembler for further analysis.

## Step 4: Apply Specialized Unflatteners for Residual Protection

If Step 3 leaves residual flattening or indirect branches, escalate to environment-specific tools that operate on the already-simplified CFG:

- **IDA Pro workflows** → `d810-ng` or `obpo-plugin`
- **Binary Ninja workflows** → `ollvm-breaker`
- **Scriptable Python workflows** → `ollvm-unflattener`

These tools handle edge cases that the generic angr analysis misses, particularly complex state machines with anti-analysis integration.

```bash

# Miasm-based unflattener for remaining control-flow flattening

ollvm-unflattener -i deobf_stage1.bin -o flatless.bin

```

## Step 5: Post-Process MBA and Opaque Predicates

After structural unflattening, run dedicated simplifiers to clean up arithmetic obfuscation. The repository recommends:

- **MBA simplifier** (integrated in D‑810) – Collapses complex boolean-arithmetic hybrids into single operations
- **Opaque-predicate remover** – Often built into the Deobfuscator, but available as standalone in `d810-ng`

```bash

# D-810 MBA simplification pass

d810-ng --mba flatless.bin -o simplified.bin

```

This step is critical: MBA expressions that survive flattening removal often hide the actual program semantics in seemingly nonsensical arithmetic.

## Step 6: Verify Results and Iterate

Import the cleaned binary into your preferred disassembler (IDA, Ghidra, Binary Ninja, or Cutter) and verify that:

- The control flow graph shows sequential, structured logic rather than state-machine dispatch
- Previously hidden branches and conditions are now visible
- Function boundaries and call graphs are correctly recovered

If flattening or opaque predicates remain, repeat Steps 3–5 with alternative tools. The routing table in [[`routing.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.md)](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/routing.md) suggests fallback options—for example, switching from angr to Quarkslab's `deflat` for aggressive trap-based protection.

```bash

# Visual verification: export CFGs for comparison

ghidra -process simplified.bin -export-cfg simplified.cfg
diff original.cfg simplified.cfg

```

## Step 7: Dynamic Tracing for Stubborn Cases

Some OLLVM variants employ anti-debug tricks that modify predicates at runtime, defeating static analysis. For these cases, the repository recommends dynamic tracing:

- **angr Symbolic Execution** with concrete state injection
- **deflat (Quarkslab)** – Runtime-aware unflattener mentioned at line 430 of [[`ollvm-deobfuscation.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/ollvm-deobfuscation.md)](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/references/ollvm-deobfuscation.md)
- **Runtime-emu via deollvm** – Unicorn-based emulation for ARM64 targets

Capture the concrete execution state, feed it back into the static pipeline, and repeat until the binary is fully deobfuscated.

```bash

# Quarkslab deflat for runtime-assisted deobfuscation

deflat -i stubborn.bin -o final_clean.bin

# ARM64 emulation alternative

deollvm -i stubborn.bin -o final_clean.bin

```

## Handling Modern OLLVM Derivatives

The reference document extends this OLLVM deobfuscation workflow to cover community-maintained variants including **Hikari**, **Polaris**, **O‑MVLL**, **Arkari**, and **amice**. Each derivative modifies the core obfuscation techniques, and the routing table maps these to appropriate tool configurations—ensuring the workflow remains effective against actively developed protection schemes.

## Summary

- **Tool-agnostic first pass**: Start with `angr`'s `Deobfuscator` analysis for platform-independent results
- **Environment-specific polishing**: Apply `d810-ng`, `obpo-plugin`, or `ollvm-breaker` based on your disassembler
- **Layered removal**: Each step eliminates one class of OLLVM tricks, reducing complexity for subsequent stages
- **Verification-driven iteration**: Re-import and inspect; repeat with alternative tools if protection persists
- **Dynamic fallback**: Use `deflat`, `deollvm`, or concrete symbolic execution for runtime-dependent obfuscation

## Frequently Asked Questions

### What is the fastest way to confirm a binary uses OLLVM protection?

Search for the classic flattening pattern `while(1){switch}` or reference the pattern list in [[`skills/reverse-engineering/patterns.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/patterns.md)](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/patterns.md). This signature appears in the vast majority of OLLVM-protected binaries and provides immediate confirmation without running complex analysis.

### Can I deobfuscate OLLVM binaries without IDA Pro or Binary Ninja?

Yes. The **angr Deobfuscator** (`proj.analyses.Deobfuscator`) runs entirely from Python without GUI dependencies. It is the recommended starting point in the official workflow and produces deobfuscated output compatible with free tools like Ghidra and Cutter.

### How does the repository handle newer OLLVM forks like O-MVLL and Arkari?

The reference file [[`ollvm-deobfuscation.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/ollvm-deobfuscation.md)](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/reverse-engineering/references/ollvm-deobfuscation.md) maintains a variant matrix that maps each modern derivative to tested tool configurations. The core 7-step workflow remains applicable, but specific parameters and plugin versions may differ—consult the routing table entry for your target variant.

### What should I do if the deobfuscator leaves some opaque predicates intact?

Repeat the pipeline with an alternative tool, particularly switching from static to dynamic approaches. The repository recommends **deflat** from Quarkslab (line 430) or **deollvm** for ARM64 targets, both of which handle runtime-modified predicates that static analysis cannot resolve.