IRvana
Slaying multi-language LLVM IR with obfuscation passes to achieve JIT execution
Install / Use
/learn @m3rcer/IRvanaREADME
IRvana is a learning and experimentation project centered around the LLVM framework and its intermediate representation (IR) formats, with a focus on code execution, reverse engineering, and JIT experimentation. While its roots are in offensive research, IRvana can be equally valuable for LLVM enthusiasts and developers looking to explore the inner workings of LLVM IR, its tooling, and its practical applications for IR debugging, transformation, and multi-language analysis. These experiments have been specifically targetted for the Windows platform. This choice is intentional, as Windows remains the primary environment of interest for red teams/offensive security and LLVM based Windows development is relatively less widespread compared to Unix like systems.
Project features:
- Simplify Cross-Language LLVM IR Generation
- Provide streamlined IR generation for four languages: C, C++, Rust, and Nim
- Integrate OLLVM obfuscation passes to transform and optimize the generated IR
- Automate IR linking and enable direct interpretation using LLVM tooling
- Enable In-Memory LLVM IR Execution via JIT and BYOI
- Leverage potential lolbas style execution with LLVM’s lli interpreter
- Working POCs using ORCJIT and MCJIT for runtime IR execution
- Showcase malware development techniques and integration with LLVM interpreters for improved OPSEC
Blog References:
- https://whiteknightlabs.com/2025/12/23/just-in-time-for-runtime-interpretation-unmasking-the-world-of-llvm-ir-based-jit-execution/
- https://rohannk.com/posts/Code-in-the-Middle/
Here's an index of the project documentation:
- Introduction
- Project Structure
- Setup Prerequisites
- Streamlining IR Generation with IRvana
- OLLVM and IRvana integration
- LLVM Interpreters
- Malware Development and LLVM interpreters
- Conclusion and Credits
Introduction
LLVM is a powerful compiler infrastructure that supports multiple frontends like C, C++, Rust, and more. It compiles these high-level languages into a target-independent intermediate representation (IR) before generating final machine code.
<p align="center"> <img src="https://i.sstatic.net/9xGDe.png" width=60% height=60%> </p>LLVM IR is like assembly for the LLVM toolchain low-level, human-readable, and optimized for analysis and transformation. There are two key IR formats:
.ll– Plain text form of LLVM IR.bc– Binary (bitcode) form of LLVM IR
In conventional development workflows, LLVM IR is an intermediate step toward creating native binaries. However, LLVM also supports JIT execution via tools like lli or custom runtimes based on ORC/MCJIT. This enables IR to be directly executed in memory making it a lightweight, portable, and dynamic format suitable for use as a stage 1 payload in red teaming or offensive tooling using the BYOI (Bring your own Interpreter) concept.
Converting between .ll and .bc is seamless and straightforward. There are two common approaches to generate LLVM IR for JIT execution:
- Manual IR authoring: Writing .ll files by hand offers readability and control, making it more approachable than raw assembly. However, this method becomes impractical for large codebases due to its complexity and verbosity.
- Automated IR generation: Projects like IRvana can generate LLVM IR from raw, cross-language source code using LLVM tools and apply optimization or deoptimization technique like obfuscation. This makes the resulting IR significantly harder to reverse engineer or analyze.
What makes LLVM IR especially compelling is that IR generated from multiple frontends C, C++, Rust, and Nim can all be interpreted by the same engine. This allows for cross-language polymorphism, dynamic payload behavior, and modular development of payloads and tooling. The interpretability and flexibility of IR make it a powerful format for both learning and offense, where runtime evasion, transformation, and obfuscation are key.
To realize this vision, LLVM version compatibility is critical. Small differences between compiler versions (e.g., Clang, Rustc) can break IR compatibility due to differences in metadata, intrinsics, or ABI details. To reach an "IRvana" state this project standardizes IR generation on a single LLVM version (18.1.5) across all frontends, ensuring the IR produced is linked and stable for execution through lli, ORCJIT, MCJIT, or custom interpreters. By aligning compiler flags, links, and toolchains, IRvana helps build a consistent IR pipeline to generate IR from C, C++, Rust and Nim project sources with multiple source files and includes.
This project also integrates obfuscation at the IR level using OLLVM. Techniques such as control flow flattening, indirect calls, string encryption, and indirect branching are applied to harden the IR and simulate real-world evasive payloads. These techniques are applied post-linking or on per-file basis, depending on the obfuscation mode selected.
Lastly, IRvana includes built-in LLVM tools and multiple POCs in C++ and Rust that demonstrate JIT (Just in time) execution using ORCJIT and MCJIT capable of interpreting generated IR. Maldev related integrations such as in-memory IR loading and encrypted payload decryption have also been documented for real world applications. These examples bridge LLVM IR tooling with malware development practices to explore JIT code execution and BYOI techniques in depth.
Main Project structure
IRVana/
├── IRgen/
│ ├── c/
│ │ └── Makefile.ir.mk --> Makefile for IR generation
| | └── src --> User places source here
| | └── ir_bin --> IR Generated file named final.ll or final-obf.ll
| | └── detect_sdk.bat --> Windows SDK and runtime detection
| | └── vs_env.mk --> Windows SDK and runtime generated information
│ ├── cxx/
│ │ └── Makefile.ir.mk
| | └── src --> User places source here
| | └── ir_bin --> IR Generated file named final.ll or final-obf.ll
| | └── detect_sdk.bat --> Windows SDK and runtime detection
| | └── vs_env.mk --> Windows SDK and runtime generated information
│ ├── rust/
│ │ └── Makefile.ir.mk
| | └── src --> User places source here
| | └── ir_bin --> IR Generated file named final.ll or final-obf.ll
| | └── detect_sdk.bat --> Windows SDK and runtime detection
| | └── vs_env.mk --> Windows SDK and runtime generated information
│ └── nim/
│ | └── Makefile.ir.mk
| | └── src --> User places source here
| | └── ir_bin --> IR Generated file named final.ll or final-obf.ll
| | └── detect_sdk.bat --> Windows SDK and runtime detection
| | └── vs_env.mk --> Windows SDK and runtime generated information
├── LLVM-18.1.5/
│ | └── bin --> Executable binaries like clang, clang++, clang-cl, opt, llc, lli, etc.
| | └── include --> header files for LLVM and Clang APIs
| | └── lib --> Static and dynamic libraries for LLVM/Clang.
| | └── libexec --> Helper executables used internally by LLVM/Clang
├── OLLVM/
| | └── vs_build --> Build files for OLLVM DLL
| | | └── ollvm-pass.sln --> Visual Studio project to recompile OLLVM DLL
| | | └── obfuscation\Release\LLVMObfuscationx.dll --> Precompiled OLLVM DLL
| | └── .....
IRvana.cpp --> Source code for automating IR generation and obfuscation
IRvana.sln --> Primary project for handling IR generation and obfuscation
├── x64/
│ └── Debug/
│ └── IRVana.exe --> Compiled build
├── nim-1.6.6/
│ | └── bin --> Executable binaries like nim, nimble
│ | └── compiler --> Nim compiler sources and modules
│ | └── lib --> Standard libraries and runtime used by Nim
├── Interpreters/
| | └── lli - ORC JIT --> LLVM’s own command-line interpreter
| | └── cxx - MCJIT --> Custom C++ interpreter built using the older MCJIT engine
| | └── cxx - ORC JIT --> Modernized C++ interpreter leveraging ORC JIT APIs
| | └── Rust - MCJIT --> Rust-based interpreter using MCJIT
├── Maldev/
| | └── IREncryption --> POC for to AES Encrypt LLVM IR before execution
| | └── RemoteLoad --> Loads obfuscated IR over the HTTP and executes via JIT in memory
Installation using a script
You can just run the below commands to install the entire project including setup
# Run using an elevated powershell
Set-ExecutionPolicy -Force Bypass
iex(iwr -Uri https://raw.githubusercontent.com/m3rcer/IRvana/refs/heads/main/Install.ps1 -UseBasicParsing)
Docker container
docker build -t irvana-windows .
docker run -it -
