Zelix KlassMaster - Java Obfuscator

Java Flow Obfuscation

A second generation Java obfuscator performs flow obfuscation in addition to name obfuscation. It makes slight changes to the bytecode that obscure the control flow without changing what the code does at runtime. Typically, selection (eg. if...else...) and looping constructs (eg. while and for loops) are changed so that they no longer have a direct Java source code equivalent. Flow obfuscated bytecode typically forces decompilers to inset a series of labels and illegal goto statements into the source code they produce. The source code is sometimes further obscured by decompiler errors.

As well as the standard Flow Obfuscation, Zelix KlassMaster™ can also perform Flow Obfuscation making use of the Method Parameter Changes functionality. You can use either approach or both together.

Other obfuscators claim to perform flow obfuscation but, in reality, they only make a token effort. Zelix KlassMaster™ was the first true second generation, heavy duty Java obfuscator and its flow obfuscation remains unmatched. See the very simple examples below. Note that the appearance of your flow obfuscated code after decompilation will vary depending on the decompiler used.

Original Source Next Section

package test;

import java.util.*;

class Demo {

   private List list = new ArrayList<>();

   /**
   * Return the position of the specified String
   * in the list. Remove the String once if it
   * has been found. Return -1 if the String
   * isn't found. */
   int getStringPos(String string) {
      for(int ctr=0; ctr < list.size(); ctr++) {
         String curString = list.get(ctr);
         if (curString.equals(string)) {
            list.remove(ctr);
            return ctr;
         }
      }
      return -1;
   }
}

Name and Flow obfuscated (2nd Generation Obfuscation) then decompiled First Section

package a;

import java.util.*;

class a {

    private List a;
    public static int b;

    a() {
        a = new ArrayList();
    }

    int a(String s) {
        int i;
        int j;
        j = b;
        i = 0;
        if(j == 0) goto _L2; else goto _L1
_L1:
        String s1 = (String)a.get(i);
        s1.equals(s);
        if(j != 0) goto _L4; else goto _L3
_L3:
        JVM INSTR ifeq 48;
           goto _L5 _L6
_L5:
        break MISSING_BLOCK_LABEL_37;
_L6:
        continue;
        a.remove(i);
        i;
_L4:
        return;
_L2:
        if(i >= a.size())
            return -1;
        if(true) goto _L1; else goto _L7
_L7:
    }
}