Skip to content
/ mirage Public

Is an experimental obfuscator that makes your Java bytecode harder to reverse engineer by replacing direct method calls and field accesses with reflection-based equivalents

License

Notifications You must be signed in to change notification settings

DedInc/mirage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌫️ Mirage

⚠️ EXPERIMENTAL · A reflection-based Java obfuscator that transforms direct method calls and field accesses into reflection API equivalents. Specialized, not full-featured.

Java 16+ License: MIT Gradle

🎯 What Is This?

Mirage is an experimental obfuscator that makes your Java bytecode harder to reverse engineer by replacing direct method calls and field accesses with reflection-based equivalents. Unlike full-featured obfuscators that do name mangling, control flow obfuscation, and string encryption, Mirage specializes in one thing: reflection transformation.

What It Does

// Before (Direct bytecode)
String result = someObject.doSomething(arg1, arg2);

// After (Reflection-based bytecode)
Method m = ReflectionHelper.getMethodSmart(someObject.getClass(), "doSomething", ...);
String result = (String) ReflectionHelper.invoke(m, someObject, new Object[]{arg1, arg2});

All transformations happen at the bytecode level — your source code remains unchanged.

⚡ Key Features

  • 🔄 Method Call Transformation — Converts INVOKEVIRTUAL, INVOKESTATIC, INVOKEINTERFACE to reflection
  • 📦 Field Access Transformation — Rewrites GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC
  • 🏗️ Constructor Handling — Transforms NEW + INVOKESPECIAL sequences (experimental)
  • λ Lambda Support — Processes invokedynamic lambda expressions
  • 🔍 Smart Detection — Auto-detects hot paths (nested loops) and respects annotations
  • ⚙️ Configurable Exclusions — Wildcard patterns to exclude packages/classes/methods
  • 📊 JAR & Class Processing — Works with both .jar and .class files

🚀 Quick Start

Prerequisites

  • Java 16 or higher
  • Gradle (or use included wrapper)

Build

./gradlew build

The shadow JAR will be created at build/libs/mirage-1.0.jar

Usage

# Transform a JAR file
java -jar mirage-1.0.jar input.jar output.jar

# Transform a single class file
java -jar mirage-1.0.jar MyClass.class MyClass-obf.class

# Use custom configuration
java -jar mirage-1.0.jar input.jar output.jar --config my-config.yml

# Generate default config
java -jar mirage-1.0.jar --init

⚙️ Configuration

Generate a config file with mirage --init, then customize:

obfuscation:
  reflectMethodCalls: true       # Transform method calls
  reflectFieldAccess: true       # Transform field accesses
  reflectConstructors: false     # Transform constructors (experimental!)
  reflectStaticCalls: true       # Transform static calls
  reflectLambdas: true           # Transform lambdas
  wrapPrimitives: true           # Box primitives for reflection
  useStringBuilder: true         # Use StringBuilder for string ops

smartDetection:
  respectNoReflectionAnnotation: true   # Honor @NoReflection
  respectHotPathAnnotation: true        # Honor @HotPath
  autoDetectHotPaths: true              # Auto-detect performance-critical loops
  loopThresholdForHotPath: 3            # Nested loop depth threshold

exclude:
  packages:
    - "java.**"                  # Exclude JDK classes
    - "javax.**"
    - "com.example.internal.**"  # Your exclusions
  
  classes:
    - "**Test"                   # Exclude test classes
  
  methods:
    - "com.example.MyClass.main" # Exclude specific methods

Wildcard Patterns

  • * — Matches within a single package level
  • ** — Matches across package hierarchies
  • Examples:
    • com.example.*com.example.MyClass ✅, com.example.sub.Other
    • com.example.** → both match ✅
    • **Test → any class ending with "Test" ✅

🎓 Annotations

Protect performance-critical code from obfuscation:

import com.github.dedinc.mirage.annotation.NoReflection;
import com.github.dedinc.mirage.annotation.HotPath;

@NoReflection(reason = "Performance critical")
public class FastProcessor {
    
    @HotPath("Called millions of times per second")
    public void processData(byte[] data) {
        // This code won't be transformed
    }
}

How It Works

  1. Analysis PhaseBytecodeAnalyzer scans classes, classifies instructions, detects hot paths
  2. Planning PhaseInstructionClassifier decides what can be safely transformed
  3. Transformation PhaseTransformationPipeline applies transformers (method, field, constructor, lambda)
  4. Code GenerationReflectionCodeGenerator emits reflection API calls
  5. Class WritingSafeClassWriter produces valid bytecode with recomputed frames

🎯 Use Cases

This is an experimental obfuscator with a narrow specialization. Use it for:

  • 🛡️ Code Protection — Add an extra layer of obfuscation through reflection
  • 🔒 Anti-Decompilation — Make decompiled code less readable and harder to understand
  • 🧩 Complementary Obfuscation — Combine with other obfuscators for layered protection
  • 🔬 Research — Study reflection-based obfuscation techniques
  • 📚 Education — Learn bytecode manipulation and Java reflection internals

NOT a replacement for:

  • ❌ Full-featured commercial obfuscators (ProGuard, DashO, etc.)
  • ❌ Name obfuscation, control flow flattening, or string encryption
  • ❌ Performance-critical production code (reflection adds overhead)
  • ❌ Security measures (obfuscation ≠ security)

⚠️ Limitations & Caveats

This is an experimental obfuscator with known limitations:

  • Specialized Focus — Only handles reflection transformation, not name mangling or control flow
  • Performance Impact — Reflection is slower than direct calls (10-100x depending on JIT)
  • Decompilation Visible — Reflection calls are visible but harder to understand than direct calls
  • Constructor Transform UnstablereflectConstructors is marked experimental for a reason
  • Frame Computation — Complex control flows may cause verification errors
  • JDK Compatibility — Requires Java 16+, targets modern bytecode
  • No Name Obfuscation — Class/method/field names remain readable (combine with other tools)

🔧 Development

# Build
./gradlew build

# Run tests
./gradlew test

# Run application
./gradlew run --args="input.jar output.jar"

# Create distribution
./gradlew shadowJar

📦 Dependencies

  • ASM (via ByteBuddy) — Bytecode manipulation
  • SnakeYAML — Configuration parsing
  • JUnit 5 — Testing

🤝 Contributing

Experimental obfuscator — contributions welcome! Focus is on improving reflection-based transformation techniques.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

MIT License — See LICENSE for details.

🙏 Acknowledgments

  • Built with ASM bytecode manipulation framework
  • Inspired by research into code transformation techniques
  • Thanks to the Java bytecode engineering community

🌫️ Mirage — Experimental Reflection-Based Obfuscator

Specialized obfuscation through reflection transformation. Not full-featured, but effective.

About

Is an experimental obfuscator that makes your Java bytecode harder to reverse engineer by replacing direct method calls and field accesses with reflection-based equivalents

Topics

Resources

License

Stars

Watchers

Forks

Languages