diff --git a/src/main/java/net/runelite/deob/ClassGroup.java b/src/main/java/net/runelite/deob/ClassGroup.java index b6533e13fe..b9f29f0aa0 100644 --- a/src/main/java/net/runelite/deob/ClassGroup.java +++ b/src/main/java/net/runelite/deob/ClassGroup.java @@ -20,6 +20,11 @@ public class ClassGroup return cf; } + public void removeClass(ClassFile cf) + { + classes.remove(cf); + } + public List getClasses() { return classes; diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index e257169337..2a7d7fd37e 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -15,6 +15,15 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; +import net.runelite.deob.deobfuscators.ConstantParameter; +import net.runelite.deob.deobfuscators.IllegalStateExceptions; +import net.runelite.deob.deobfuscators.MethodInliner; +import net.runelite.deob.deobfuscators.RuntimeExceptions; +import net.runelite.deob.deobfuscators.UnreachedCode; +import net.runelite.deob.deobfuscators.UnusedClass; +import net.runelite.deob.deobfuscators.UnusedFields; +import net.runelite.deob.deobfuscators.UnusedMethods; +import net.runelite.deob.deobfuscators.UnusedParameters; //move static methods //move static fields @@ -37,70 +46,72 @@ public class Deob // bdur = System.currentTimeMillis() - bstart; // System.out.println("rename unique took " + bdur/1000L + " seconds"); -// // remove except RuntimeException -// bstart = System.currentTimeMillis(); -// new RuntimeExceptions().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("runtime exception took " + bdur/1000L + " seconds"); -// -// // remove unused methods -// bstart = System.currentTimeMillis(); -// new UnusedMethods().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused methods took " + bdur/1000L + " seconds"); -// -// new UnreachedCode().run(group); -// -// // remove illegal state exceptions, frees up some parameters -// bstart = System.currentTimeMillis(); -// new IllegalStateExceptions().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("illegal state exception took " + bdur/1000L + " seconds"); -// -// // remove constant logically dead parameters -// bstart = System.currentTimeMillis(); -// new ConstantParameter().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("constant param took " + bdur/1000L + " seconds"); -// -// // remove unhit blocks -// bstart = System.currentTimeMillis(); -// new UnreachedCode().run(group); -// //new UnusedBlocks().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused blocks took " + bdur/1000L + " seconds"); -// -// // remove unused parameters -// bstart = System.currentTimeMillis(); -// new UnusedParameters().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused params took " + bdur/1000L + " seconds"); -// -// // remove jump obfuscation -// //new Jumps().run(group); -// -// // remove unused fields -// bstart = System.currentTimeMillis(); -// new UnusedFields().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused fields took " + bdur/1000L + " seconds"); -// -// // remove unused methods, again? -// bstart = System.currentTimeMillis(); -// new UnusedMethods().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused methods took " + bdur/1000L + " seconds"); -// -// -// new MethodInliner().run(group); + // remove except RuntimeException + bstart = System.currentTimeMillis(); + new RuntimeExceptions().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("runtime exception took " + bdur/1000L + " seconds"); + + // remove unused methods + bstart = System.currentTimeMillis(); + new UnusedMethods().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused methods took " + bdur/1000L + " seconds"); + + new UnreachedCode().run(group); + + // remove illegal state exceptions, frees up some parameters + bstart = System.currentTimeMillis(); + new IllegalStateExceptions().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("illegal state exception took " + bdur/1000L + " seconds"); + + // remove constant logically dead parameters + bstart = System.currentTimeMillis(); + new ConstantParameter().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("constant param took " + bdur/1000L + " seconds"); + + // remove unhit blocks + bstart = System.currentTimeMillis(); + new UnreachedCode().run(group); + //new UnusedBlocks().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused blocks took " + bdur/1000L + " seconds"); + + // remove unused parameters + bstart = System.currentTimeMillis(); + new UnusedParameters().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused params took " + bdur/1000L + " seconds"); + + // remove jump obfuscation + //new Jumps().run(group); + + // remove unused fields + bstart = System.currentTimeMillis(); + new UnusedFields().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused fields took " + bdur/1000L + " seconds"); + + // remove unused methods, again? + bstart = System.currentTimeMillis(); + new UnusedMethods().run(group); + bdur = System.currentTimeMillis() - bstart; + System.out.println("unused methods took " + bdur/1000L + " seconds"); + + + new MethodInliner().run(group); // new ModularArithmeticDeobfuscation().run(group); -// new MethodMover().run(group); -// -// new FieldMover().run(group); + new MethodMover().run(group); + + new FieldMover().run(group); new FieldInliner().run(group); + + new UnusedClass().run(group); saveJar(group, args[1]); diff --git a/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java b/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java index 4ba592ff12..21eede3495 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java +++ b/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java @@ -1,5 +1,6 @@ package net.runelite.deob.deobfuscators; +import java.util.ArrayList; import net.runelite.deob.ClassFile; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; @@ -10,10 +11,13 @@ import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; import net.runelite.deob.pool.NameAndType; import java.util.Collection; +import java.util.List; import org.apache.commons.collections4.map.MultiValueMap; public class FieldMover implements Deobfuscator { + private static final String mainClass = "client"; + private ClassGroup group; private MultiValueMap fields = new MultiValueMap<>(); @@ -57,6 +61,46 @@ public class FieldMover implements Deobfuscator } } + private boolean isDowncastable(ClassFile from, ClassFile to) + { + while (from != null && from != to) + { + from = from.getParent(); + } + + return from != null; + } + + private ClassFile getBase(ClassFile one, ClassFile two) + { + if (one == two) + return one; + + if (isDowncastable(one, two)) + return two; + + if (isDowncastable(two, one)) + return one; + + return null; + } + + private ClassFile findCommonBase(Collection classes) + { + List list = new ArrayList<>(classes); + + if (list.size() == 1) + return list.get(0); + +// ClassFile cf = getBase(list.get(0), list.get(1)); +// +// for (int i = 2; i < list.size(); ++i) +// cf = getBase(cf, list.get(i)); +// +// return cf; + return null; // to do this, would have to move static initializer + } + private int moveFields() { int count = 0; @@ -65,18 +109,18 @@ public class FieldMover implements Deobfuscator { Collection cfs = fields.getCollection(field); - if (cfs.size() != 1) - { - // XXX clinit + ClassFile to = findCommonBase(cfs); + if (to == null) continue; - } + // no common base, move to entry class + //to = group.findClass(mainClass); - ClassFile cf = cfs.iterator().next(); + assert to != null; - if (field.getFields().getClassFile() == cf) + if (field.getFields().getClassFile() == to) continue; - moveField(field, cf); + moveField(field, to); ++count; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/UnusedClass.java b/src/main/java/net/runelite/deob/deobfuscators/UnusedClass.java new file mode 100644 index 0000000000..5c319acc43 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/UnusedClass.java @@ -0,0 +1,28 @@ +package net.runelite.deob.deobfuscators; + +import java.util.ArrayList; +import net.runelite.deob.ClassFile; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Deobfuscator; + +public class UnusedClass implements Deobfuscator +{ + @Override + public void run(ClassGroup group) + { + int count = 0; + for (ClassFile cf : new ArrayList<>(group.getClasses())) + { + if (!cf.getFields().getFields().isEmpty()) + continue; + + if (!cf.getMethods().getMethods().isEmpty()) + continue; + + group.removeClass(cf); + ++count; + } + System.out.println("Removed " + count + " classes"); + } + +} diff --git a/src/main/java/net/runelite/deob/deobfuscators/UnusedMethods.java b/src/main/java/net/runelite/deob/deobfuscators/UnusedMethods.java index 34e9357139..aa2b333fd3 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/UnusedMethods.java +++ b/src/main/java/net/runelite/deob/deobfuscators/UnusedMethods.java @@ -14,7 +14,7 @@ public class UnusedMethods implements Deobfuscator @Override public void run(ClassGroup group) { - group.buildClassGraph(); // does this use this? + group.buildClassGraph(); Execution execution = new Execution(group); execution.populateInitialMethods(); @@ -25,7 +25,7 @@ public class UnusedMethods implements Deobfuscator { for (Method m : new ArrayList<>(cf.getMethods().getMethods())) { - if (!Deob.isObfuscated(m.getName())) + if (!Deob.isObfuscated(m.getName()) && !m.getName().equals("")) continue; if (!execution.methods.contains(m)) diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index c8966f6dba..9cfad7e2a7 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -31,7 +31,7 @@ public class Execution { for (Method m : cf.getMethods().getMethods()) { - if (!Deob.isObfuscated(m.getName())) + if (!Deob.isObfuscated(m.getName()) && !m.getName().equals("")) { addMethod(m); // I guess this method name is overriding a jre interface (init, run, ?). }