DEV Community

lich0
lich0

Posted on • Edited on

Implement ollvm with llvm pass

Why lich4/ollvm-pass is worth attention among “hundreds of OLLVM open-source projects”

GitHub - lich4/ollvm-pass: Independent hikari

If you’ve been looking for OLLVM (Obfuscator-LLVM) related projects recently, you’ve probably run into a reality: there are tons of open-source repos, but not many that actually bring something new. Many projects mainly port classic implementations to newer LLVM/Clang versions—useful, but limited when it comes to real-world engineering adoption and controllable obfuscation.

lich4/ollvm-pass, however, has a very clear positioning: based on LLVM NewPassManager, it turns original OLLVM + Hikari-style implementations into standalone “passes,” and fills in what production use most often lacks— a policy system and Xcode integration.


1) Most mainstream OLLVM projects focus on “version compatibility,” not “engineering enhancements”

Common open-source OLLVM projects include:

  • obfuscator-llvm/obfuscator: the earliest public Obfuscator-LLVM, implementing classic features such as substitution / bogus control flow / flattening.
  • HikariObfuscator/Hikari: extends Obfuscator with string encryption, split basic blocks, function wrapping / call obfuscation, etc.
  • KomiMoe/Arkari (goron family): more focused on indirect calls/branches and adapts to newer LLVM.
  • za233/Polaris-Obfuscator: adds some MIR-level obfuscation beyond IR (e.g., dirty bytes, MIR instruction substitution).
  • open-obfuscator/o-mvll: emphasizes “Python-driven + pass manager,” with broad feature coverage.

The issue is: many derivative repos mainly add “compatibility with newer LLVM versions.” But in real engineering scenarios—“obfuscate only key modules/functions,” “don’t explode build time,” “don’t increase app store release risk”—they often don’t provide a systematic solution.


2) From “patching LLVM source” to “dynamic passes”: the modern way to do OLLVM

In the early days (LLVM 3.x era), OLLVM often meant directly modifying LLVM’s source, largely because the ecosystem and mechanisms weren’t mature. Today, most IR-level obfuscation can be done via pass plugins.

A simplified evolution of LLVM’s pass mechanism:

  • LLVM 5–12: primarily LegacyPassManager
  • LLVM 13–14: Legacy by default, also supports NewPassManager
  • LLVM 15–present: NewPassManager by default

Engineering advantages of dynamic passes (pass plugins)

This is one of the core values emphasized by lich4/ollvm-pass:

  • Avoid the massive cost of building LLVM/Clang: you can use the LLVM already installed on your system (Homebrew/apt, etc.) as long as the major Clang version matches.
  • Fast build and iteration: the output is typically just a few-MB dynamic library, not a hundreds-of-MB clang binary or multi-GB toolchain.
  • Better developer experience: writing passes, running them, validating IR output—iteration is faster and the barrier is lower.

That said, it’s important to acknowledge the boundaries: passes are hard to cover MIR/MC-level obfuscation (which is why projects like Polaris add MIR-level enhancements).


3) What lich4/ollvm-pass does: not “yet another port,” but a production-usable pass-based solution

The project description is straightforward: based on LLVM NewPassManager, it turns original OLLVM + Hikari into independent passes, verifying that “IR-level obfuscation can be implemented as standalone passes,” and it’s tested on macOS 15 + LLVM 15–19.

More importantly, it completes two capabilities that matter a lot for real adoption:


a) A “policy syntax”: precisely control obfuscation down to module/function via policy.json

In real projects, many teams aren’t unwilling to obfuscate everything—they can’t:

  • The project/dependencies are huge; obfuscating irrelevant code bloats artifacts
  • Heavy obfuscation (like flattening) slows builds drastically or even causes stalls
  • After obfuscation, runtime overhead can become obvious for complex algorithms (flattening often causes ~10% level overhead)
  • Over-obfuscation may increase compliance/review risk for App Store / Google Play (these points are explicitly mentioned in the README)

So in practice, “controllable obfuscation” matters more than “obfuscation exists.” Traditional open-source OLLVM controls are often either too coarse (module-only), too intrusive (requires code changes), or limited by language (e.g., annotations that mainly work for C/C++).

ollvm-pass’s approach: use a policy.json in the working directory to declare rules—compatible with most frontends and languages—distinguishing module-level and function-level strategies; also supports “forward override,” optional field comments, IR dump, and other engineering features.

You can think of it as: upgrading obfuscation switches from compiler flags / code intrusion to an auditable, reusable, version-controllable policy configuration—critical for large, multi-module, multi-language builds (especially on mobile).


b) Xcode integration: a realistic integration path for iOS/macOS projects

Many people hit the same pitfall: open-source clang ≠ Apple clang shipped with Xcode; pass plugins don’t always “just work” inside Xcode. ollvm-pass provides three practical routes in its README:

  1. In Xcode, set CC to open-source clang and add -fpass-plugin in Other C Flags
  2. In Xcode, set CC to a script: first clang -emit-llvm to produce bitcode, then run passes with opt, then clang -c to output an object file (the repo provides the author’s script xcode_cc.sh), and notes this is more friendly for arm64e compatibility
  3. Build a dynamic pass specifically for Apple clang (hard: must handle symbol conflicts; better for LLVM experts)

The value here is: it doesn’t just say “it’s theoretically possible”—it lays out real, workable engineering integration paths, including ready-to-use scaffolding (scripts).


Who is this for?

  • You don’t want to build a multi-GB toolchain just for one OLLVM setup, and you want “compile the pass in minutes, validate immediately.”
  • You need “obfuscate only key modules/functions” in a real production codebase, and you want policies that are versioned and auditable
  • You target iOS/macOS (Xcode / Apple clang ecosystem) and want a practical integration path

If OLLVM is “just for running a demo,” then many porting repos are enough. But if you want it in production—controllable and maintainable—then the direction of pass-based + policy-based + Xcode-adapted like lich4/ollvm-pass is much closer to an engineering-grade answer.


References

  1. GitHub - lich4/ollvm-pass: Independent hikari
  2. GitHub - lich4/awesome-ollvm: List of (truly) awesome Obfuscator-LLVMs and IDA deobfuscation plugins
  3. OLLVM learning | Chao’s blog

Top comments (0)