Paramorphism Logo

Paramorphism

A fast, modern obfuscator with support for Java 8 through 13, Kotlin, and other JVM languages.

Media

Here are some highlights that show how Paramorphism can conceal your intellectual property from reverse engineers:


Anti-Decompilation

With certain settings, Paramorphism becomes extremely effective at evading decompilation, through the use of nearly-malformed bytecode.

Paramorphism contains specific strategies against Lee Benfield's CFR, JetBrains' Fernflower, JD-GUI, Procyon, and Krakatau, as well as further generalised techniques designed to counter decompilation tools.

With CFR v0.148, a HelloWorld.class file created with javac produces the following output:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

Notice how almost the entire original source (not comments, obviously) can be recovered with a decompiler. It can even get the local variable and parameter names thanks to the JVM classfile format's LocalVariableTable attribute.

After obfuscation, this becomes:

public class a {
    /*
     * Exception decompiling
     */
    public a() {
        // This method has failed to decompile.  When submitting a bug report, please provide this stack trace, and (if you hold appropriate legal rights) the relevant class file.
        // org.benf.cfr.reader.util.ConfusedCFRException: Underrun type stack
        // org.benf.cfr.reader.bytecode.analysis.stack.StackSim.getEntry(StackSim.java:35)
        // org.benf.cfr.reader.bytecode.opcode.OperationFactoryDefault.getStackTypes(OperationFactoryDefault.java:55)
        // org.benf.cfr.reader.bytecode.opcode.OperationFactorySwap.getStackDelta(OperationFactorySwap.java:18)
        // org.benf.cfr.reader.bytecode.opcode.JVMInstr.getStackDelta(JVMInstr.java:315)
        // org.benf.cfr.reader.bytecode.analysis.opgraph.Op02WithProcessedDataAndRefs.populateStackInfo(Op02WithProcessedDataAndRefs.java:195)
        // org.benf.cfr.reader.bytecode.analysis.opgraph.Op02WithProcessedDataAndRefs.populateStackInfo(Op02WithProcessedDataAndRefs.java:1539)
        // org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisInner(CodeAnalyser.java:364)
        // org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisOrWrapFail(CodeAnalyser.java:238)
        // org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysis(CodeAnalyser.java:183)
        // org.benf.cfr.reader.entities.attributes.AttributeCode.analyse(AttributeCode.java:96)
        // org.benf.cfr.reader.entities.Method.analyse(Method.java:397)
        // org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:964)
        // org.benf.cfr.reader.entities.ClassFile.analyseTop(ClassFile.java:855)
        // org.benf.cfr.reader.Driver.doJarVersionTypes(Driver.java:242)
        // org.benf.cfr.reader.Driver.doJar(Driver.java:125)
        // org.benf.cfr.reader.CfrDriverImpl.analyse(CfrDriverImpl.java:65)
        // org.benf.cfr.reader.Main.main(Main.java:48)
        throw new IllegalStateException("Decompilation failed");
    }
    /*
     * Exception decompiling
     */
    public static void main(String[] var0) {
        // This method has failed to decompile.  When submitting a bug report, please provide this stack trace, and (if you hold appropriate legal rights) the relevant class file.
        // org.benf.cfr.reader.util.ConfusedCFRException: Underrun type stack
        // org.benf.cfr.reader.bytecode.analysis.stack.StackSim.getEntry(StackSim.java:35)
        // org.benf.cfr.reader.bytecode.opcode.OperationFactoryDefault.getStackTypes(OperationFactoryDefault.java:55)
        // org.benf.cfr.reader.bytecode.opcode.OperationFactorySwap.getStackDelta(OperationFactorySwap.java:18)
        // org.benf.cfr.reader.bytecode.opcode.JVMInstr.getStackDelta(JVMInstr.java:315)
        // org.benf.cfr.reader.bytecode.analysis.opgraph.Op02WithProcessedDataAndRefs.populateStackInfo(Op02WithProcessedDataAndRefs.java:195)
        // org.benf.cfr.reader.bytecode.analysis.opgraph.Op02WithProcessedDataAndRefs.populateStackInfo(Op02WithProcessedDataAndRefs.java:1539)
        // org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisInner(CodeAnalyser.java:364)
        // org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisOrWrapFail(CodeAnalyser.java:238)
        // org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysis(CodeAnalyser.java:183)
        // org.benf.cfr.reader.entities.attributes.AttributeCode.analyse(AttributeCode.java:96)
        // org.benf.cfr.reader.entities.Method.analyse(Method.java:397)
        // org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:964)
        // org.benf.cfr.reader.entities.ClassFile.analyseTop(ClassFile.java:855)
        // org.benf.cfr.reader.Driver.doJarVersionTypes(Driver.java:242)
        // org.benf.cfr.reader.Driver.doJar(Driver.java:125)
        // org.benf.cfr.reader.CfrDriverImpl.analyse(CfrDriverImpl.java:65)
        // org.benf.cfr.reader.Main.main(Main.java:48)
        throw new IllegalStateException("Decompilation failed");
    }
}

At the same level of obfuscation, many off-the-shelf decompilation tools are unable to open the JAR file:


Configuration and the CLI

Paramorphism is a configuration-based CLI application. This means that no GUI is required to use the obfuscator. Simply write a config file, run the JAR, and your obfuscated output will pop into existence. Plus, using the public API, automated behaviour is easy!


Features

Paramorphism comes with all standard Java obfuscation features:

  • Automatic renaming of classes, methods, and fields
  • Cryptographic string concealment
  • Control flow graph mangling
  • External call concealment

The obfuscator also contains specific obfuscation strategies tailored for Kotlin, as the Kotlin compiler leaves behind custom debugging information that can be used for deobfuscation of the target program.


What's in a Name?

In geology, a paramorphism is a change in the physical structure of a mineral without any chemical change.

The Paramorphism obfuscator is analogous, as it aims to change the internal structure of a program (to make it less easily readable) without any changes to its semantics.