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.

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 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 Vector buffer = new Vector();

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

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

package a;

import java.util.Vector;

class a {

    private Vector a;
    public static int b;

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

    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.elementAt(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:
    }
}