Skip to content

Architecture

kagura/
├── include/kagura/         Public headers (Passes.h, Options.h, Utils.h, game_protect.h)
├── lib/Transforms/
│   ├── CFG/                Control-flow obfuscation passes
│   ├── Data/               String / constant / global / wide-string / memory-value encryption
│   ├── AntiAnalysis/       Anti-debug, integrity, call indirection, honey values
│   ├── Platform/           iOS (ObjC), Android (JNI), VM virtualization
│   ├── Infrastructure/     DWARF control, config DSL, symbol map
│   ├── Options.cpp         Centralized CLI flag definitions
│   ├── Plugin.cpp          Pass registration & pipeline wiring
│   └── Utils.cpp           Shared IR helpers & PRNG
├── runtime/
│   ├── core/               AES, VM interpreter, crash symbolication, device key
│   ├── anti_debug/         Anti-debug / anti-Frida (cross-platform POSIX)
│   ├── android/            Android + Linux: root detection, attestation, /proc, syscall
│   ├── ios/                iOS / macOS: jailbreak detection, Mach-O integrity
│   ├── windows/            Windows: IsDebuggerPresent, NtQueryInformationProcess, PE integrity
│   └── game/               Anti-cheat, IL2CPP protection, telemetry
├── integration/            Xcode, Gradle, Unity, Unreal, CMake, Bazel, CocoaPods, SPM
├── scripts/                CLI tools, verification, differential testing, review risk assessment
└── tests/                  CTest + FileCheck lit-based regression tests

Plugin entry point

lib/Transforms/Plugin.cpp registers all passes with the LLVM New Pass Manager via PassPluginLibraryInfo. It does two things:

  1. Exposes every pass by name so it can be requested from opt (-passes="kagura-str,...") or from clang via -mllvm -kagura-<name>.
  2. Auto-wires the recommended order onto the OptimizerLast extension point so users only need -fpass-plugin=KaguraObfuscator.dylib to get a sensible default pipeline.

Configuration & options

Options.cpp is the single source of truth for every CLI flag — adding a new tunable means adding a cl::opt<...> there, then reading it from the pass. The kagura-config loader runs first in the pipeline and populates these option values from the JSON policy file.