diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index a1f5a731c8..21643ea391 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -1,8 +1,6 @@ package net.runelite.deob; import net.runelite.deob.deobfuscators.FieldInliner; -import net.runelite.deob.deobfuscators.FieldMover; -import net.runelite.deob.deobfuscators.MethodMover; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; @@ -18,6 +16,7 @@ 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.Rename; import net.runelite.deob.deobfuscators.RenameUnique; import net.runelite.deob.deobfuscators.RuntimeExceptions; import net.runelite.deob.deobfuscators.UnreachedCode; @@ -35,6 +34,8 @@ public class Deob { public static void main(String[] args) throws IOException { + //merge(); if(true) return; + long start = System.currentTimeMillis(); ClassGroup group = loadJar(args[0]); @@ -70,9 +71,10 @@ public class Deob // // // remove unused methods, again? // run(group, new UnusedMethods()); -// -// run(group, new MethodInliner()); -// + + run(group, new MethodInliner()); + // now remove unused methods? + // // broken because rename was removed // //run(group, new MethodMover()); // @@ -83,28 +85,28 @@ public class Deob // //new FieldMover().run(group); // // run(group, new UnusedClass()); - - ModArith mod = new ModArith(); - mod.run(group); - - int last = -1, cur; - while ((cur = mod.runOnce()) > 0) - { - new MultiplicationDeobfuscator().run(group); - - new MultiplyOneDeobfuscator().run(group); - - new MultiplyZeroDeobfuscator().run(group); - - if (last == cur) - { - System.out.println("break"); - break; - } - - last = cur; - //break; - } +// +// ModArith mod = new ModArith(); +// mod.run(group); +// +// int last = -1, cur; +// while ((cur = mod.runOnce()) > 0) +// { +// new MultiplicationDeobfuscator().run(group); +// +// new MultiplyOneDeobfuscator().run(group); +// +// new MultiplyZeroDeobfuscator().run(group); +// +// if (last == cur) +// { +// System.out.println("break"); +// break; +// } +// +// last = cur; +// //break; +// } // eval constant fields (only set once to a constant in ctor) maybe just inline them @@ -116,6 +118,15 @@ public class Deob System.out.println("Done in " + ((end - start) / 1000L) + "s"); } + private static void merge() throws IOException + { + ClassGroup group1 = loadJar("d:/rs/07/adamin1.jar"), + group2 = loadJar("d:/rs/07/adamin2.jar"); + + Rename rename = new Rename(); + rename.run(group1, group2); + } + public static boolean isObfuscated(String name) { return name.length() <= 2 || name.startsWith("method") || name.startsWith("vmethod") || name.startsWith("field") || name.startsWith("class"); diff --git a/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java b/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java index ec965f7f36..17f1325aac 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java +++ b/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java @@ -30,7 +30,7 @@ import net.runelite.deob.attributes.code.Exceptions; public class MethodInliner implements Deobfuscator { private Map calls = new HashMap<>(); - private Set removeMethods = new HashSet<>(); + //private Set removeMethods = new HashSet<>(); private void countCalls(Method m) { @@ -72,6 +72,7 @@ public class MethodInliner implements Deobfuscator for (Instruction i : ins.getInstructions()) { + assert i.getInstructions() == ins; // can only inline static method calls if (!(i instanceof InvokeStatic)) continue; @@ -82,14 +83,18 @@ public class MethodInliner implements Deobfuscator Method invokedMethod = invokedMethods.get(0); Integer count = calls.get(invokedMethod); + + if (count == null || invokedMethod.getCode().getInstructions().getInstructions().size() > 30) + continue; +// if (count == null || count != 1) +// continue; // only inline methods called once - if (count == null || count != 1) - continue; // only inline methods called once - - assert m != invokedMethod; + if (m == invokedMethod) + continue; // recursive method int invokeIdx = ins.getInstructions().indexOf(i); assert invokeIdx != -1; + assert ins.getInstructions().get(invokeIdx).getInstructions() == ins.getInstructions(); int lvtIndex = code.getMaxLocals(), //startLvtIndex = lvtIndex, @@ -178,6 +183,7 @@ public class MethodInliner implements Deobfuscator invokeMethodInstructions = invokeMethodCode.getInstructions(); int idx = methodInstructions.getInstructions().indexOf(invokeIns); // index of invoke ins, before removal + assert invokeIns.getInstructions() == methodInstructions; assert idx != -1; Instruction nextInstruction = methodInstructions.getInstructions().get(idx + 1); @@ -274,8 +280,8 @@ public class MethodInliner implements Deobfuscator } // old method goes away - invokeMethodInstructions.getInstructions().clear(); - removeMethods.add(invokeMethod); + //invokeMethodInstructions.getInstructions().clear(); + //removeMethods.add(invokeMethod); } private void moveExceptions(Method to, Method from) @@ -312,7 +318,7 @@ public class MethodInliner implements Deobfuscator int count = 0; calls.clear(); - removeMethods.clear(); + //removeMethods.clear(); for (ClassFile cf : group.getClasses()) { @@ -329,9 +335,9 @@ public class MethodInliner implements Deobfuscator count += processMethod(m); } } - - for (Method m : removeMethods) - m.getMethods().removeMethod(m); +// +// for (Method m : removeMethods) +// m.getMethods().removeMethod(m); System.out.println("Inlined " + count + " methods"); return count; diff --git a/src/main/java/net/runelite/deob/deobfuscators/Rename.java b/src/main/java/net/runelite/deob/deobfuscators/Rename.java new file mode 100644 index 0000000000..dd35ca5486 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/Rename.java @@ -0,0 +1,74 @@ +package net.runelite.deob.deobfuscators; + +import java.util.List; +import java.util.stream.Collectors; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.instruction.types.ComparisonInstruction; +import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; +import net.runelite.deob.attributes.code.instruction.types.LVTInstruction; +import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; +import net.runelite.deob.execution.Execution; +import net.runelite.deob.execution.Frame; + +public class Rename +{ + private static boolean isExpressionInstruction(Instruction in) + { + return + in instanceof SetFieldInstruction || + (in instanceof LVTInstruction && ((LVTInstruction) in).store()) || + in instanceof InvokeInstruction || + in instanceof ComparisonInstruction; + } + + private static List getExprIns(Frame frame) + { + return frame.getInstructions().stream().map(i -> i.getInstruction()).filter(i -> isExpressionInstruction(i)).collect(Collectors.toList()); + } + + private static boolean equalsFrames(Frame one, Frame two) + { + List oneIns = getExprIns(one), + twoIns = getExprIns(two); + + if (oneIns.size() != twoIns.size() || oneIns.isEmpty()) + return false; + + for (int i = 0; i < oneIns.size(); ++i) + { + Instruction i1 = oneIns.get(i), + i2 = twoIns.get(i); + + if (i1.getType() != i2.getType()) + return false; + } + + if (one.getMethod().getName().startsWith("method") && two.getMethod().getName().startsWith("method")) + { + int i =5; + } + return true; + } + + public void run(ClassGroup one, ClassGroup two) + { + Execution ex1 = new Execution(one); + ex1.populateInitialMethods(); + ex1.run(); + + Execution ex2 = new Execution(two); + ex2.populateInitialMethods(); + ex2.run(); + + for (Frame f : ex1.processedFrames) + for (Frame f2 : ex2.processedFrames) + { + if (f.getMethod().getName().equals("vmethod2976") && f2.getMethod().getName().equals("vmethod2973")) + { + if (equalsFrames(f, f2)) + System.out.println(f.getMethod().getName() + " " + f2.getMethod().getName()); + } + } + } +}