Adding an Obfuscator

SandMark is designed to make it easy to add a new obfuscation algorithm. Assume that we want to add a new obfuscation ReorderMethods. The process would be the following:
  1. Create a new directory sandmark/obfuscate/reorderMethods.
  2. Create a new class sandmark/obfuscate/reorderMethods/ReorderMethods.java.
  3. The ReorderMethods class should extend one of the base classes AppObfuscator (if the algorithm works on the entire user program), MethodObfuscator (if the algorithm works one method at a time), or ClassObfuscator (if the algorithm works on one individual class at a time). Let's assume that our algorithm reorders methods within one class. ReorderMethods should therefore extend ClassObfuscator, which looks like this:
    package sandmark.obfuscate;
    public abstract class ClassObfuscator extends GeneralObfuscator {
    protected ClassObfuscator(String label) {
        super(label);
    }
    abstract public void apply(
        sandmark.util.ClassFileCollection cfc, String classname)
        throws Exception;
    }
    public String toString() {
        return "ClassObfuscator(" + getLabel() + ")";
    }
    }
    
  4. The ReorderMethods class should look something like this:
    package sandmark.obfuscate.myobfuscator;
    public class MyObfuscator extends sandmark.obfuscate.ClassObfuscator {
    
       public MyObfuscator() {}
    
       public String getAuthor() {
          return "Jane Doe";
       }
    
       public String getAuthorEmail() {
          return "doe@cs.arizona.edu";
       }
    
       public String getDescription() {
          return "Turn all foos into bars by first turning them into yadas.";
       }
    
       public String getShortName() {
          return "BarMaker";
       }
    
       public String getLongName() {
          return "Turn foos into bars.";
       }
    
       public java.lang.String getAlgHTML() {
          return "...";
       }
    
       public java.lang.String getAlgURL() {
          return "sandmark/obfuscate/myobfuscator/doc/help.html";
       }
    
       public void apply(sandmark.program.Class cls) throws Exception {
          // Actual code goes here!
       }
    
    }
    
  5. Use BCEL to implement your obfuscation. The cls parameter represents the set of classes to be obfuscated. Use routines in sandmark.program.* to open a class to be edited by BCEL.
  6. Create a file sandmark/obfuscate/myobfuscator/doc/help.html documenting your work.
  7. Type make at the top-level sandmark directory (smark). The new obfuscation should be loaded automagically at runtime.

Example

Here is a real example of a simple obfuscator.
package sandmark.obfuscate.setfieldspublic;

/**
 * The SetFieldsPublic obfuscator changes the field access modifiers
 * of all of the fields in a class.
 @author         Christian Collberg
 @version        1.0
 */

public class SetFieldsPublic extends sandmark.obfuscate.ClassObfuscator {
   static int AND_MASK = ~(org.apache.bcel.Constants.ACC_PRIVATE
         | org.apache.bcel.Constants.ACC_PROTECTED);
   static int OR_MASK = org.apache.bcel.Constants.ACC_PUBLIC;

   /**
    *  Constructor.
    */
   public SetFieldsPublic() {}

   public String getAuthor() {
      return "Christian Collberg";
   }

   public String getAuthorEmail() {
      return "collberg@cs.arizona.edu";
   }

   public String getDescription() {
      return "Make all the fields and methods in a class public";
   }

   public sandmark.config.ModificationProperty[] getMutations() {
      return null;
   }

   public sandmark.config.RequisiteProperty[] getPostprohibited() {
      return new sandmark.config.RequisiteProperty[] {
         new sandmark.config.AlgorithmProperty(this)
      };
   }

   public String getShortName() {
      return "Publicize Fields";
   }

   public String getLongName() {
      return "Make all the fields/methods in this class public";
   }

   public java.lang.String getAlgHTML() {
      return "...";
   }

   public java.lang.String getAlgURL() {
      return "sandmark/obfuscate/setfieldspublic/doc/help.html";
   }

   /*************************************************************************/
   
   /* Embedding                               */
   
   /*************************************************************************/


   public void apply(sandmark.program.Class cls) throws Exception {
      sandmark.program.Field[] fields = cls.getFields();

      for (int i = 0; i < fields.length; i++) {
         fields[i].setAccessFlags((fields[i].getAccessFlags() & AND_MASK)
               | OR_MASK);	    
      }
      cls.mark();
   }

}