From 3ce0b0a7b98ad2613a1bce9b41dcb416f491169d Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 12 Dec 2015 15:19:55 -0500 Subject: [PATCH] Add graphbuilder to statically build graph --- .../deobfuscators/rename/graph/Graph.java | 11 ++ .../rename/graph/GraphBuilder.java | 169 ++++++++++++++++++ .../deobfuscators/rename/graph/Vertex.java | 29 ++- .../rename/graph/GraphBuilderTest.java | 18 ++ 4 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/rename/graph/GraphBuilder.java create mode 100644 src/test/java/net/runelite/deob/deobfuscators/rename/graph/GraphBuilderTest.java 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 index 74311df267..b5ee711f22 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Graph.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Graph.java @@ -46,6 +46,17 @@ public class Graph return v; } + public void removeVertex(Object o) + { + Vertex v = this.getVertexFor(o); + + assert v.getEdges().isEmpty(); + assert v.getEdgesFrom().isEmpty(); + + verticies.remove(v); + o2v.remove(o); + } + public void addEdge(Edge e) { e.getFrom().addEdge(e); diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/GraphBuilder.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/GraphBuilder.java new file mode 100644 index 0000000000..c38c48e09f --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/GraphBuilder.java @@ -0,0 +1,169 @@ +package net.runelite.deob.deobfuscators.rename.graph; + +import java.util.HashSet; +import java.util.List; +import net.runelite.deob.ClassFile; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Field; +import net.runelite.deob.Method; +import net.runelite.deob.attributes.Code; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; +import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; +import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; +import net.runelite.deob.attributes.code.instructions.InvokeStatic; + +public class GraphBuilder +{ + public static Graph build(ClassGroup group) + { + // statically build + Graph g = new Graph(); + + // add verticies + for (ClassFile cf : group.getClasses()) + { + //g.addVertex(cf, VertexType.CLASS); + + for (Field f : cf.getFields().getFields()) + { + g.addVertex(f, VertexType.FIELD); + } + + for (Method m : cf.getMethods().getMethods()) + { + g.addVertex(m, VertexType.METHOD); + } + } + + for (ClassFile cf : group.getClasses()) + { + for (Method m : cf.getMethods().getMethods()) + { + processMethod(g, m); + } + } + + // remove static methods + for (ClassFile cf : group.getClasses()) + { + for (Method m : cf.getMethods().getMethods()) + { + if (m.isStatic() && !m.getName().equals("")) + { + removeMethod(g, m); + + Vertex v = g.getVertexFor(m); + + assert v.getEdges().isEmpty(); + assert v.getEdgesFrom().isEmpty(); + + g.removeVertex(m); + } + } + } + + return g; + } + + private static void processMethod(Graph graph, Method method) + { + Code code = method.getCode(); + if (code == null) + return; + + for (Instruction i : code.getInstructions().getInstructions()) + { + if (i instanceof InvokeInstruction) + { + if (i instanceof InvokeStatic) + return; + + InvokeInstruction ii = (InvokeInstruction) i; + + List methods = ii.getMethods(); + if (methods.isEmpty()) + return; + + Vertex methodVertex = graph.getVertexFor(method); + + for (Method m : methods) + { + Vertex otherMethodVertex = graph.getVertexFor(m); + + graph.addEdge(new Edge(null, methodVertex, otherMethodVertex, EdgeType.INVOKE)); + graph.addEdge(new Edge(null, otherMethodVertex, methodVertex, EdgeType.INVOKED_FROM)); + } + } + else if (i instanceof FieldInstruction) + { + FieldInstruction fi = (FieldInstruction) i; + + if (fi.getMyField() == null) + return; + + Vertex methodVertex = graph.getVertexFor(method), + fieldVertex = graph.getVertexFor(fi.getMyField()); + + EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD; + graph.addEdge(new Edge(null, methodVertex, fieldVertex, type)); + EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM; + graph.addEdge(new Edge(null, fieldVertex, methodVertex, typeRev)); + } + } + } + + private static void removeMethod(Graph g, Method m) + { + Vertex v = g.getVertexFor(m); + + // for every object that points to m, make it point to + // everything that m points to, with edge type of the edge from m. + + for (Edge e : new HashSet<>(v.getEdgesFrom())) + { + // edge is TO v + assert e.getTo() == v; + + Vertex from = e.getFrom(); + + // add an edge from -> everything v is to + + for (Edge e2 : new HashSet<>(v.getEdges())) + { + assert e2.getFrom() == v; + + Vertex to = e2.getTo(); + EdgeType type = e2.getType(); + + // add edge + from.addEdge(new Edge(null, from, to, type)); + } + + + // remove + from.removeEdge(e); + } + + // for every object m points to, everything that points to m should point to it. + for (Edge e : new HashSet<>(v.getEdges())) + { + assert e.getFrom() == v; + + Vertex to = e.getTo(); + EdgeType type = e.getType(); + + for (Edge e2 : new HashSet<>(v.getEdgesFrom())) + { + assert e2.getTo() == v; + + // add edge from -> to + Vertex from = e2.getFrom(); + + from.addEdge(new Edge(null, from, to, type)); + } + + v.removeEdge(e); + } + } +} 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 index 087afdd793..dffc15f17f 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Vertex.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Vertex.java @@ -31,7 +31,8 @@ public class Vertex private final Object object; private VertexType type; - private final Set edges = new HashSet<>(); + private final Set edges = new HashSet<>(), + from = new HashSet<>(); private Collection mightBe; private Vertex is; @@ -107,6 +108,9 @@ public class Vertex public void addEdge(Edge edge) { + assert edge.getFrom() == this; + //assert edge.getTo() != this; + if (edges.contains(edge)) //if (c != null) { @@ -118,15 +122,38 @@ public class Vertex return; } + Vertex to = edge.getTo(); + assert to.from.contains(edge) == false; + edges.add(edge); + to.from.add(edge); + //edges.put(edge, edge); } + public void removeEdge(Edge edge) + { + assert edge.getFrom() == this; + + assert edges.contains(edge); + + Vertex to = edge.getTo(); + assert to.from.contains(edge); + + edges.remove(edge); + to.from.remove(edge); + } + public Set getEdges() { return edges; } + public Set getEdgesFrom() + { + return from; + } + public void merge(Collection maybe) { boolean b = false; diff --git a/src/test/java/net/runelite/deob/deobfuscators/rename/graph/GraphBuilderTest.java b/src/test/java/net/runelite/deob/deobfuscators/rename/graph/GraphBuilderTest.java new file mode 100644 index 0000000000..e912ca3f6f --- /dev/null +++ b/src/test/java/net/runelite/deob/deobfuscators/rename/graph/GraphBuilderTest.java @@ -0,0 +1,18 @@ +package net.runelite.deob.deobfuscators.rename.graph; + +import java.io.File; +import java.io.IOException; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.util.JarUtil; +import org.junit.Test; + + +public class GraphBuilderTest +{ + @Test + public void test() throws IOException + { + ClassGroup group = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar")); + GraphBuilder.build(group); + } +}