From a2581e62c1c404deaf25bf02641b444127525551 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 28 Nov 2015 23:27:34 -0500 Subject: [PATCH] total crap --- pom.xml | 2 +- src/main/java/net/runelite/deob/Deob.java | 124 +++++++++--------- src/main/java/net/runelite/deob/Field.java | 2 +- .../attributes/annotation/Annotation.java | 2 +- .../deob/attributes/annotation/Element.java | 2 +- .../code/instructions/InvokeStatic.java | 11 +- .../deobfuscators/arithmetic/ModArith.java | 2 +- .../deob/deobfuscators/rename/Rename2.java | 64 +++++++-- .../deob/deobfuscators/rename/graph/Edge.java | 14 +- .../deobfuscators/rename/graph/EdgeType.java | 14 +- .../deobfuscators/rename/graph/FieldEdge.java | 39 ++++++ .../deobfuscators/rename/graph/Graph.java | 10 +- .../rename/graph/MethodEdge.java | 53 ++++++++ .../deobfuscators/rename/graph/Vertex.java | 9 +- .../runelite/deob/execution/Execution.java | 98 ++++++++++++-- .../net/runelite/deob/execution/Frame.java | 34 ++++- .../deob/execution/MethodContext.java | 1 + .../net/runelite/deob/execution/Type.java | 2 +- .../net/runelite/deob/pool/NameAndType.java | 4 +- .../runelite/deob/signature/Signature.java | 4 +- .../deob/deobfuscators/rename/Rename.java | 95 ++++++++++++++ 21 files changed, 482 insertions(+), 104 deletions(-) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/rename/graph/FieldEdge.java create mode 100644 src/main/java/net/runelite/deob/deobfuscators/rename/graph/MethodEdge.java create mode 100644 src/test/java/net/runelite/deob/deobfuscators/rename/Rename.java diff --git a/pom.xml b/pom.xml index dd910da92e..295625ff7f 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 net.runelite deob - 0.0.1-SNAPSHOT + 1.0-SNAPSHOT org.apache.commons diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 5a967aec2c..c5e17f20b5 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -31,67 +31,67 @@ public class Deob ClassGroup group = JarUtil.loadJar(new File(args[0])); -// run(group, new RenameUnique()); -// -// // remove except RuntimeException -// run(group, new RuntimeExceptions()); -// -// // remove unused methods -// run(group, new UnreachedCode()); -// run(group, new UnusedMethods()); -// -// // remove illegal state exceptions, frees up some parameters -// run(group, new IllegalStateExceptions()); -// -// // remove constant logically dead parameters -// run(group, new ConstantParameter()); -// -// // remove unhit blocks -// run(group, new UnreachedCode()); -// run(group, new UnusedMethods()); -// -// // remove unused parameters -// run(group, new UnusedParameters()); -// -// // remove unused fields -// run(group, new UnusedFields()); -// -// // remove unused methods, again? -// run(group, new UnusedMethods()); -// -//// run(group, new MethodInliner()); -//// run(group, new UnusedMethods()); // inliner might leave unused methods -// -//// // broken because rename was removed -//// //run(group, new MethodMover()); -// -// run(group, new FieldInliner()); -// -//// // XXX this is broken because when moving clinit around, some fields can depend on other fields -//// // (like multianewarray) -//// //new FieldMover().run(group); -// -// run(group, new UnusedClass()); + run(group, new RenameUnique()); + + // remove except RuntimeException + run(group, new RuntimeExceptions()); + + // remove unused methods + run(group, new UnreachedCode()); + run(group, new UnusedMethods()); + + // remove illegal state exceptions, frees up some parameters + run(group, new IllegalStateExceptions()); + + // remove constant logically dead parameters + run(group, new ConstantParameter()); + + // remove unhit blocks + run(group, new UnreachedCode()); + run(group, new UnusedMethods()); + + // remove unused parameters + run(group, new UnusedParameters()); + + // remove unused fields + run(group, new UnusedFields()); + + // remove unused methods, again? + run(group, new UnusedMethods()); + +// run(group, new MethodInliner()); +// run(group, new UnusedMethods()); // inliner might leave unused methods + +// // broken because rename was removed +// //run(group, new MethodMover()); + + run(group, new FieldInliner()); + +// // XXX this is broken because when moving clinit around, some fields can depend on other fields +// // (like multianewarray) +// //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) -// break; -// -// last = cur; -// } -// -// mod.annotateEncryption(); + 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) + break; + + last = cur; + } + + mod.annotateEncryption(); // eval constant fields (only set once to a constant in ctor) maybe just inline them @@ -105,8 +105,8 @@ public class Deob private static void merge() throws IOException { - ClassGroup group1 = JarUtil.loadJar(new File("/Users/adam/w/rs/07/adamin1.jar")), - group2 = JarUtil.loadJar(new File("/Users/adam/w/rs/07/adamin2.jar")); + ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")), + group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar")); Rename2 rename = new Rename2(); rename.run(group1, group2); diff --git a/src/main/java/net/runelite/deob/Field.java b/src/main/java/net/runelite/deob/Field.java index 910d10aeb7..4d0fdfef72 100644 --- a/src/main/java/net/runelite/deob/Field.java +++ b/src/main/java/net/runelite/deob/Field.java @@ -54,7 +54,7 @@ public class Field out.writeShort(accessFlags); out.writeShort(pool.makeUTF8(name)); - out.writeShort(pool.makeUTF8(type.toString())); + out.writeShort(pool.makeUTF8(type.getFullType())); attributes.write(out); } diff --git a/src/main/java/net/runelite/deob/attributes/annotation/Annotation.java b/src/main/java/net/runelite/deob/attributes/annotation/Annotation.java index bf44f27d01..dcd6b51859 100644 --- a/src/main/java/net/runelite/deob/attributes/annotation/Annotation.java +++ b/src/main/java/net/runelite/deob/attributes/annotation/Annotation.java @@ -65,7 +65,7 @@ public class Annotation { ConstantPool pool = annotations.getAttributes().getClassFile().getPool(); - out.writeShort(pool.makeUTF8(type.toString())); + out.writeShort(pool.makeUTF8(type.getFullType())); out.writeShort(elements.size()); for (Element e : elements) { diff --git a/src/main/java/net/runelite/deob/attributes/annotation/Element.java b/src/main/java/net/runelite/deob/attributes/annotation/Element.java index 94da9891a2..c644994534 100644 --- a/src/main/java/net/runelite/deob/attributes/annotation/Element.java +++ b/src/main/java/net/runelite/deob/attributes/annotation/Element.java @@ -64,7 +64,7 @@ public class Element { ConstantPool pool = annotation.getAnnotations().getAttributes().getClassFile().getPool(); - out.writeShort(pool.makeUTF8(type.toString())); + out.writeShort(pool.makeUTF8(type.getFullType())); byte type; switch (value.getType()) { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java index 629e737e7d..84346341da 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java @@ -95,7 +95,16 @@ public class InvokeStatic extends Instruction implements InvokeInstruction // add possible method call to execution Execution execution = frame.getExecution(); - execution.invoke(ins, method); + Frame f = execution.invoke(ins, method); + + if (f != null) + { + assert f.getMethod() == method; + //assert f.lastField == frame.lastField; + //assert f.staticReturn == frame; + + //frame.stop(); + } } frame.addInstructionContext(ins); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 9c1790c2f5..2dd5822ca3 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -42,7 +42,7 @@ public class ModArith implements Deobfuscator private List pairs = new ArrayList<>(); private Encryption encryption = new Encryption(); - private List getInsInExpr(InstructionContext ctx, Set set) + private static List getInsInExpr(InstructionContext ctx, Set set) { List l = new ArrayList<>(); diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java index c4bc56131e..b561a2ee1c 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/Rename2.java @@ -25,6 +25,8 @@ import net.runelite.deob.attributes.annotation.Annotation; import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.deob.deobfuscators.Renamer; import net.runelite.deob.deobfuscators.rename.graph.Edge; +import net.runelite.deob.deobfuscators.rename.graph.EdgeType; +import net.runelite.deob.deobfuscators.rename.graph.FieldEdge; import net.runelite.deob.deobfuscators.rename.graph.Graph; import net.runelite.deob.deobfuscators.rename.graph.Vertex; import net.runelite.deob.deobfuscators.rename.graph.VertexType; @@ -193,6 +195,47 @@ public class Rename2 return fields; } + private void mapOneFrame(ClassGroup group, Execution e) + { + for (ClassFile cf : group.getClasses()) + { + for (Method m : cf.getMethods().getMethods()) + { + if (m.isStatic()) + continue; + + List frames = e.processedFrames.stream().filter(f -> f.getMethod() == m).collect(Collectors.toList()); + + if (frames.size() != 1) + continue; + + int count = 0; + for (InstructionContext i : frames.get(0).getInstructions()) + { + if (i.getInstruction() instanceof SetFieldInstruction) + { + SetFieldInstruction sfi = (SetFieldInstruction) i.getInstruction(); + + Field f = sfi.getMyField(); + if (f == null) + continue; + + Vertex methodVertex = e.getGraph().getVertexFor(m), + fieldVertex = e.getGraph().getVertexFor(f); + + Edge edge = new FieldEdge(i.getInstruction(), methodVertex, fieldVertex, EdgeType.SETFIELD, count); + e.getGraph().addEdge(edge); + + edge = new FieldEdge(i.getInstruction(), fieldVertex, methodVertex, EdgeType.SETFIELD_FROM, count); + e.getGraph().addEdge(edge); + + ++count; + } + } + } + } + } + private void solve() { List solved = g1.getVerticies().stream().filter(v -> v.getOther() != null).collect(Collectors.toList()); @@ -231,14 +274,14 @@ public class Rename2 if (e2.getTo().getOther() != null) continue; // skip solved edges - if (b2) - { - Method m = (Method) e2.getTo().getObject(); - if (m.getName().equals("method2489")) - { - b2 = true; - } - } +// if (b2) +// { +// Method m = (Method) e2.getTo().getObject(); +// if (m.getName().equals("method2489")) +// { +// b2 = true; +// } +// } if (!e.getTo().couldBeEqual(e2.getTo())) { @@ -320,6 +363,9 @@ public class Rename2 System.out.println(fname(f1) + " is " + fname(f2)); } +// mapOneFrame(one, eone); +// mapOneFrame(two, etwo); + System.out.println("g1 verticies " + g1.getVerticies().size() + " reachable " + g1.reachableVerticiesFromSolvedVerticies().size()); Set reachable = g1.reachableVerticiesFromSolvedVerticies(); for (Vertex v : g1.getVerticies()) @@ -384,7 +430,7 @@ public class Rename2 try { - JarUtil.saveJar(two, new File("/Users/adam/w/rs/07/adamout.jar")); + JarUtil.saveJar(two, new File("d:/rs/07/adamout.jar")); } catch (IOException ex) { 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 index 611e5cf8f3..9644b96302 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/Edge.java @@ -1,15 +1,18 @@ package net.runelite.deob.deobfuscators.rename.graph; import java.util.Objects; +import net.runelite.deob.attributes.code.Instruction; public class Edge { + private final Instruction ins; // craetor private final Vertex from, to; private final EdgeType type; private int weight; - public Edge(Vertex from, Vertex to, EdgeType type) + public Edge(Instruction ins, Vertex from, Vertex to, EdgeType type) { + this.ins = ins; this.from = from; this.to = to; this.type = type; @@ -17,6 +20,11 @@ public class Edge assert from.getGraph() == to.getGraph(); } + public Instruction getIns() + { + return ins; + } + public Vertex getFrom() { return from; @@ -94,8 +102,8 @@ public class Edge if (this.type != other.type) return false; - //if (this.weight != other.weight) - // return false; +// if (this.weight != other.weight) +// return false; return true; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/EdgeType.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/EdgeType.java index 9651842c6c..fc4180da2b 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/EdgeType.java +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/EdgeType.java @@ -8,5 +8,17 @@ public enum EdgeType INVOKED_FROM, GETFIELD_FROM, - SETFIELD_FROM; + SETFIELD_FROM, + + FIELD_ASSOCIATION, + FIELD_ASSOCIATION_FROM, + + METHOD_ASSOCIATION, + METHOD_ASSOCIATION_FROM, + + PREV_FIELD, + PREV_FIELD_FROM, + + FIELD_ASSIGNMENT_FIELD, + FIELD_ASSIGNMENT_FIELD_FROM; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/FieldEdge.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/FieldEdge.java new file mode 100644 index 0000000000..33f0ffeff8 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/FieldEdge.java @@ -0,0 +1,39 @@ +package net.runelite.deob.deobfuscators.rename.graph; + +import net.runelite.deob.attributes.code.Instruction; + +public class FieldEdge extends Edge +{ + private int id; + + public FieldEdge(Instruction ins, Vertex from, Vertex to, EdgeType type, int id) + { + super(ins, from, to, type); + this.id = id; + } + + @Override + public boolean equals(Object obj) + { + if (!super.equals(obj)) + { + return false; + } + final FieldEdge other = (FieldEdge) obj; + if (this.id != other.id) + { + return false; + } + return true; + } + + @Override + public int hashCode() + { + int hash = 5; + hash = 89 * hash + this.id; + return hash ^ super.hashCode(); + } + + +} 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 872eb8839c..74311df267 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,15 +46,9 @@ public class Graph return v; } - public void addEdge(Object from, Object to, EdgeType type) + public void addEdge(Edge e) { - assert from != null; - assert to != null; - - Vertex v1 = getVertexFor(from), v2 = getVertexFor(to); - - Edge e = new Edge(v1, v2, type); - v1.addEdge(e); + e.getFrom().addEdge(e); } public List getVerticies() diff --git a/src/main/java/net/runelite/deob/deobfuscators/rename/graph/MethodEdge.java b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/MethodEdge.java new file mode 100644 index 0000000000..036ec421c8 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/rename/graph/MethodEdge.java @@ -0,0 +1,53 @@ +package net.runelite.deob.deobfuscators.rename.graph; + +import java.util.Objects; +import net.runelite.deob.Method; +import net.runelite.deob.attributes.code.Instruction; + +public class MethodEdge extends Edge +{ + private final Method method; + + public MethodEdge(Instruction i, Vertex from, Vertex to, EdgeType type, Method method) + { + super(i, from, to, type); + this.method = method; + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 61 * hash + Objects.hashCode(this.method); + return hash ^ super.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (!super.equals(obj)) + { + return false; + } + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final MethodEdge other = (MethodEdge) obj; + if (!Objects.equals(this.method, other.method)) + { + return false; + } + return true; + } + + +} 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 4169978271..14807d9330 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 @@ -16,6 +16,7 @@ import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.ConstantValue; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; +import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.deob.attributes.code.instructions.InvokeStatic; import net.runelite.deob.deobfuscators.rename.InstructionList; import net.runelite.deob.deobfuscators.rename.Rename2; @@ -34,6 +35,8 @@ public class Vertex private Collection mightBe; private Vertex is; + + private Set edgeFrom = new HashSet<>(); public Vertex(Graph graph, Object object) { @@ -107,7 +110,11 @@ public class Vertex Edge c = edges.get(edge); if (c != null) { - c.increase(); + if (edge.getIns() instanceof SetFieldInstruction && !edgeFrom.contains(edge.getIns())) + { + edgeFrom.add(edge.getIns()); + c.increase(); + } return; } diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index 35eff6776d..d0d6571642 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -18,9 +18,13 @@ import net.runelite.deob.Field; 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.instruction.types.SetFieldInstruction; import net.runelite.deob.attributes.code.instructions.InvokeStatic; +import net.runelite.deob.deobfuscators.rename.graph.Edge; import net.runelite.deob.deobfuscators.rename.graph.EdgeType; +import net.runelite.deob.deobfuscators.rename.graph.FieldEdge; import net.runelite.deob.deobfuscators.rename.graph.Graph; +import net.runelite.deob.deobfuscators.rename.graph.MethodEdge; import net.runelite.deob.deobfuscators.rename.graph.VertexType; import org.apache.commons.collections4.map.MultiValueMap; @@ -100,14 +104,15 @@ public class Execution frames.add(frame); } - public void invoke(InstructionContext from, Method to) + public Frame invoke(InstructionContext from, Method to) { if (hasInvoked(from, to)) - return; + return null; Frame f = new Frame(this, to); f.initialize(from); this.addFrame(f); + return f; } public void addMethod(Method to) @@ -132,7 +137,9 @@ public class Execution frame.execute(); assert frames.get(0) == frame; - frames.remove(0); + assert !frame.isExecuting(); + + frames.remove(frame); processedFrames.add(frame); } @@ -189,12 +196,13 @@ public class Execution } } - protected void buildGraph(Frame frame, Instruction i) + protected void buildGraph(Frame frame, Instruction i, InstructionContext ctx) { if (!isBuildGraph()) return; assert frame.getMethod() == frame.nonStatic || frame.nonStatic.isStatic() == false; + assert ctx.getInstruction() == i; if (i instanceof InvokeInstruction) { @@ -209,8 +217,8 @@ public class Execution for (Method m : methods) { - graph.addEdge(frame.nonStatic, m, EdgeType.INVOKE); - graph.addEdge(m, frame.nonStatic, EdgeType.INVOKED_FROM); + graph.addEdge(new Edge(i, graph.getVertexFor(frame.nonStatic), graph.getVertexFor(m), EdgeType.INVOKE)); + graph.addEdge(new Edge(i, graph.getVertexFor(m), graph.getVertexFor(frame.nonStatic), EdgeType.INVOKED_FROM)); } } else if (i instanceof FieldInstruction) @@ -220,13 +228,87 @@ public class Execution if (fi.getMyField() == null) return; + //int id = frame.getMethodCtx().fcount++; EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD; - graph.addEdge(frame.nonStatic, fi.getMyField(), type); + graph.addEdge(new Edge(i, graph.getVertexFor(frame.nonStatic), graph.getVertexFor(fi.getMyField()), type)); EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM; - graph.addEdge(fi.getMyField(), frame.nonStatic, typeRev); + graph.addEdge(new Edge(i, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(frame.nonStatic), typeRev)); + + if (fi instanceof SetFieldInstruction && frame.lastField != null) + { + graph.addEdge(new MethodEdge(i, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(frame.lastField), EdgeType.PREV_FIELD, frame.nonStatic)); + graph.addEdge(new MethodEdge(i, graph.getVertexFor(frame.lastField), graph.getVertexFor(fi.getMyField()), EdgeType.PREV_FIELD_FROM, frame.nonStatic)); + } + +// if (fi instanceof SetFieldInstruction) +// { +// StackContext sctx = ctx.getPops().get(0); +// if (sctx.getPushed().getInstruction() instanceof GetFieldInstruction) +// { +// GetFieldInstruction gfi = (GetFieldInstruction) sctx.getPushed().getInstruction(); +// +// if (gfi.getMyField() != null) +// { +// // XXX dup edges +// graph.addEdge(new MethodEdge(i, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(gfi.getMyField()), EdgeType.FIELD_ASSIGNMENT_FIELD, frame.nonStatic)); +// graph.addEdge(new MethodEdge(i, graph.getVertexFor(gfi.getMyField()), graph.getVertexFor(fi.getMyField()), EdgeType.FIELD_ASSIGNMENT_FIELD_FROM, frame.nonStatic)); +// } +// } +// } + + // associated fields + for (InstructionContext ic : getInsInExpr(ctx, new HashSet<>())) + { + Instruction i2 = (Instruction) ic.getInstruction(); + + if (i2 instanceof FieldInstruction) + { + FieldInstruction fi2 = (FieldInstruction) i2; + + if (fi2.getMyField() == null) + continue; + + // these are within the context of a method + graph.addEdge(new MethodEdge(i2, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(fi2.getMyField()), EdgeType.FIELD_ASSOCIATION, frame.nonStatic)); + graph.addEdge(new MethodEdge(i2, graph.getVertexFor(fi2.getMyField()), graph.getVertexFor(fi.getMyField()), EdgeType.FIELD_ASSOCIATION_FROM, frame.nonStatic)); + } + else if (i2 instanceof InvokeInstruction) + { + InvokeInstruction ii2 = (InvokeInstruction) i2; + + if (ii2 instanceof InvokeStatic) + continue; + + for (Method m : ii2.getMethods()) + { + graph.addEdge(new MethodEdge(i2, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(m), EdgeType.METHOD_ASSOCIATION, frame.nonStatic)); + graph.addEdge(new MethodEdge(i2, graph.getVertexFor(m), graph.getVertexFor(fi.getMyField()), EdgeType.METHOD_ASSOCIATION_FROM, frame.nonStatic)); + } + } + } } } + private static List getInsInExpr(InstructionContext ctx, Set set) + { + List l = new ArrayList<>(); + + if (ctx == null || set.contains(ctx.getInstruction())) + return l; + + set.add(ctx.getInstruction()); + + l.add(ctx); + + for (StackContext s : ctx.getPops()) + l.addAll(getInsInExpr(s.getPushed(), set)); + for (StackContext s : ctx.getPushes()) + for (InstructionContext i : s.getPopped()) + l.addAll(getInsInExpr(i, set)); + + return l; + } + 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 d00a01e391..9e20bc0b8d 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -3,6 +3,7 @@ package net.runelite.deob.execution; import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; +import net.runelite.deob.Field; import net.runelite.deob.Method; import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.code.Exception; @@ -11,6 +12,9 @@ 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 net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; +import net.runelite.deob.attributes.code.instructions.AThrow; +import net.runelite.deob.attributes.code.instructions.InvokeStatic; public class Frame { @@ -23,6 +27,8 @@ public class Frame private List instructions = new ArrayList<>(); // instructions executed in this frame private MethodContext ctx; protected Method nonStatic; // next non static method up the stack + public Field lastField; + public Frame staticReturn; public Frame(Execution execution, Method method) { @@ -63,6 +69,9 @@ public class Frame if (this.getMethod().isStatic()) { this.nonStatic = ctx.getFrame().nonStatic; +// this.lastField = ctx.getFrame().lastField; +// this.staticReturn = ctx.getFrame(); + //this.ctx = ctx.getFrame().ctx; } // initialize LVT. the last argument is popped first, and is at arguments[0] @@ -99,6 +108,8 @@ public class Frame this.variables = new Variables(other.variables); this.ctx = other.ctx; this.nonStatic = other.nonStatic; + this.lastField = other.lastField; + this.staticReturn = other.staticReturn; } public Frame dup() @@ -167,6 +178,21 @@ public class Frame { Instruction oldCur = cur; + if ((cur instanceof ReturnInstruction || cur instanceof AThrow) && this.staticReturn != null) + { + Frame newFrame = this.staticReturn.dup(); + newFrame.lastField = this.lastField; + newFrame.executing = true; + + assert newFrame.cur instanceof InvokeStatic; + int i = newFrame.method.getCode().getInstructions().getInstructions().indexOf(newFrame.cur); + assert i != -1; + newFrame.cur = newFrame.method.getCode().getInstructions().getInstructions().get(i + 1); + + assert execution.frames.contains(newFrame); + //this.execution.frames.add(newFrame); + } + try { cur.execute(this); @@ -199,7 +225,13 @@ public class Frame if (!executing) break; - execution.buildGraph(this, oldCur); + execution.buildGraph(this, oldCur, ictx); + if (oldCur instanceof SetFieldInstruction) + { + SetFieldInstruction sfi = (SetFieldInstruction) oldCur; + if (sfi.getMyField() != null) + this.lastField = sfi.getMyField(); + } if (oldCur == cur) { diff --git a/src/main/java/net/runelite/deob/execution/MethodContext.java b/src/main/java/net/runelite/deob/execution/MethodContext.java index 99dbe328fe..fa97ec80d3 100644 --- a/src/main/java/net/runelite/deob/execution/MethodContext.java +++ b/src/main/java/net/runelite/deob/execution/MethodContext.java @@ -1,6 +1,7 @@ package net.runelite.deob.execution; import java.util.Collection; +import net.runelite.deob.Field; import net.runelite.deob.attributes.code.Instruction; import org.apache.commons.collections4.map.MultiValueMap; diff --git a/src/main/java/net/runelite/deob/execution/Type.java b/src/main/java/net/runelite/deob/execution/Type.java index e21cfb5e63..29e376c23e 100644 --- a/src/main/java/net/runelite/deob/execution/Type.java +++ b/src/main/java/net/runelite/deob/execution/Type.java @@ -28,7 +28,7 @@ public class Type private static String asmTypeToClass(String type) { - switch (type.toString()) + switch (type) { case "B": return byte.class.getCanonicalName(); diff --git a/src/main/java/net/runelite/deob/pool/NameAndType.java b/src/main/java/net/runelite/deob/pool/NameAndType.java index 58a7b12d3f..75a7ed6661 100644 --- a/src/main/java/net/runelite/deob/pool/NameAndType.java +++ b/src/main/java/net/runelite/deob/pool/NameAndType.java @@ -61,7 +61,7 @@ public class NameAndType extends PoolEntry if (signature != null) descriptorIndex = pool.makeUTF8(signature.toString()); else - descriptorIndex = pool.makeUTF8(type.toString()); + descriptorIndex = pool.makeUTF8(type.getFullType()); } @Override @@ -97,7 +97,7 @@ public class NameAndType extends PoolEntry public Object getStackObject() { - switch (type.toString()) + switch (type.getFullType()) { case "B": return (byte) 0; diff --git a/src/main/java/net/runelite/deob/signature/Signature.java b/src/main/java/net/runelite/deob/signature/Signature.java index a04943fac6..8b9ce7fec5 100644 --- a/src/main/java/net/runelite/deob/signature/Signature.java +++ b/src/main/java/net/runelite/deob/signature/Signature.java @@ -64,9 +64,9 @@ public class Signature StringBuffer sb = new StringBuffer(); sb.append('('); for (Type a : arguments) - sb.append(a.toString()); + sb.append(a.getFullType()); sb.append(')'); - sb.append(rv.toString()); + sb.append(rv.getFullType()); return sb.toString(); } diff --git a/src/test/java/net/runelite/deob/deobfuscators/rename/Rename.java b/src/test/java/net/runelite/deob/deobfuscators/rename/Rename.java new file mode 100644 index 0000000000..05af1da2cf --- /dev/null +++ b/src/test/java/net/runelite/deob/deobfuscators/rename/Rename.java @@ -0,0 +1,95 @@ +package net.runelite.deob.deobfuscators.rename; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +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.InvokeInstruction; +import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; +import net.runelite.deob.attributes.code.instructions.InvokeStatic; +import net.runelite.deob.execution.Execution; +import net.runelite.deob.execution.Frame; +import net.runelite.deob.util.JarUtil; +import org.junit.Test; + +public class Rename +{ + private List getInstructionsInMethodInclStatic(Method method, Set visited) + { + List ilist = new ArrayList<>(); + + if (visited.contains(method)) + return ilist; + visited.add(method); + + Code code = method.getCode(); + if (code == null) + return ilist; + + for (Instruction i : code.getInstructions().getInstructions()) + { + if (i instanceof InvokeStatic) + { + InvokeInstruction ii = (InvokeInstruction) i; + List methods = ii.getMethods(); + + if (methods.isEmpty()) + continue; + + Method m = methods.get(0); + ilist.addAll(this.getInstructionsInMethodInclStatic(m, visited)); + } + else + { + ilist.add(i); + } + } + + return ilist; + } + + @Test + public void test() throws IOException + { + ClassGroup one = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")), two = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar")); + + Execution eone = new Execution(one); + eone.setBuildGraph(true); + eone.populateInitialMethods(); + eone.run(); + + Execution etwo = new Execution(two); + etwo.setBuildGraph(true); + etwo.populateInitialMethods(); + etwo.run(); + +// Method m1 = one.findClass("client").findMethod("vmethod3096"), m2 = two.findClass("client").findMethod("vmethod2975"); +// +// List l1 = (List) getInstructionsInMethodInclStatic(m1, new HashSet()).stream().filter(i -> i instanceof SetFieldInstruction).collect(Collectors.toList()), +// l2 = (List) getInstructionsInMethodInclStatic(m2, new HashSet()).stream().filter(i -> i instanceof SetFieldInstruction).collect(Collectors.toList()); +// +// +// List lf1 =(List) l1.stream().filter(i -> i.getMyField() != null).map(i -> i.getMyField()).distinct().collect(Collectors.toList()), +// lf2 = l2.stream().filter(i -> i.getMyField() != null).map(i -> i.getMyField()).distinct().collect(Collectors.toList()); +// +// for (int i = 0; i< 100; ++i) +// { +// Field f1 = lf1.get(i), f2 = lf2.get(i); +// +// System.out.println(f1 + " <-> " + f2); +// } + // number of setfields + //List f1 = eone.processedFrames.stream().filter(f -> f.getMethod() == m1).collect(Collectors.toList()), + // f2 = etwo.processedFrames.stream().filter(f -> f.getMethod() == m2).collect(Collectors.toList()); + + //System.out.println(ll1); + } +}