package net.contra.obfuscator.trans.ob; import com.sun.org.apache.bcel.internal.classfile.Method; import com.sun.org.apache.bcel.internal.generic.ClassGen; import com.sun.org.apache.bcel.internal.generic.InstructionHandle; import com.sun.org.apache.bcel.internal.generic.InstructionList; import com.sun.org.apache.bcel.internal.generic.MethodGen; import net.contra.obfuscator.ITransformer; import net.contra.obfuscator.Settings; import net.contra.obfuscator.util.bcel.BCELMethods; import net.contra.obfuscator.util.bcel.JarLoader; import net.contra.obfuscator.util.misc.LogHandler; import net.contra.obfuscator.util.misc.Misc; import net.contra.obfuscator.util.misc.RenamedPair; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class MethodNameObfuscator implements ITransformer { private final LogHandler Logger = new LogHandler("MethodNameObfuscator"); //ClassName, <OldSig, NewSig> private final Map<String, ArrayList<RenamedPair>> ChangedMethods = new HashMap<String, ArrayList<RenamedPair>>(); private String Location = ""; private JarLoader LoadedJar; public MethodNameObfuscator(String loc) { Location = loc; } public void load() { LoadedJar = new JarLoader(Location); } public void transform() { //We rename methods for (ClassGen cg : LoadedJar.ClassEntries.values()) { ArrayList<RenamedPair> NewClassMethods = new ArrayList<RenamedPair>(); if (cg.isAbstract()) continue; //TODO: Probably more shit we shouldn't rename for (Method method : cg.getMethods()) { if (method.isInterface() || method.isAbstract() || method.getName().endsWith("init>") || method.getName().equals("main")) continue; //TODO: Probably more shit we shouldn't rename MethodGen mg = new MethodGen(method, cg.getClassName(), cg.getConstantPool()); String newName = Misc.getRandomName(); mg.setName(newName); cg.replaceMethod(method, mg.getMethod()); RenamedPair pair = new RenamedPair(method.getName(), method.getSignature(), mg.getName()); NewClassMethods.add(pair); Logger.log("Obfuscating Method Names -> Class: " + cg.getClassName() + " Method: " + method.getName()); } ChangedMethods.put(cg.getClassName(), NewClassMethods); } //We fix all of the method calls for (ClassGen cg : LoadedJar.ClassEntries.values()) { for (Method method : cg.getMethods()) { MethodGen mg = new MethodGen(method, cg.getClassName(), cg.getConstantPool()); InstructionList list = mg.getInstructionList(); if (list == null) continue; Logger.log("Fixing Method Calls -> Class: " + cg.getClassName() + " Method: " + method.getName()); InstructionHandle[] handles = list.getInstructionHandles(); for (InstructionHandle handle : handles) { if (BCELMethods.isInvoke(handle.getInstruction())) { String clazz = BCELMethods.getInvokeClassName(handle.getInstruction(), cg.getConstantPool()).trim(); String methname = BCELMethods.getInvokeMethodName(handle.getInstruction(), cg.getConstantPool()).trim(); String methsig = BCELMethods.getInvokeSignature(handle.getInstruction(), cg.getConstantPool()).trim(); if (!ChangedMethods.containsKey(clazz)) continue; for (RenamedPair pair : ChangedMethods.get(clazz)) { if (pair.OldName.equals(methname) && pair.OldSignature.equals(methsig)) { int index = cg.getConstantPool().addMethodref(clazz, pair.NewName, pair.OldSignature); handle.setInstruction(BCELMethods.getNewInvoke(handle.getInstruction(), index)); } } } } list.setPositions(); mg.setInstructionList(list); mg.setMaxLocals(); mg.setMaxStack(); cg.replaceMethod(method, mg.getMethod()); } } } public void save() { String loc = Location.replace(".jar", Settings.FILE_TAG + ".jar"); LoadedJar.saveJar(loc); } }