From 804b34d0753c7bcadbc325aedfdd9144ae811842 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 19 Nov 2015 16:32:19 -0500 Subject: [PATCH] hm --- pom.xml | 8 +- src/main/java/net/runelite/deob/Deob.java | 6 +- src/main/java/net/runelite/deob/Method.java | 10 + .../deob/deobfuscators/rename/Rename.java | 462 +++++++++--------- .../deob/deobfuscators/rename/Rename2.java | 162 ++++++ .../deob/deobfuscators/rename/graph/Edge.java | 64 +++ .../deobfuscators/rename/graph/Graph.java | 79 +++ .../deobfuscators/rename/graph/Vertex.java | 174 +++++++ .../rename/graph/VertexType.java | 8 + .../runelite/deob/execution/Execution.java | 83 +++- .../net/runelite/deob/execution/Frame.java | 85 ++-- .../net/runelite/deob/execution/MIKey.java | 51 -- .../deob/execution/MethodContext.java | 186 +++---- .../runelite/deob/signature/Signature.java | 10 + .../runelite/deob/execution/FrameTest.java | 267 +++++----- 15 files changed, 1069 insertions(+), 586 deletions(-) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java create mode 100644 src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java create mode 100644 src/main/java/net/runelite/deob/deobfuscators/rename/graph/Graph.java create mode 100644 src/main/java/net/runelite/deob/deobfuscators/rename/graph/Vertex.java create mode 100644 src/main/java/net/runelite/deob/deobfuscators/rename/graph/VertexType.java delete mode 100644 src/main/java/net/runelite/deob/execution/MIKey.java diff --git a/pom.xml b/pom.xml index 4b58e1d18a..efb5165e6e 100644 --- a/pom.xml +++ b/pom.xml @@ -24,21 +24,21 @@ commons-compress 1.10 - + com.google.code.gson gson 2.4 - + org.slf4j diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 53cba01fa9..0fe33c9981 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -3,12 +3,14 @@ package net.runelite.deob; import java.io.File; import java.io.IOException; import net.runelite.deob.deobfuscators.MethodInliner; -import net.runelite.deob.deobfuscators.rename.Rename; import net.runelite.deob.deobfuscators.UnusedMethods; +import net.runelite.deob.deobfuscators.rename.Rename2; import net.runelite.deob.execution.Execution; import net.runelite.deob.util.JarUtil; // XXX something to detect final fields and evaluate them +// the problem is static functions which dup, +// graph of method/field (not include static) relationships public class Deob { @@ -103,7 +105,7 @@ public class Deob ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")), group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar")); - Rename rename = new Rename(); + Rename2 rename = new Rename2(); rename.run(group1, group2); } diff --git a/src/main/java/net/runelite/deob/Method.java b/src/main/java/net/runelite/deob/Method.java index 96943360d9..adfe22ba28 100644 --- a/src/main/java/net/runelite/deob/Method.java +++ b/src/main/java/net/runelite/deob/Method.java @@ -17,8 +17,13 @@ import java.util.List; public class Method { + public static final int ACC_PUBLIC = 0x1; + public static final int ACC_PRIVATE = 0x2; + public static final int ACC_PROTECTED = 0x4; public static final int ACC_STATIC = 0x8; + public static final int ACC_FINAL = 0x10; public static final int ACC_SYNCHRONIZED = 0x20; + public static final int ACC_ABSTRACT = 0x400; private Methods methods; @@ -79,6 +84,11 @@ public class Method { this.attributes = a; } + + public short getAccessFlags() + { + return accessFlags; + } public String getName() { diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java index e9acade0db..ccb8072e7e 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename.java @@ -1,246 +1,246 @@ -package net.runelite.deob.deobfuscators.rename; - -import edu.ucla.sspace.graph.Edge; -import edu.ucla.sspace.graph.Graph; -import edu.ucla.sspace.graph.isomorphism.IsomorphismTester; -import edu.ucla.sspace.graph.isomorphism.VF2IsomorphismTester; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import net.runelite.deob.ClassGroup; -import net.runelite.deob.Method; -import net.runelite.deob.execution.Execution; -import net.runelite.deob.execution.Frame; -import net.runelite.deob.execution.MethodContext; - -public class Rename -{ - private ClassGroup groupOne, groupTwo; - - // respective executions - //private Execution eone, etwo; - - // old -> new object mapping - private Map objMap = new HashMap<>(); - - // methods which have been processed in the original - private Set processed = new HashSet<>(); - - private static String cname(Method m) { return m.getMethods().getClassFile().getName(); } - private static String mname(Method m) { return cname(m) + "." + m.getName(); } - - private void compare(MethodContext m1, Graph g1, MethodContext m2, Graph g2) - { - Set edges = new HashSet<>(g1.edges()); // edges in g1 not in g2 - for (Edge e : (Set) g2.edges()) - { - edges.remove(e); - } - - for (Edge e : edges) - { - Method me1 = m1.getIdMap().get(e.from()).get(0); - Method me2 = m1.getIdMap().get(e.to()).get(0); - - System.out.println("EDGE IN 1 NOT IN 2: " + mname(me1) + " -> " + mname(me2)); - - Method om1 = m2.getIdMap().get(e.from()).get(0); - Method om2 = m2.getIdMap().get(e.to()).get(0); - - System.out.println(" OTHER SIDE: " + mname(om1) + " -> " + mname(om2)); - } - //System.out.println(edges); - - if (g2.order() == g1.order()) - { - int[] v1 = g1.vertices().toPrimitiveArray(), - v2 = g2.vertices().toPrimitiveArray(); - for (int i = 0; i < g1.order(); ++i) - { - Method me1 = m1.getIdMap().get(v1[i]).get(0); - Method me2 = m2.getIdMap().get(v2[i]).get(0); - - System.out.println("VMATCH " + mname(me1) + " -> " + mname(me2)); - } - } - } - - private boolean compare(Frame f1, Frame f2) - { - Graph g1 = f1.getMethodCtx().getGraph(), g2 = f2.getMethodCtx().getGraph(); - - IsomorphismTester isoTest = new /*Typed*/VF2IsomorphismTester(); - if (g1.size() != g2.size() || g1.order() != g2.order() || !isoTest.areIsomorphic(g1, g2)) - { - System.out.println("IN " + mname(f1.getMethod()) + " -> " + mname(f2.getMethod())); - compare(f1.getMethodCtx(), g1, f2.getMethodCtx(), g2); - System.out.println("Not isomorphic " + g1.size() + " " + g2.size()); - return false; - } - - Map mapping = isoTest.findIsomorphism(g1, g2); - Map> map1 = f1.getMethodCtx().getIdMap(), map2 = f2.getMethodCtx().getIdMap(); - - for (Entry e : mapping.entrySet()) - { -// if (e.getKey() == null || e.getValue() == null) +//package net.runelite.deob.deobfuscators.rename; +// +//import edu.ucla.sspace.graph.Edge; +//import edu.ucla.sspace.graph.Graph; +//import edu.ucla.sspace.graph.isomorphism.IsomorphismTester; +//import edu.ucla.sspace.graph.isomorphism.VF2IsomorphismTester; +//import java.util.HashMap; +//import java.util.HashSet; +//import java.util.List; +//import java.util.Map; +//import java.util.Map.Entry; +//import java.util.Optional; +//import java.util.Set; +//import java.util.stream.Collectors; +//import net.runelite.deob.ClassGroup; +//import net.runelite.deob.Method; +//import net.runelite.deob.execution.Execution; +//import net.runelite.deob.execution.Frame; +//import net.runelite.deob.execution.MethodContext; +// +//public class Rename +//{ +// private ClassGroup groupOne, groupTwo; +// +// // respective executions +// //private Execution eone, etwo; +// +// // old -> new object mapping +// private Map objMap = new HashMap<>(); +// +// // methods which have been processed in the original +// private Set processed = new HashSet<>(); +// +// private static String cname(Method m) { return m.getMethods().getClassFile().getName(); } +// private static String mname(Method m) { return cname(m) + "." + m.getName(); } +// +// private void compare(MethodContext m1, Graph g1, MethodContext m2, Graph g2) +// { +// Set edges = new HashSet<>(g1.edges()); // edges in g1 not in g2 +// for (Edge e : (Set) g2.edges()) +// { +// edges.remove(e); +// } +// +// for (Edge e : edges) +// { +// Method me1 = m1.getIdMap().get(e.from()).get(0); +// Method me2 = m1.getIdMap().get(e.to()).get(0); +// +// System.out.println("EDGE IN 1 NOT IN 2: " + mname(me1) + " -> " + mname(me2)); +// +// Method om1 = m2.getIdMap().get(e.from()).get(0); +// Method om2 = m2.getIdMap().get(e.to()).get(0); +// +// System.out.println(" OTHER SIDE: " + mname(om1) + " -> " + mname(om2)); +// } +// //System.out.println(edges); +// +// if (g2.order() == g1.order()) +// { +// int[] v1 = g1.vertices().toPrimitiveArray(), +// v2 = g2.vertices().toPrimitiveArray(); +// for (int i = 0; i < g1.order(); ++i) // { -// assert e.getKey() == e.getValue(); -// continue; +// Method me1 = m1.getIdMap().get(v1[i]).get(0); +// Method me2 = m2.getIdMap().get(v2[i]).get(0); +// +// System.out.println("VMATCH " + mname(me1) + " -> " + mname(me2)); // } - - List i1 = map1.get(e.getKey()); - List i2 = map2.get(e.getValue()); - - //assert i1.getClass() == i2.getClass(); - - //InvokeInstruction ii1 = (InvokeInstruction) i1, ii2 = (InvokeInstruction) i2; - - //assert ii1.getMethods().size() == ii2.getMethods().size(); - - assert i1.size() == i2.size(); - - for (int i = 0; i < i1.size(); ++i) - { - Method m1 = i1.get(i), m2 = i2.get(i); - -// assert objMap.containsKey(m1) == false || objMap.get(m1) == m2; - objMap.put(m1, m2); - } - - System.out.println("MATCH " + i1.get(0).getName() + " -> " + i2.get(0).getName()); - } - - return true; - } - - private void process(Method one, Method two) - { - Execution eone = new Execution(groupOne); - eone.setBuildGraph(true); - eone.setFollowInvokes(false); - eone.addMethod(one); - eone.run(); - - Execution etwo = new Execution(groupTwo); - etwo.setBuildGraph(true); - etwo.setFollowInvokes(false); - etwo.addMethod(two); - etwo.run(); - - // get frames for respective methods - List f1 = eone.processedFrames, f2 = etwo.processedFrames; - - f1 = f1.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList()); - f2 = f2.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList()); - - //List f1 = eone.processedFrames.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList()); - //List f2 = etwo.processedFrames.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList()); - - Frame p1 = null, p2 = null; - outer: - for (Frame fr1 : f1) - for (Frame fr2 : f2) - { - if (p1 == null) p1 = fr1; - if (p2 == null) p2 = fr2; - - assert fr1.getMethod() == one; - assert fr2.getMethod() == two; - - assert fr1.getMethodCtx() == p1.getMethodCtx(); - assert fr2.getMethodCtx() == p2.getMethodCtx(); - } - - assert p1.getMethod() == one; - assert p2.getMethod() == two; - - outer2: - for (Frame fr1 : f1) - for (Frame fr2 : f2) - { - boolean b = compare(fr1, fr2); - if (!b) - { - System.out.println("Mismatch " + p1.getMethod().getMethods().getClassFile().getName() + "." + p1.getMethod().getName() + " <-> " + p2.getMethod().getMethods().getClassFile().getName() + "." + p2.getMethod().getName()); - System.out.println(one.getMethods().getClassFile().getName() + "." + one.getName() + " and " + two.getMethods().getClassFile().getName() + "." + two.getName()); - int i =7; - } - break outer2; - } - - System.out.println("end"); - } - public void run(ClassGroup one, ClassGroup two) - { - groupOne = one; - groupTwo = two; - -// Execution eone = new Execution(one); +// } +// } +// +// private boolean compare(Frame f1, Frame f2) +// { +// Graph g1 = f1.getMethodCtx().getGraph(), g2 = f2.getMethodCtx().getGraph(); +// +// IsomorphismTester isoTest = new /*Typed*/VF2IsomorphismTester(); +// if (g1.size() != g2.size() || g1.order() != g2.order() || !isoTest.areIsomorphic(g1, g2)) +// { +// System.out.println("IN " + mname(f1.getMethod()) + " -> " + mname(f2.getMethod())); +// compare(f1.getMethodCtx(), g1, f2.getMethodCtx(), g2); +// System.out.println("Not isomorphic " + g1.size() + " " + g2.size()); +// return false; +// } +// +// Map mapping = isoTest.findIsomorphism(g1, g2); +// Map> map1 = f1.getMethodCtx().getIdMap(), map2 = f2.getMethodCtx().getIdMap(); +// +// for (Entry e : mapping.entrySet()) +// { +//// if (e.getKey() == null || e.getValue() == null) +//// { +//// assert e.getKey() == e.getValue(); +//// continue; +//// } +// +// List i1 = map1.get(e.getKey()); +// List i2 = map2.get(e.getValue()); +// +// //assert i1.getClass() == i2.getClass(); +// +// //InvokeInstruction ii1 = (InvokeInstruction) i1, ii2 = (InvokeInstruction) i2; +// +// //assert ii1.getMethods().size() == ii2.getMethods().size(); +// +// assert i1.size() == i2.size(); +// +// for (int i = 0; i < i1.size(); ++i) +// { +// Method m1 = i1.get(i), m2 = i2.get(i); +// +//// assert objMap.containsKey(m1) == false || objMap.get(m1) == m2; +// objMap.put(m1, m2); +// } +// +// System.out.println("MATCH " + i1.get(0).getName() + " -> " + i2.get(0).getName()); +// } +// +// return true; +// } +// +// private void process(Method one, Method two) +// { +// Execution eone = new Execution(groupOne); // eone.setBuildGraph(true); // eone.setFollowInvokes(false); -// eone.populateInitialMethods(); -// List initial1 = eone.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList()); +// eone.addMethod(one); // eone.run(); // -// Execution etwo = new Execution(two); +// Execution etwo = new Execution(groupTwo); // etwo.setBuildGraph(true); // etwo.setFollowInvokes(false); -// etwo.populateInitialMethods(); -// List initial2 = etwo.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList()); +// etwo.addMethod(two); // etwo.run(); // -// assert initial1.size() == initial2.size(); +// // get frames for respective methods +// List f1 = eone.processedFrames, f2 = etwo.processedFrames; // -// for (int i = 0; i < initial1.size(); ++i) +// f1 = f1.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList()); +// f2 = f2.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList()); +// +// //List f1 = eone.processedFrames.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList()); +// //List f2 = etwo.processedFrames.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList()); +// +// Frame p1 = null, p2 = null; +// outer: +// for (Frame fr1 : f1) +// for (Frame fr2 : f2) +// { +// if (p1 == null) p1 = fr1; +// if (p2 == null) p2 = fr2; +// +// assert fr1.getMethod() == one; +// assert fr2.getMethod() == two; +// +// assert fr1.getMethodCtx() == p1.getMethodCtx(); +// assert fr2.getMethodCtx() == p2.getMethodCtx(); +// } +// +// assert p1.getMethod() == one; +// assert p2.getMethod() == two; +// +// outer2: +// for (Frame fr1 : f1) +// for (Frame fr2 : f2) +// { +// boolean b = compare(fr1, fr2); +// if (!b) +// { +// System.out.println("Mismatch " + p1.getMethod().getMethods().getClassFile().getName() + "." + p1.getMethod().getName() + " <-> " + p2.getMethod().getMethods().getClassFile().getName() + "." + p2.getMethod().getName()); +// System.out.println(one.getMethods().getClassFile().getName() + "." + one.getName() + " and " + two.getMethods().getClassFile().getName() + "." + two.getName()); +// int i =7; +// } +// break outer2; +// } +// +// System.out.println("end"); +// } +// public void run(ClassGroup one, ClassGroup two) +// { +// groupOne = one; +// groupTwo = two; +// +//// Execution eone = new Execution(one); +//// eone.setBuildGraph(true); +//// eone.setFollowInvokes(false); +//// eone.populateInitialMethods(); +//// List initial1 = eone.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList()); +//// eone.run(); +//// +//// Execution etwo = new Execution(two); +//// etwo.setBuildGraph(true); +//// etwo.setFollowInvokes(false); +//// etwo.populateInitialMethods(); +//// List initial2 = etwo.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList()); +//// etwo.run(); +//// +//// assert initial1.size() == initial2.size(); +//// +//// for (int i = 0; i < initial1.size(); ++i) +//// { +//// Method m1 = initial1.get(i), m2 = initial2.get(i); +//// +//// assert m1.getName().equals(m2.getName()); +//// +//// objMap.put(m1, m2); +//// } +// +// process( +// one.findClass("client").findMethod("vmethod2999"), +// two.findClass("client").findMethod("vmethod2978") +// ); +// +// for (;;) // { -// Method m1 = initial1.get(i), m2 = initial2.get(i); +// Optional next = objMap.keySet().stream() +// .filter(m -> !processed.contains(m)) +// .findAny(); +// if (!next.isPresent()) +// break; // -// assert m1.getName().equals(m2.getName()); +// Method m = (Method) next.get(); +// Method m2 = (Method) objMap.get(m); // -// objMap.put(m1, m2); +// if (m.getCode() == null || m2.getCode() == null) +// { +// processed.add(m); +// continue; +// } +// +// System.out.println("Scanning " + m.getMethods().getClassFile().getName() + "." + m.getName() + " -> " + m2.getMethods().getClassFile().getName() + "." + m2.getName()); +// process(m, m2); +// processed.add(m); // } - - process( - one.findClass("client").findMethod("vmethod2999"), - two.findClass("client").findMethod("vmethod2978") - ); - - for (;;) - { - Optional next = objMap.keySet().stream() - .filter(m -> !processed.contains(m)) - .findAny(); - if (!next.isPresent()) - break; - - Method m = (Method) next.get(); - Method m2 = (Method) objMap.get(m); - - if (m.getCode() == null || m2.getCode() == null) - { - processed.add(m); - continue; - } - - System.out.println("Scanning " + m.getMethods().getClassFile().getName() + "." + m.getName() + " -> " + m2.getMethods().getClassFile().getName() + "." + m2.getName()); - process(m, m2); - processed.add(m); - } - - for (Entry e : objMap.entrySet()) - { - Method m1 = (Method) e.getKey(); - Method m2 = (Method) e.getValue(); - - System.out.println("FINAL " + m1.getMethods().getClassFile().getName() + "." + m1.getName() + " -> " + m2.getMethods().getClassFile().getName() + "." + m2.getName()); - } - - System.out.println("done count " + objMap.size()); - } -} +// +// for (Entry e : objMap.entrySet()) +// { +// Method m1 = (Method) e.getKey(); +// Method m2 = (Method) e.getValue(); +// +// System.out.println("FINAL " + m1.getMethods().getClassFile().getName() + "." + m1.getName() + " -> " + m2.getMethods().getClassFile().getName() + "." + m2.getName()); +// } +// +// System.out.println("done count " + objMap.size()); +// } +//} diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java new file mode 100644 index 0000000000..688803df9e --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java @@ -0,0 +1,162 @@ +package net.runelite.deob.deobfuscators.rename; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import net.runelite.deob.ClassFile; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Field; +import net.runelite.deob.Method; +import net.runelite.deob.deobfuscators.rename.graph.Graph; +import net.runelite.deob.deobfuscators.rename.graph.Vertex; +import net.runelite.deob.deobfuscators.rename.graph.VertexType; +import net.runelite.deob.execution.Execution; +import net.runelite.deob.signature.Signature; + +public class Rename2 +{ + private Graph g1, g2; + + private static String cname(Method m) { return m.getMethods().getClassFile().getName(); } + private static String mname(Method m) { return cname(m) + "." + m.getName(); } + private static String fname(Field f) { return f.getFields().getClassFile().getName() + "." + f.getName(); } + + public static void collide(Object o0, Object o1, Object o2) + { + assert o0.getClass() == o1.getClass(); + assert o1.getClass() == o2.getClass(); + + if (o1 instanceof Method) + { + Method m1 = (Method) o1; + Method m2 = (Method) o2; + + System.out.println("COLLISION " + mname(m1) + " -> " + mname(m2)); + } + else if (o1 instanceof Field) + { + Field f0 = (Field) o0; + Field f1 = (Field) o1; + Field f2 = (Field) o2; + + System.out.println("COLLISION " + fname(f0) + ": " + fname(f1) + " -> " + fname(f2)); + } + else + assert false; + } + + private Map find(ClassFile cf) + { + Map set = new HashMap(); + Set collided = new HashSet(); + for (Method m : cf.getMethods().getMethods()) + { + if (m.isStatic()) + continue; + + Signature sig = m.getDescriptor(); + + if (set.containsKey(sig) || collided.contains(sig)) + { + collided.add(sig); + set.remove(sig); + continue; + } + set.put(sig, m); + } + return set; + } + + void mapClassMethods(Map one, Map two) + { + if (!one.keySet().equals(two.keySet())) + return; + + for (Signature sig : one.keySet()) + { + Method m1 = one.get(sig); + Method m2 = two.get(sig); + + Vertex v1 = g1.getVertexFor(m1); + Vertex v2 = g2.getVertexFor(m2); + + v1.is(v2); + v2.is(v1); + + System.out.println(mname(m1) + " is " + mname(m2)); + } + } + + private void solve() + { + List solved = g1.getVerticies().stream().filter(v -> v.getOther() != null).collect(Collectors.toList()); + + for (Vertex s : solved) + { + Vertex other = s.getOther(); + + s.getEdges().stream() + .map(e -> e.getTo()) // e.from is always s + .filter(v -> v.getOther() == null) // only get vertexes that aren't solved yet + .forEach(v -> + v.merge( + other.getEdges().stream() + .map(e -> e.getTo()) + .filter(v2 -> v2.getOther() == null) + .filter(v2 -> v.couldBeEqual(v2)) + .collect(Collectors.toList()) + ) + ); + } + } + + public void run(ClassGroup one, ClassGroup two) + { + Execution eone = new Execution(one); + eone.setBuildGraph(true); + //eone.setFollowInvokes(false); + eone.populateInitialMethods(); + eone.run(); + + Execution etwo = new Execution(two); + etwo.setBuildGraph(true); + //etwo.setFollowInvokes(false); + etwo.populateInitialMethods(); + etwo.run(); + + g1 = eone.getGraph(); + g2 = etwo.getGraph(); + + System.out.println(eone.getGraph()); + System.out.println(etwo.getGraph()); + + for (int i = 0; i < Math.min(one.getClasses().size(), two.getClasses().size()); ++i) + { + Map m1 = this.find(one.getClasses().get(i)); + Map m2 = this.find(two.getClasses().get(i)); + + mapClassMethods(m1, m2); + } + + for (;;) + { + int before = g1.solved(null); + System.out.println("Before " + before); + solve(); + g1.getVerticies().forEach(v -> v.finish()); + int after = g1.solved(null); + System.out.println("After " + after); + + if (before == after) + break; + } + + g1.check();g2.check(); + + System.out.println("methods " +g1.solved(VertexType.METHOD)); + System.out.println("f " +g1.solved(VertexType.FIELD)); + } +} diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java new file mode 100644 index 0000000000..b49db24baa --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java @@ -0,0 +1,64 @@ +package net.runelite.deob.deobfuscators.rename.graph; + +import java.util.Objects; + +public class Edge +{ + private final Vertex from, to; + + public Edge(Vertex from, Vertex to) + { + this.from = from; + this.to = to; + + assert from.getGraph() == to.getGraph(); + } + + public Vertex getFrom() + { + return from; + } + + public Vertex getTo() + { + return to; + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 11 * hash + Objects.hashCode(this.from); + hash = 11 * hash + Objects.hashCode(this.to); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final Edge other = (Edge) obj; + if (!Objects.equals(this.from, other.from)) + { + return false; + } + if (!Objects.equals(this.to, other.to)) + { + return false; + } + return true; + } + + +} diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Graph.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Graph.java new file mode 100644 index 0000000000..fe7d07f0bd --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Graph.java @@ -0,0 +1,79 @@ +package net.runelite.deob.deobfuscators.rename.graph; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Graph +{ + private List verticies = new ArrayList<>(); + + private Map o2v = new HashMap<>(); + private int edgeCount; + + public Vertex getVertexFor(Object o) + { + Vertex v = o2v.get(o); + if (v != null) + return v; + + v = new Vertex(this, o); + o2v.put(o, v); + verticies.add(v); + return v; + } + + public void addEdge(Object from, Object to) + { + assert from != null; + assert to != null; + + Vertex v1 = getVertexFor(from), v2 = getVertexFor(to); + + Edge e = new Edge(v1, v2); + if (v1.addEdge(e)) + ++edgeCount; + } + + public List getVerticies() + { + return verticies; + } + + public int vertexCount() + { + return verticies.size(); + } + + public int edgeCount() + { + return edgeCount; + } + + @Override + public String toString() + { + return "Graph{" + "verticies=" + verticies.size() + ", edgeCount=" + edgeCount + '}'; + } + + public void check() + { + for (Vertex v : verticies) + { + if (v.getOther() != null) + { + assert v.getOther().getOther() == v; + } + } + } + + public int solved(VertexType type) + { + int solved = 0; + for (Vertex v : verticies) + if (v.getOther() != null && (type == null || v.getType() == type)) + ++solved; + return solved; + } +} diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Vertex.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Vertex.java new file mode 100644 index 0000000000..5b43cd631f --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Vertex.java @@ -0,0 +1,174 @@ +package net.runelite.deob.deobfuscators.rename.graph; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import net.runelite.deob.ClassFile; +import net.runelite.deob.Field; +import net.runelite.deob.Method; +import net.runelite.deob.deobfuscators.rename.Rename2; +import org.apache.commons.collections4.CollectionUtils; + +public class Vertex +{ + private Graph graph; + private Object object; + private VertexType type; + + private Set edges = new HashSet<>(); + + private Collection mightBe; + private Vertex is; + + public Vertex(Graph graph, Object object) + { + this.graph = graph; + this.object = object; + if (object instanceof Method) + type = VertexType.METHOD; + else if (object instanceof Field) + type = VertexType.FIELD; + else + assert false; + } + + public Graph getGraph() + { + return graph; + } + + public Object getObject() + { + return object; + } + + public VertexType getType() + { + return type; + } + + public void setType(VertexType type) + { + this.type = type; + } + + public boolean addEdge(Edge edge) + { + return edges.add(edge); + } + + public Set getEdges() + { + return edges; + } + + public void merge(Collection maybe) + { + // mightBe and maybe + + if (mightBe == null) + mightBe = maybe; + else + mightBe = CollectionUtils.intersection(mightBe, maybe); + } + + public void finish() + { + if (mightBe != null && mightBe.size() == 1) + { + is(mightBe.stream().findAny().get()); + is.is(this); + mightBe = null; + } + } + + public void is(Vertex other) + { + if (is != null) + { + assert graph != other.graph; + assert is.graph == other.graph; + Rename2.collide(object, is.object, other.object); + } + assert is == null; + assert other.graph != graph; + + this.is = other; + } + + public Vertex getOther() + { + return is; + } + + private boolean couldBeEqual(ClassFile cf1, ClassFile cf2) + { + if (!cf1.getName().equals(cf2.getName())) + return false; + + if (!cf1.getInterfaces().getInterfaces().equals(cf2.getInterfaces().getInterfaces())) + return false; + + if (!cf1.getParentClass().equals(cf2.getParentClass())) + return false; + + return true; + } + + public boolean couldBeEqual(Vertex other) + { + assert this != other; + assert graph != other.graph; + assert is == null; + assert other.is == null; + + if (this.getType() != other.getType()) + return false; + + if (this.getType() == VertexType.METHOD) + { + Method m1 = (Method) object; + Method m2 = (Method) other.object; + + assert !m1.isStatic(); + assert !m2.isStatic(); + + if (m1.getName().equals("") != m2.getName().equals("")) + return false; + + if (!m1.getDescriptor().equals(m2.getDescriptor())) + return false; + + if (m1.getAccessFlags() != m2.getAccessFlags()) + return false; + + ClassFile cf1 = m1.getMethods().getClassFile(), cf2 = m2.getMethods().getClassFile(); + + if (!couldBeEqual(cf1, cf2)) + return false; + } + else if (type == VertexType.FIELD) + { + Field f1 = (Field) object; + Field f2 = (Field) other.object; + + if (!f1.getType().equals(f2.getType())) + return false; + + if (f1.isStatic() != f2.isStatic() || f1.getAccessFlags() != f2.getAccessFlags()) + return false; + + if (!f1.isStatic()) + { + ClassFile cf1 = f1.getFields().getClassFile(), cf2 = f2.getFields().getClassFile(); + + if (!couldBeEqual(cf1, cf2)) + return false; + } + } + else + assert false; + + return true; + } +} diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/VertexType.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/VertexType.java new file mode 100644 index 0000000000..8a13981063 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/VertexType.java @@ -0,0 +1,8 @@ +package net.runelite.deob.deobfuscators.rename.graph; + + +public enum VertexType +{ + METHOD, + FIELD; +} diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index 4f27b994fd..f18c0baa9e 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -7,6 +7,7 @@ import net.runelite.deob.Method; import net.runelite.deob.attributes.code.Instruction; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -14,7 +15,11 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; +import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; +import net.runelite.deob.attributes.code.instructions.InvokeStatic; import net.runelite.deob.deobfuscators.arithmetic.Encryption; +import net.runelite.deob.deobfuscators.rename.graph.Graph; import org.apache.commons.collections4.map.MultiValueMap; public class Execution @@ -24,12 +29,12 @@ public class Execution processedFrames = new LinkedList<>(); public Set methods = new HashSet<>(); // all methods public Set executed = new HashSet<>(); // executed instructions - private MultiValueMap invokes = new MultiValueMap<>(); + private MultiValueMap invokes = new MultiValueMap<>(); private Encryption encryption; public MultiValueMap contexts = new MultiValueMap<>(); private Map methodContexts = new HashMap<>(); private boolean buildGraph; // if true the frame graph is built and execution hasJumped also compares previous instructions - private boolean followInvokes = true; + private Graph graph = new Graph(); public Execution(ClassGroup group) { @@ -45,16 +50,6 @@ public class Execution { this.encryption = encryption; } - - public boolean isFollowInvokes() - { - return followInvokes; - } - - public void setFollowInvokes(boolean followInvokes) - { - this.followInvokes = followInvokes; - } public List getInitialMethods() { @@ -101,27 +96,26 @@ public class Execution private boolean hasInvoked(InstructionContext from, Method to) { - Frame frame = from.getFrame(); - MIKey key = new MIKey(frame.prevVertex.intValue(), from); - Collection methods = invokes.getCollection(key); + Collection methods = invokes.getCollection(from); if (methods != null && methods.contains(to)) return true; - invokes.put(key, to); + invokes.put(from, to); return false; } private void addFrame(Frame frame) { - frames.add(0, frame); + frames.add(frame); + //frames.add(0, frame); } public void invoke(InstructionContext from, Method to) { Frame frame = from.getFrame(); - if (!this.isFollowInvokes() && !to.isStatic()) - return; +// if (!this.isFollowInvokes() && !to.isStatic()) +// return; if (hasInvoked(from, to)) return; @@ -161,16 +155,16 @@ public class Execution assert frame.isExecuting(); frame.execute(); - if (!frame.isExecuting()) - { - //assert frames.get(0) == frame; +// if (!frame.isExecuting()) +// { + assert frames.get(0) == frame; frames.remove(frame); processedFrames.add(frame); - } - else - { - // another frame takes priority - } +// } +// else +// { +// // another frame takes priority +// } } System.out.println("Processed " + fcount + " frames"); @@ -201,4 +195,39 @@ public class Execution { this.buildGraph = buildGraph; } + + protected void buildGraph(Frame frame, Instruction i) + { + if (!isBuildGraph()) + return; + + if (i instanceof InvokeInstruction) + { + if (i instanceof InvokeStatic) + return; + + InvokeInstruction ii = (InvokeInstruction) i; + + List methods = ii.getMethods(); + if (methods.isEmpty()) + return; + + for (Method m : methods) + graph.addEdge(frame.nonStatic, m); + } + else if (i instanceof FieldInstruction) + { + FieldInstruction fi = (FieldInstruction) i; + + if (fi.getMyField() == null) + return; + + graph.addEdge(frame.nonStatic, fi.getMyField()); + } + } + + public Graph getGraph() + { + return graph; + } } diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index 14afe0289f..56ecb60247 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -11,7 +11,6 @@ import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.pool.NameAndType; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instruction.types.ReturnInstruction; -import org.apache.commons.lang3.mutable.MutableInt; public class Frame { @@ -23,10 +22,7 @@ public class Frame private Variables variables; private List instructions = new ArrayList<>(); // instructions executed in this frame private MethodContext ctx; - protected MutableInt prevVertex = new MutableInt(-1); - //protected int prevVertex = -1; - //private List prevInvokes; - private Frame from; + protected Method nonStatic; // next non static method up the stack public Frame(Execution execution, Method method) { @@ -38,6 +34,7 @@ public class Frame stack = new Stack(code.getMaxStack()); variables = new Variables(code.getMaxLocals()); ctx = execution.getMethodContext(method); + nonStatic = method; } public void initialize() @@ -63,12 +60,15 @@ public class Frame // initialize frame from invoking context assert ctx.getInstruction() instanceof InvokeInstruction; - if (!this.getExecution().isFollowInvokes() && this.getMethod().isStatic()) + //if (!this.getExecution().isFollowInvokes() && this.getMethod().isStatic()) + if (this.getMethod().isStatic()) { - assert from == null; - from = ctx.getFrame(); - this.ctx = ctx.getFrame().ctx; // share ctx if this method is static - this.prevVertex = ctx.getFrame().prevVertex; + //assert this.nonStatic == null; + this.nonStatic = ctx.getFrame().nonStatic; + //assert from == null; + //from = ctx.getFrame(); + //this.ctx = ctx.getFrame().ctx; // share ctx if this method is static + //this.prevVertex = ctx.getFrame().prevVertex; } // initialize LVT. the last argument is popped first, and is at arguments[0] @@ -104,9 +104,10 @@ public class Frame this.stack = new Stack(other.stack); this.variables = new Variables(other.variables); this.ctx = other.ctx; - this.prevVertex = new MutableInt(other.prevVertex); + //this.prevVertex = new MutableInt(other.prevVertex); //this.prevInvokes = other.prevInvokes; - from = other.from; + nonStatic = other.nonStatic; +// from = other.from; } public Frame dup() @@ -175,10 +176,6 @@ public class Frame { Instruction oldCur = cur; - if (cur instanceof ReturnInstruction) - if (processReturn()) - break; - try { cur.execute(this); @@ -211,7 +208,7 @@ public class Frame if (!executing) break; - ctx.buildGraph(this, oldCur); + execution.buildGraph(this, oldCur); if (oldCur == cur) { @@ -224,12 +221,12 @@ public class Frame /* jump */ } - if (!execution.frames.isEmpty() && execution.frames.get(0) != this) - { - stop(); // the prev frame must be an invokestatic? - assert execution.frames.get(0).getMethod().isStatic(); - break; - } +// if (!execution.frames.isEmpty() && execution.frames.get(0) != this) +// { +// stop(); // the prev frame must be an invokestatic? +// assert execution.frames.get(0).getMethod().isStatic(); +// break; +// } } } @@ -267,7 +264,7 @@ public class Frame assert to.getInstructions() == method.getCode().getInstructions(); assert method.getCode().getInstructions().getInstructions().contains(to); - if (ctx.hasJumped(prevVertex, from, to)) + if (ctx.hasJumped(from, to)) { executing = false; return; @@ -276,24 +273,24 @@ public class Frame cur = to; } - private boolean processReturn() - { - if (this.getExecution().isFollowInvokes() || !this.getMethod().isStatic()) - return false; - - if (from == null) - return false; - - assert !from.isExecuting(); - - // update method, cur, stack, variables, from outermost method - this.method = from.method; - //this.executing = from.executing; - this.cur = from.cur; - this.stack = new Stack(from.stack); - this.variables = new Variables(from.variables); - - //stop(); // now that weve switched this should still be running - return true; // this stops frame execution - } +// private boolean processReturn() +// { +// if (this.getExecution().isFollowInvokes() || !this.getMethod().isStatic()) +// return false; +// +// if (from == null) +// return false; +// +// assert !from.isExecuting(); +// +// // update method, cur, stack, variables, from outermost method +// this.method = from.method; +// //this.executing = from.executing; +// this.cur = from.cur; +// this.stack = new Stack(from.stack); +// this.variables = new Variables(from.variables); +// +// //stop(); // now that weve switched this should still be running +// return true; // this stops frame execution +// } } diff --git a/src/main/java/net/runelite/deob/execution/MIKey.java b/src/main/java/net/runelite/deob/execution/MIKey.java deleted file mode 100644 index af50cfe09a..0000000000 --- a/src/main/java/net/runelite/deob/execution/MIKey.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.runelite.deob.execution; - -import java.util.Objects; - -class MIKey -{ - private int prevVertex; - private InstructionContext ictx; - - public MIKey(int prevVertex, InstructionContext ictx) - { - this.prevVertex = prevVertex; - this.ictx = ictx; - } - - @Override - public int hashCode() - { - int hash = 7; - hash = 97 * hash + this.prevVertex; - hash = 97 * hash + Objects.hashCode(this.ictx); - return hash; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (getClass() != obj.getClass()) - { - return false; - } - final MIKey other = (MIKey) obj; - if (this.prevVertex != other.prevVertex) - { - return false; - } - if (!Objects.equals(this.ictx, other.ictx)) - { - return false; - } - return true; - } -} diff --git a/src/main/java/net/runelite/deob/execution/MethodContext.java b/src/main/java/net/runelite/deob/execution/MethodContext.java index db12a572af..74035f566d 100644 --- a/src/main/java/net/runelite/deob/execution/MethodContext.java +++ b/src/main/java/net/runelite/deob/execution/MethodContext.java @@ -1,130 +1,130 @@ package net.runelite.deob.execution; -import edu.ucla.sspace.graph.DirectedEdge; -import edu.ucla.sspace.graph.Graph; -import edu.ucla.sspace.graph.SimpleDirectedEdge; -import edu.ucla.sspace.graph.SparseDirectedGraph; +import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Objects; import net.runelite.deob.Method; import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instructions.InvokeStatic; -import net.runelite.deob.util.IdGen; +import net.runelite.deob.deobfuscators.rename.graph.Graph; import org.apache.commons.collections4.map.MultiValueMap; -import org.apache.commons.lang3.mutable.MutableInt; public class MethodContext { private Execution execution; - private MultiValueMap visited = new MultiValueMap<>(); - private IdGen ids = new IdGen(); - private Map> idMap = new HashMap<>(); - private Map, Integer> insMap = new HashMap<>(); - private Graph graph = new SparseDirectedGraph(); + private MultiValueMap visited = new MultiValueMap<>(); + //private IdGen ids = new IdGen(); + //private Map> idMap = new HashMap<>(); + //private Map, Integer> insMap = new HashMap<>(); +// private Graph graph = new Graph(); public MethodContext(Execution execution) { this.execution = execution; } - public Map> getIdMap() - { - return idMap; - } +// public Map> getIdMap() +// { +// return idMap; +// } + - public Graph getGraph() - { - return graph; - } - protected boolean hasJumped(MutableInt prevVertex, InstructionContext from, Instruction to) + protected boolean hasJumped(InstructionContext from, Instruction to) { - // with this true, there are so many frames I can't run a full execution without oom. - MIKey key = execution.isBuildGraph() ? new MIKey(prevVertex.intValue(), from) : new MIKey(-1, from); - Collection i = visited.getCollection(key); + Collection i = visited.getCollection(from); if (i != null && i.contains(to)) return true; - visited.put(key, to); + visited.put(from, to); return false; } - private int getIdFor(List i) - { - if (insMap.containsKey(i)) - return insMap.get(i); - - assert idMap.values().contains(i) == false; - - int id = ids.get(); - - //graph.add(id); - - this.idMap.put(id, i); - this.insMap.put(i, id); - - return id; - } +// private int getIdFor(List i) +// { +// if (insMap.containsKey(i)) +// return insMap.get(i); +// +// assert idMap.values().contains(i) == false; +// +// int id = ids.get(); +// +// //graph.add(id); +// +// this.idMap.put(id, i); +// this.insMap.put(i, id); +// +// return id; +// } - protected void buildGraph(Frame frame, Instruction i) - { - if (!execution.isBuildGraph()) - return; - - List methods; - if (i instanceof InvokeInstruction) - { - if (i instanceof InvokeStatic) - return; - - InvokeInstruction ii = (InvokeInstruction) i; - - methods = ii.getMethods(); - if (methods.isEmpty()) - return; - } +// protected void buildGraph(Frame frame, Instruction i) +// { +// if (!execution.isBuildGraph()) +// return; +// +// List to; +// //List methods; +// if (i instanceof InvokeInstruction) +// { +// if (i instanceof InvokeStatic) +// return; +// +// InvokeInstruction ii = (InvokeInstruction) i; +// +// List methods = ii.getMethods(); +// if (methods.isEmpty()) +// return; +// +// to = (List) methods; +// } // else if (i instanceof FieldInstruction) // { // FieldInstruction fi = (FieldInstruction) i; // // if (fi.getMyField() == null) // return; +// +// to = Arrays.asList(fi.getMyField()); // } - else - { - return; - } - - if (frame.prevVertex.intValue() == -1) - { - int id = getIdFor(methods); - //int id = ids.get(); - //graph.add(id); - frame.prevVertex.setValue(id); - //this.idMap.put(id, i); - return; - } - - int id = getIdFor(methods); - //int id = ids.get(); - //graph.add(id); - //idMap.put(id, i); - - if (frame.prevVertex.intValue() == id) - return; - - List from = this.idMap.get(frame.prevVertex.intValue()), to = this.idMap.get(id); - System.out.println("Added edge " + from.get(0).getMethods().getClassFile().getName() + "." + from.get(0).getName() + - " to " + to.get(0).getMethods().getClassFile().getName() + "." + to.get(0).getName() + - " (" + frame.prevVertex.intValue() + " -> " + id + ")"); - - DirectedEdge edge = new SimpleDirectedEdge(frame.prevVertex.intValue(), id); - graph.add(edge); - - frame.prevVertex.setValue(id); - } +// else +// { +// return; +// } +// +// to.stream().forEach(o -> graph.addEdge(frame.getMethod(), o)); +// +//// if (frame.prevVertex.intValue() == -1) +//// { +//// int id = getIdFor(methods); +//// //int id = ids.get(); +//// //graph.add(id); +//// frame.prevVertex.setValue(id); +//// //this.idMap.put(id, i); +//// return; +//// } +//// +//// int id = getIdFor(methods); +//// //int id = ids.get(); +//// //graph.add(id); +//// //idMap.put(id, i); +//// +//// if (frame.prevVertex.intValue() == id) +//// return; +//// +//// DirectedEdge edge = new SimpleDirectedEdge(frame.prevVertex.intValue(), id); +//// +//// if (graph.contains(edge) == false) +//// { +//// List from = this.idMap.get(frame.prevVertex.intValue()), to = this.idMap.get(id); +//// System.out.println("Added edge " + from.get(0).getMethods().getClassFile().getName() + "." + from.get(0).getName() + +//// " to " + to.get(0).getMethods().getClassFile().getName() + "." + to.get(0).getName() + +//// " (" + frame.prevVertex.intValue() + " -> " + id + ")"); +//// +//// graph.add(edge); +//// } +//// +//// frame.prevVertex.setValue(id); +// } } diff --git a/src/main/java/net/runelite/deob/signature/Signature.java b/src/main/java/net/runelite/deob/signature/Signature.java index 37b6316ed7..a04943fac6 100644 --- a/src/main/java/net/runelite/deob/signature/Signature.java +++ b/src/main/java/net/runelite/deob/signature/Signature.java @@ -2,6 +2,7 @@ package net.runelite.deob.signature; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -47,6 +48,15 @@ public class Signature Signature a = (Signature) other; return arguments.equals(a.arguments) && rv.equals(a.rv); } + + @Override + public int hashCode() + { + int hash = 5; + hash = 97 * hash + Objects.hashCode(this.arguments); + hash = 97 * hash + Objects.hashCode(this.rv); + return hash; + } @Override public String toString() diff --git a/src/test/java/net/runelite/deob/execution/FrameTest.java b/src/test/java/net/runelite/deob/execution/FrameTest.java index acbe88e663..8a8bf7e9ac 100644 --- a/src/test/java/net/runelite/deob/execution/FrameTest.java +++ b/src/test/java/net/runelite/deob/execution/FrameTest.java @@ -1,134 +1,133 @@ -package net.runelite.deob.execution; - -import edu.ucla.sspace.graph.Graph; -import net.runelite.deob.ClassGroup; -import net.runelite.deob.ClassGroupFactory; -import net.runelite.deob.Method; -import net.runelite.deob.attributes.Code; -import net.runelite.deob.attributes.code.Instruction; -import net.runelite.deob.attributes.code.Instructions; -import net.runelite.deob.attributes.code.instructions.Goto; -import net.runelite.deob.attributes.code.instructions.IConst_0; -import net.runelite.deob.attributes.code.instructions.If0; -import net.runelite.deob.attributes.code.instructions.InvokeStatic; -import net.runelite.deob.attributes.code.instructions.NOP; -import net.runelite.deob.attributes.code.instructions.VReturn; -import net.runelite.deob.signature.Signature; -import org.junit.Assert; -import org.junit.Test; - -public class FrameTest -{ - // invoke instruction, - // conditional jump out, - // both jump in, - // jump, - // invoke - // check that num edges = 4 - @Test - public void testGraph() - { - ClassGroup group = ClassGroupFactory.generateGroup(); - Code code = group.findClass("test").findMethod("func").getCode(); - Instructions ins = code.getInstructions(); - - code.setMaxStack(1); - - Method void1 = group.findClass("test").findMethod("void1"), - void2 = group.findClass("test").findMethod("void2"), - void3 = group.findClass("test").findMethod("void3"), - void4 = group.findClass("test").findMethod("void4"); - - NOP label1 = new NOP(ins), - label2 = new NOP(ins), - label3 = new NOP(ins); - - Instruction body[] = { - new InvokeStatic(ins, void1.getPoolMethod()), - - new IConst_0(ins), - new If0(ins, label1), - - new InvokeStatic(ins, void2.getPoolMethod()), - new Goto(ins, label2), - - label1, - new InvokeStatic(ins, void3.getPoolMethod()), - - label2, - // do something dumb - - new Goto(ins, label3), - label3, - - new InvokeStatic(ins, void4.getPoolMethod()), - - new VReturn(ins) - }; - - for (Instruction i : body) - ins.addInstruction(i); - - Execution e = new Execution(group); - e.setBuildGraph(true); - e.populateInitialMethods(); - e.run(); - - Graph graph = e.processedFrames.get(0).getMethodCtx().getGraph(); - Assert.assertEquals(4, graph.size()); - } - - // invoke instruction, - // conditional jump out, - // both jump in, - // invoke - // check that num edges = 4 - @Test - public void testGraph2() - { - ClassGroup group = ClassGroupFactory.generateGroup(); - Code code = group.findClass("test").findMethod("func").getCode(); - Instructions ins = code.getInstructions(); - - code.setMaxStack(1); - - Method void1 = group.findClass("test").findMethod("void1"), - void2 = group.findClass("test").findMethod("void2"), - void3 = group.findClass("test").findMethod("void3"), - void4 = group.findClass("test").findMethod("void4"); - - NOP label1 = new NOP(ins), - label2 = new NOP(ins); - - Instruction body[] = { - new InvokeStatic(ins, void1.getPoolMethod()), - - new IConst_0(ins), - new If0(ins, label1), - - new InvokeStatic(ins, void2.getPoolMethod()), - new Goto(ins, label2), - - label1, - new InvokeStatic(ins, void3.getPoolMethod()), - - label2, - // do something dumb - - new InvokeStatic(ins, void4.getPoolMethod()), - - new VReturn(ins) - }; - - for (Instruction i : body) - ins.addInstruction(i); - - Execution e = new Execution(group); - e.setBuildGraph(true); - e.populateInitialMethods(); - e.run(); - - Graph graph = e.processedFrames.get(0).getMethodCtx().getGraph(); - Assert.assertEquals(4, graph.size()); - } -} +//package net.runelite.deob.execution; +// +//import net.runelite.deob.ClassGroup; +//import net.runelite.deob.ClassGroupFactory; +//import net.runelite.deob.Method; +//import net.runelite.deob.attributes.Code; +//import net.runelite.deob.attributes.code.Instruction; +//import net.runelite.deob.attributes.code.Instructions; +//import net.runelite.deob.attributes.code.instructions.Goto; +//import net.runelite.deob.attributes.code.instructions.IConst_0; +//import net.runelite.deob.attributes.code.instructions.If0; +//import net.runelite.deob.attributes.code.instructions.InvokeStatic; +//import net.runelite.deob.attributes.code.instructions.NOP; +//import net.runelite.deob.attributes.code.instructions.VReturn; +//import net.runelite.deob.deobfuscators.rename.graph.Graph; +//import org.junit.Assert; +//import org.junit.Test; +// +//public class FrameTest +//{ +// // invoke instruction, +// // conditional jump out, +// // both jump in, +// // jump, +// // invoke +// // check that num edges = 4 +// @Test +// public void testGraph() +// { +// ClassGroup group = ClassGroupFactory.generateGroup(); +// Code code = group.findClass("test").findMethod("func").getCode(); +// Instructions ins = code.getInstructions(); +// +// code.setMaxStack(1); +// +// Method void1 = group.findClass("test").findMethod("void1"), +// void2 = group.findClass("test").findMethod("void2"), +// void3 = group.findClass("test").findMethod("void3"), +// void4 = group.findClass("test").findMethod("void4"); +// +// NOP label1 = new NOP(ins), +// label2 = new NOP(ins), +// label3 = new NOP(ins); +// +// Instruction body[] = { +// new InvokeStatic(ins, void1.getPoolMethod()), +// +// new IConst_0(ins), +// new If0(ins, label1), +// +// new InvokeStatic(ins, void2.getPoolMethod()), +// new Goto(ins, label2), +// +// label1, +// new InvokeStatic(ins, void3.getPoolMethod()), +// +// label2, +// // do something dumb +// +// new Goto(ins, label3), +// label3, +// +// new InvokeStatic(ins, void4.getPoolMethod()), +// +// new VReturn(ins) +// }; +// +// for (Instruction i : body) +// ins.addInstruction(i); +// +// Execution e = new Execution(group); +// e.setBuildGraph(true); +// e.populateInitialMethods(); +// e.run(); +// +// Graph graph = e.processedFrames.get(0).getMethodCtx().getGraph(); +// Assert.assertEquals(4, graph.size()); +// } +// +// // invoke instruction, +// // conditional jump out, +// // both jump in, +// // invoke +// // check that num edges = 4 +// @Test +// public void testGraph2() +// { +// ClassGroup group = ClassGroupFactory.generateGroup(); +// Code code = group.findClass("test").findMethod("func").getCode(); +// Instructions ins = code.getInstructions(); +// +// code.setMaxStack(1); +// +// Method void1 = group.findClass("test").findMethod("void1"), +// void2 = group.findClass("test").findMethod("void2"), +// void3 = group.findClass("test").findMethod("void3"), +// void4 = group.findClass("test").findMethod("void4"); +// +// NOP label1 = new NOP(ins), +// label2 = new NOP(ins); +// +// Instruction body[] = { +// new InvokeStatic(ins, void1.getPoolMethod()), +// +// new IConst_0(ins), +// new If0(ins, label1), +// +// new InvokeStatic(ins, void2.getPoolMethod()), +// new Goto(ins, label2), +// +// label1, +// new InvokeStatic(ins, void3.getPoolMethod()), +// +// label2, +// // do something dumb +// +// new InvokeStatic(ins, void4.getPoolMethod()), +// +// new VReturn(ins) +// }; +// +// for (Instruction i : body) +// ins.addInstruction(i); +// +// Execution e = new Execution(group); +// e.setBuildGraph(true); +// e.populateInitialMethods(); +// e.run(); +// +// Graph graph = e.processedFrames.get(0).getMethodCtx().getGraph(); +// Assert.assertEquals(4, graph.size()); +// } +//} \ No newline at end of file