hm
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -24,21 +24,21 @@
|
|||||||
<artifactId>commons-compress</artifactId>
|
<artifactId>commons-compress</artifactId>
|
||||||
<version>1.10</version>
|
<version>1.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<!-- <dependency>
|
||||||
<groupId>edu.ucla.sspace</groupId>
|
<groupId>edu.ucla.sspace</groupId>
|
||||||
<artifactId>sspace</artifactId>
|
<artifactId>sspace</artifactId>
|
||||||
<version>2.0.4</version>
|
<version>2.0.4</version>
|
||||||
</dependency>
|
</dependency>-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.4</version>
|
<version>2.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<!-- <dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.1</version>
|
<version>3.1</version>
|
||||||
</dependency>
|
</dependency>-->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ package net.runelite.deob;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import net.runelite.deob.deobfuscators.MethodInliner;
|
import net.runelite.deob.deobfuscators.MethodInliner;
|
||||||
import net.runelite.deob.deobfuscators.rename.Rename;
|
|
||||||
import net.runelite.deob.deobfuscators.UnusedMethods;
|
import net.runelite.deob.deobfuscators.UnusedMethods;
|
||||||
|
import net.runelite.deob.deobfuscators.rename.Rename2;
|
||||||
import net.runelite.deob.execution.Execution;
|
import net.runelite.deob.execution.Execution;
|
||||||
import net.runelite.deob.util.JarUtil;
|
import net.runelite.deob.util.JarUtil;
|
||||||
|
|
||||||
// XXX something to detect final fields and evaluate them
|
// 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
|
public class Deob
|
||||||
{
|
{
|
||||||
@@ -103,7 +105,7 @@ public class Deob
|
|||||||
ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")),
|
ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")),
|
||||||
group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar"));
|
group2 = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar"));
|
||||||
|
|
||||||
Rename rename = new Rename();
|
Rename2 rename = new Rename2();
|
||||||
rename.run(group1, group2);
|
rename.run(group1, group2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,13 @@ import java.util.List;
|
|||||||
|
|
||||||
public class Method
|
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_STATIC = 0x8;
|
||||||
|
public static final int ACC_FINAL = 0x10;
|
||||||
public static final int ACC_SYNCHRONIZED = 0x20;
|
public static final int ACC_SYNCHRONIZED = 0x20;
|
||||||
|
public static final int ACC_ABSTRACT = 0x400;
|
||||||
|
|
||||||
private Methods methods;
|
private Methods methods;
|
||||||
|
|
||||||
@@ -79,6 +84,11 @@ public class Method
|
|||||||
{
|
{
|
||||||
this.attributes = a;
|
this.attributes = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public short getAccessFlags()
|
||||||
|
{
|
||||||
|
return accessFlags;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,246 +1,246 @@
|
|||||||
package net.runelite.deob.deobfuscators.rename;
|
//package net.runelite.deob.deobfuscators.rename;
|
||||||
|
//
|
||||||
import edu.ucla.sspace.graph.Edge;
|
//import edu.ucla.sspace.graph.Edge;
|
||||||
import edu.ucla.sspace.graph.Graph;
|
//import edu.ucla.sspace.graph.Graph;
|
||||||
import edu.ucla.sspace.graph.isomorphism.IsomorphismTester;
|
//import edu.ucla.sspace.graph.isomorphism.IsomorphismTester;
|
||||||
import edu.ucla.sspace.graph.isomorphism.VF2IsomorphismTester;
|
//import edu.ucla.sspace.graph.isomorphism.VF2IsomorphismTester;
|
||||||
import java.util.HashMap;
|
//import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
//import java.util.HashSet;
|
||||||
import java.util.List;
|
//import java.util.List;
|
||||||
import java.util.Map;
|
//import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
//import java.util.Map.Entry;
|
||||||
import java.util.Optional;
|
//import java.util.Optional;
|
||||||
import java.util.Set;
|
//import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
//import java.util.stream.Collectors;
|
||||||
import net.runelite.deob.ClassGroup;
|
//import net.runelite.deob.ClassGroup;
|
||||||
import net.runelite.deob.Method;
|
//import net.runelite.deob.Method;
|
||||||
import net.runelite.deob.execution.Execution;
|
//import net.runelite.deob.execution.Execution;
|
||||||
import net.runelite.deob.execution.Frame;
|
//import net.runelite.deob.execution.Frame;
|
||||||
import net.runelite.deob.execution.MethodContext;
|
//import net.runelite.deob.execution.MethodContext;
|
||||||
|
//
|
||||||
public class Rename
|
//public class Rename
|
||||||
{
|
//{
|
||||||
private ClassGroup groupOne, groupTwo;
|
// private ClassGroup groupOne, groupTwo;
|
||||||
|
//
|
||||||
// respective executions
|
// // respective executions
|
||||||
//private Execution eone, etwo;
|
// //private Execution eone, etwo;
|
||||||
|
//
|
||||||
// old -> new object mapping
|
// // old -> new object mapping
|
||||||
private Map<Object, Object> objMap = new HashMap<>();
|
// private Map<Object, Object> objMap = new HashMap<>();
|
||||||
|
//
|
||||||
// methods which have been processed in the original
|
// // methods which have been processed in the original
|
||||||
private Set<Method> processed = new HashSet<>();
|
// private Set<Method> processed = new HashSet<>();
|
||||||
|
//
|
||||||
private static String cname(Method m) { return m.getMethods().getClassFile().getName(); }
|
// 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 mname(Method m) { return cname(m) + "." + m.getName(); }
|
||||||
|
//
|
||||||
private void compare(MethodContext m1, Graph g1, MethodContext m2, Graph g2)
|
// private void compare(MethodContext m1, Graph g1, MethodContext m2, Graph g2)
|
||||||
{
|
// {
|
||||||
Set<Edge> edges = new HashSet<>(g1.edges()); // edges in g1 not in g2
|
// Set<Edge> edges = new HashSet<>(g1.edges()); // edges in g1 not in g2
|
||||||
for (Edge e : (Set<Edge>) g2.edges())
|
// for (Edge e : (Set<Edge>) g2.edges())
|
||||||
{
|
// {
|
||||||
edges.remove(e);
|
// edges.remove(e);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
for (Edge e : edges)
|
// for (Edge e : edges)
|
||||||
{
|
// {
|
||||||
Method me1 = m1.getIdMap().get(e.from()).get(0);
|
// Method me1 = m1.getIdMap().get(e.from()).get(0);
|
||||||
Method me2 = m1.getIdMap().get(e.to()).get(0);
|
// Method me2 = m1.getIdMap().get(e.to()).get(0);
|
||||||
|
//
|
||||||
System.out.println("EDGE IN 1 NOT IN 2: " + mname(me1) + " -> " + mname(me2));
|
// System.out.println("EDGE IN 1 NOT IN 2: " + mname(me1) + " -> " + mname(me2));
|
||||||
|
//
|
||||||
Method om1 = m2.getIdMap().get(e.from()).get(0);
|
// Method om1 = m2.getIdMap().get(e.from()).get(0);
|
||||||
Method om2 = m2.getIdMap().get(e.to()).get(0);
|
// Method om2 = m2.getIdMap().get(e.to()).get(0);
|
||||||
|
//
|
||||||
System.out.println(" OTHER SIDE: " + mname(om1) + " -> " + mname(om2));
|
// System.out.println(" OTHER SIDE: " + mname(om1) + " -> " + mname(om2));
|
||||||
}
|
// }
|
||||||
//System.out.println(edges);
|
// //System.out.println(edges);
|
||||||
|
//
|
||||||
if (g2.order() == g1.order())
|
// if (g2.order() == g1.order())
|
||||||
{
|
// {
|
||||||
int[] v1 = g1.vertices().toPrimitiveArray(),
|
// int[] v1 = g1.vertices().toPrimitiveArray(),
|
||||||
v2 = g2.vertices().toPrimitiveArray();
|
// v2 = g2.vertices().toPrimitiveArray();
|
||||||
for (int i = 0; i < g1.order(); ++i)
|
// 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<Integer, Integer> mapping = isoTest.findIsomorphism(g1, g2);
|
|
||||||
Map<Integer, List<Method>> map1 = f1.getMethodCtx().getIdMap(), map2 = f2.getMethodCtx().getIdMap();
|
|
||||||
|
|
||||||
for (Entry<Integer, Integer> e : mapping.entrySet())
|
|
||||||
{
|
|
||||||
// if (e.getKey() == null || e.getValue() == null)
|
|
||||||
// {
|
// {
|
||||||
// assert e.getKey() == e.getValue();
|
// Method me1 = m1.getIdMap().get(v1[i]).get(0);
|
||||||
// continue;
|
// Method me2 = m2.getIdMap().get(v2[i]).get(0);
|
||||||
|
//
|
||||||
|
// System.out.println("VMATCH " + mname(me1) + " -> " + mname(me2));
|
||||||
// }
|
// }
|
||||||
|
// }
|
||||||
List<Method> i1 = map1.get(e.getKey());
|
// }
|
||||||
List<Method> i2 = map2.get(e.getValue());
|
//
|
||||||
|
// private boolean compare(Frame f1, Frame f2)
|
||||||
//assert i1.getClass() == i2.getClass();
|
// {
|
||||||
|
// Graph g1 = f1.getMethodCtx().getGraph(), g2 = f2.getMethodCtx().getGraph();
|
||||||
//InvokeInstruction ii1 = (InvokeInstruction) i1, ii2 = (InvokeInstruction) i2;
|
//
|
||||||
|
// IsomorphismTester isoTest = new /*Typed*/VF2IsomorphismTester();
|
||||||
//assert ii1.getMethods().size() == ii2.getMethods().size();
|
// if (g1.size() != g2.size() || g1.order() != g2.order() || !isoTest.areIsomorphic(g1, g2))
|
||||||
|
// {
|
||||||
assert i1.size() == i2.size();
|
// System.out.println("IN " + mname(f1.getMethod()) + " -> " + mname(f2.getMethod()));
|
||||||
|
// compare(f1.getMethodCtx(), g1, f2.getMethodCtx(), g2);
|
||||||
for (int i = 0; i < i1.size(); ++i)
|
// System.out.println("Not isomorphic " + g1.size() + " " + g2.size());
|
||||||
{
|
// return false;
|
||||||
Method m1 = i1.get(i), m2 = i2.get(i);
|
// }
|
||||||
|
//
|
||||||
// assert objMap.containsKey(m1) == false || objMap.get(m1) == m2;
|
// Map<Integer, Integer> mapping = isoTest.findIsomorphism(g1, g2);
|
||||||
objMap.put(m1, m2);
|
// Map<Integer, List<Method>> map1 = f1.getMethodCtx().getIdMap(), map2 = f2.getMethodCtx().getIdMap();
|
||||||
}
|
//
|
||||||
|
// for (Entry<Integer, Integer> e : mapping.entrySet())
|
||||||
System.out.println("MATCH " + i1.get(0).getName() + " -> " + i2.get(0).getName());
|
// {
|
||||||
}
|
//// if (e.getKey() == null || e.getValue() == null)
|
||||||
|
//// {
|
||||||
return true;
|
//// assert e.getKey() == e.getValue();
|
||||||
}
|
//// continue;
|
||||||
|
//// }
|
||||||
private void process(Method one, Method two)
|
//
|
||||||
{
|
// List<Method> i1 = map1.get(e.getKey());
|
||||||
Execution eone = new Execution(groupOne);
|
// List<Method> i2 = map2.get(e.getValue());
|
||||||
eone.setBuildGraph(true);
|
//
|
||||||
eone.setFollowInvokes(false);
|
// //assert i1.getClass() == i2.getClass();
|
||||||
eone.addMethod(one);
|
//
|
||||||
eone.run();
|
// //InvokeInstruction ii1 = (InvokeInstruction) i1, ii2 = (InvokeInstruction) i2;
|
||||||
|
//
|
||||||
Execution etwo = new Execution(groupTwo);
|
// //assert ii1.getMethods().size() == ii2.getMethods().size();
|
||||||
etwo.setBuildGraph(true);
|
//
|
||||||
etwo.setFollowInvokes(false);
|
// assert i1.size() == i2.size();
|
||||||
etwo.addMethod(two);
|
//
|
||||||
etwo.run();
|
// for (int i = 0; i < i1.size(); ++i)
|
||||||
|
// {
|
||||||
// get frames for respective methods
|
// Method m1 = i1.get(i), m2 = i2.get(i);
|
||||||
List<Frame> f1 = eone.processedFrames, f2 = etwo.processedFrames;
|
//
|
||||||
|
//// assert objMap.containsKey(m1) == false || objMap.get(m1) == m2;
|
||||||
f1 = f1.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList());
|
// objMap.put(m1, m2);
|
||||||
f2 = f2.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList());
|
// }
|
||||||
|
//
|
||||||
//List<Frame> f1 = eone.processedFrames.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList());
|
// System.out.println("MATCH " + i1.get(0).getName() + " -> " + i2.get(0).getName());
|
||||||
//List<Frame> f2 = etwo.processedFrames.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList());
|
// }
|
||||||
|
//
|
||||||
Frame p1 = null, p2 = null;
|
// return true;
|
||||||
outer:
|
// }
|
||||||
for (Frame fr1 : f1)
|
//
|
||||||
for (Frame fr2 : f2)
|
// private void process(Method one, Method two)
|
||||||
{
|
// {
|
||||||
if (p1 == null) p1 = fr1;
|
// Execution eone = new Execution(groupOne);
|
||||||
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.setBuildGraph(true);
|
||||||
// eone.setFollowInvokes(false);
|
// eone.setFollowInvokes(false);
|
||||||
// eone.populateInitialMethods();
|
// eone.addMethod(one);
|
||||||
// List<Method> initial1 = eone.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList());
|
|
||||||
// eone.run();
|
// eone.run();
|
||||||
//
|
//
|
||||||
// Execution etwo = new Execution(two);
|
// Execution etwo = new Execution(groupTwo);
|
||||||
// etwo.setBuildGraph(true);
|
// etwo.setBuildGraph(true);
|
||||||
// etwo.setFollowInvokes(false);
|
// etwo.setFollowInvokes(false);
|
||||||
// etwo.populateInitialMethods();
|
// etwo.addMethod(two);
|
||||||
// List<Method> initial2 = etwo.getInitialMethods().stream().sorted((m1, m2) -> m1.getName().compareTo(m2.getName())).collect(Collectors.toList());
|
|
||||||
// etwo.run();
|
// etwo.run();
|
||||||
//
|
//
|
||||||
// assert initial1.size() == initial2.size();
|
// // get frames for respective methods
|
||||||
|
// List<Frame> 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<Frame> f1 = eone.processedFrames.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList());
|
||||||
|
// //List<Frame> 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<Method> 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<Method> 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(
|
// for (Entry<Object, Object> e : objMap.entrySet())
|
||||||
one.findClass("client").findMethod("vmethod2999"),
|
// {
|
||||||
two.findClass("client").findMethod("vmethod2978")
|
// Method m1 = (Method) e.getKey();
|
||||||
);
|
// Method m2 = (Method) e.getValue();
|
||||||
|
//
|
||||||
for (;;)
|
// System.out.println("FINAL " + m1.getMethods().getClassFile().getName() + "." + m1.getName() + " -> " + m2.getMethods().getClassFile().getName() + "." + m2.getName());
|
||||||
{
|
// }
|
||||||
Optional next = objMap.keySet().stream()
|
//
|
||||||
.filter(m -> !processed.contains(m))
|
// System.out.println("done count " + objMap.size());
|
||||||
.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<Object, Object> 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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<Signature, Method> find(ClassFile cf)
|
||||||
|
{
|
||||||
|
Map<Signature, Method> 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<Signature, Method> one, Map<Signature, Method> 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<Vertex> 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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<Vertex> verticies = new ArrayList<>();
|
||||||
|
|
||||||
|
private Map<Object, Vertex> 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<Vertex> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Edge> edges = new HashSet<>();
|
||||||
|
|
||||||
|
private Collection<Vertex> 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<Edge> getEdges()
|
||||||
|
{
|
||||||
|
return edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void merge(Collection<Vertex> 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("<init>") != m2.getName().equals("<init>"))
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package net.runelite.deob.deobfuscators.rename.graph;
|
||||||
|
|
||||||
|
|
||||||
|
public enum VertexType
|
||||||
|
{
|
||||||
|
METHOD,
|
||||||
|
FIELD;
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import net.runelite.deob.Method;
|
|||||||
import net.runelite.deob.attributes.code.Instruction;
|
import net.runelite.deob.attributes.code.Instruction;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -14,7 +15,11 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
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.arithmetic.Encryption;
|
||||||
|
import net.runelite.deob.deobfuscators.rename.graph.Graph;
|
||||||
import org.apache.commons.collections4.map.MultiValueMap;
|
import org.apache.commons.collections4.map.MultiValueMap;
|
||||||
|
|
||||||
public class Execution
|
public class Execution
|
||||||
@@ -24,12 +29,12 @@ public class Execution
|
|||||||
processedFrames = new LinkedList<>();
|
processedFrames = new LinkedList<>();
|
||||||
public Set<Method> methods = new HashSet<>(); // all methods
|
public Set<Method> methods = new HashSet<>(); // all methods
|
||||||
public Set<Instruction> executed = new HashSet<>(); // executed instructions
|
public Set<Instruction> executed = new HashSet<>(); // executed instructions
|
||||||
private MultiValueMap<MIKey, Method> invokes = new MultiValueMap<>();
|
private MultiValueMap<InstructionContext, Method> invokes = new MultiValueMap<>();
|
||||||
private Encryption encryption;
|
private Encryption encryption;
|
||||||
public MultiValueMap<Instruction, InstructionContext> contexts = new MultiValueMap<>();
|
public MultiValueMap<Instruction, InstructionContext> contexts = new MultiValueMap<>();
|
||||||
private Map<Method, MethodContext> methodContexts = new HashMap<>();
|
private Map<Method, MethodContext> methodContexts = new HashMap<>();
|
||||||
private boolean buildGraph; // if true the frame graph is built and execution hasJumped also compares previous instructions
|
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)
|
public Execution(ClassGroup group)
|
||||||
{
|
{
|
||||||
@@ -45,16 +50,6 @@ public class Execution
|
|||||||
{
|
{
|
||||||
this.encryption = encryption;
|
this.encryption = encryption;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFollowInvokes()
|
|
||||||
{
|
|
||||||
return followInvokes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFollowInvokes(boolean followInvokes)
|
|
||||||
{
|
|
||||||
this.followInvokes = followInvokes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Method> getInitialMethods()
|
public List<Method> getInitialMethods()
|
||||||
{
|
{
|
||||||
@@ -101,27 +96,26 @@ public class Execution
|
|||||||
|
|
||||||
private boolean hasInvoked(InstructionContext from, Method to)
|
private boolean hasInvoked(InstructionContext from, Method to)
|
||||||
{
|
{
|
||||||
Frame frame = from.getFrame();
|
Collection<Method> methods = invokes.getCollection(from);
|
||||||
MIKey key = new MIKey(frame.prevVertex.intValue(), from);
|
|
||||||
Collection<Method> methods = invokes.getCollection(key);
|
|
||||||
if (methods != null && methods.contains(to))
|
if (methods != null && methods.contains(to))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
invokes.put(key, to);
|
invokes.put(from, to);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFrame(Frame frame)
|
private void addFrame(Frame frame)
|
||||||
{
|
{
|
||||||
frames.add(0, frame);
|
frames.add(frame);
|
||||||
|
//frames.add(0, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invoke(InstructionContext from, Method to)
|
public void invoke(InstructionContext from, Method to)
|
||||||
{
|
{
|
||||||
Frame frame = from.getFrame();
|
Frame frame = from.getFrame();
|
||||||
|
|
||||||
if (!this.isFollowInvokes() && !to.isStatic())
|
// if (!this.isFollowInvokes() && !to.isStatic())
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
if (hasInvoked(from, to))
|
if (hasInvoked(from, to))
|
||||||
return;
|
return;
|
||||||
@@ -161,16 +155,16 @@ public class Execution
|
|||||||
assert frame.isExecuting();
|
assert frame.isExecuting();
|
||||||
frame.execute();
|
frame.execute();
|
||||||
|
|
||||||
if (!frame.isExecuting())
|
// if (!frame.isExecuting())
|
||||||
{
|
// {
|
||||||
//assert frames.get(0) == frame;
|
assert frames.get(0) == frame;
|
||||||
frames.remove(frame);
|
frames.remove(frame);
|
||||||
processedFrames.add(frame);
|
processedFrames.add(frame);
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
// another frame takes priority
|
// // another frame takes priority
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Processed " + fcount + " frames");
|
System.out.println("Processed " + fcount + " frames");
|
||||||
@@ -201,4 +195,39 @@ public class Execution
|
|||||||
{
|
{
|
||||||
this.buildGraph = buildGraph;
|
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<Method> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import net.runelite.deob.attributes.code.Instructions;
|
|||||||
import net.runelite.deob.pool.NameAndType;
|
import net.runelite.deob.pool.NameAndType;
|
||||||
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
|
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.ReturnInstruction;
|
||||||
import org.apache.commons.lang3.mutable.MutableInt;
|
|
||||||
|
|
||||||
public class Frame
|
public class Frame
|
||||||
{
|
{
|
||||||
@@ -23,10 +22,7 @@ public class Frame
|
|||||||
private Variables variables;
|
private Variables variables;
|
||||||
private List<InstructionContext> instructions = new ArrayList<>(); // instructions executed in this frame
|
private List<InstructionContext> instructions = new ArrayList<>(); // instructions executed in this frame
|
||||||
private MethodContext ctx;
|
private MethodContext ctx;
|
||||||
protected MutableInt prevVertex = new MutableInt(-1);
|
protected Method nonStatic; // next non static method up the stack
|
||||||
//protected int prevVertex = -1;
|
|
||||||
//private List<Method> prevInvokes;
|
|
||||||
private Frame from;
|
|
||||||
|
|
||||||
public Frame(Execution execution, Method method)
|
public Frame(Execution execution, Method method)
|
||||||
{
|
{
|
||||||
@@ -38,6 +34,7 @@ public class Frame
|
|||||||
stack = new Stack(code.getMaxStack());
|
stack = new Stack(code.getMaxStack());
|
||||||
variables = new Variables(code.getMaxLocals());
|
variables = new Variables(code.getMaxLocals());
|
||||||
ctx = execution.getMethodContext(method);
|
ctx = execution.getMethodContext(method);
|
||||||
|
nonStatic = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize()
|
public void initialize()
|
||||||
@@ -63,12 +60,15 @@ public class Frame
|
|||||||
// initialize frame from invoking context
|
// initialize frame from invoking context
|
||||||
assert ctx.getInstruction() instanceof InvokeInstruction;
|
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;
|
//assert this.nonStatic == null;
|
||||||
from = ctx.getFrame();
|
this.nonStatic = ctx.getFrame().nonStatic;
|
||||||
this.ctx = ctx.getFrame().ctx; // share ctx if this method is static
|
//assert from == null;
|
||||||
this.prevVertex = ctx.getFrame().prevVertex;
|
//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]
|
// 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.stack = new Stack(other.stack);
|
||||||
this.variables = new Variables(other.variables);
|
this.variables = new Variables(other.variables);
|
||||||
this.ctx = other.ctx;
|
this.ctx = other.ctx;
|
||||||
this.prevVertex = new MutableInt(other.prevVertex);
|
//this.prevVertex = new MutableInt(other.prevVertex);
|
||||||
//this.prevInvokes = other.prevInvokes;
|
//this.prevInvokes = other.prevInvokes;
|
||||||
from = other.from;
|
nonStatic = other.nonStatic;
|
||||||
|
// from = other.from;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Frame dup()
|
public Frame dup()
|
||||||
@@ -175,10 +176,6 @@ public class Frame
|
|||||||
{
|
{
|
||||||
Instruction oldCur = cur;
|
Instruction oldCur = cur;
|
||||||
|
|
||||||
if (cur instanceof ReturnInstruction)
|
|
||||||
if (processReturn())
|
|
||||||
break;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cur.execute(this);
|
cur.execute(this);
|
||||||
@@ -211,7 +208,7 @@ public class Frame
|
|||||||
if (!executing)
|
if (!executing)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ctx.buildGraph(this, oldCur);
|
execution.buildGraph(this, oldCur);
|
||||||
|
|
||||||
if (oldCur == cur)
|
if (oldCur == cur)
|
||||||
{
|
{
|
||||||
@@ -224,12 +221,12 @@ public class Frame
|
|||||||
/* jump */
|
/* jump */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!execution.frames.isEmpty() && execution.frames.get(0) != this)
|
// if (!execution.frames.isEmpty() && execution.frames.get(0) != this)
|
||||||
{
|
// {
|
||||||
stop(); // the prev frame must be an invokestatic?
|
// stop(); // the prev frame must be an invokestatic?
|
||||||
assert execution.frames.get(0).getMethod().isStatic();
|
// assert execution.frames.get(0).getMethod().isStatic();
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +264,7 @@ public class Frame
|
|||||||
assert to.getInstructions() == method.getCode().getInstructions();
|
assert to.getInstructions() == method.getCode().getInstructions();
|
||||||
assert method.getCode().getInstructions().getInstructions().contains(to);
|
assert method.getCode().getInstructions().getInstructions().contains(to);
|
||||||
|
|
||||||
if (ctx.hasJumped(prevVertex, from, to))
|
if (ctx.hasJumped(from, to))
|
||||||
{
|
{
|
||||||
executing = false;
|
executing = false;
|
||||||
return;
|
return;
|
||||||
@@ -276,24 +273,24 @@ public class Frame
|
|||||||
cur = to;
|
cur = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean processReturn()
|
// private boolean processReturn()
|
||||||
{
|
// {
|
||||||
if (this.getExecution().isFollowInvokes() || !this.getMethod().isStatic())
|
// if (this.getExecution().isFollowInvokes() || !this.getMethod().isStatic())
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
if (from == null)
|
// if (from == null)
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
assert !from.isExecuting();
|
// assert !from.isExecuting();
|
||||||
|
//
|
||||||
// update method, cur, stack, variables, from outermost method
|
// // update method, cur, stack, variables, from outermost method
|
||||||
this.method = from.method;
|
// this.method = from.method;
|
||||||
//this.executing = from.executing;
|
// //this.executing = from.executing;
|
||||||
this.cur = from.cur;
|
// this.cur = from.cur;
|
||||||
this.stack = new Stack(from.stack);
|
// this.stack = new Stack(from.stack);
|
||||||
this.variables = new Variables(from.variables);
|
// this.variables = new Variables(from.variables);
|
||||||
|
//
|
||||||
//stop(); // now that weve switched this should still be running
|
// //stop(); // now that weve switched this should still be running
|
||||||
return true; // this stops frame execution
|
// return true; // this stops frame execution
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,130 +1,130 @@
|
|||||||
package net.runelite.deob.execution;
|
package net.runelite.deob.execution;
|
||||||
|
|
||||||
import edu.ucla.sspace.graph.DirectedEdge;
|
import java.util.Arrays;
|
||||||
import edu.ucla.sspace.graph.Graph;
|
|
||||||
import edu.ucla.sspace.graph.SimpleDirectedEdge;
|
|
||||||
import edu.ucla.sspace.graph.SparseDirectedGraph;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import net.runelite.deob.Method;
|
import net.runelite.deob.Method;
|
||||||
import net.runelite.deob.attributes.code.Instruction;
|
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.instruction.types.InvokeInstruction;
|
||||||
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
|
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.collections4.map.MultiValueMap;
|
||||||
import org.apache.commons.lang3.mutable.MutableInt;
|
|
||||||
|
|
||||||
public class MethodContext
|
public class MethodContext
|
||||||
{
|
{
|
||||||
private Execution execution;
|
private Execution execution;
|
||||||
private MultiValueMap<MIKey, Instruction> visited = new MultiValueMap<>();
|
private MultiValueMap<InstructionContext, Instruction> visited = new MultiValueMap<>();
|
||||||
private IdGen ids = new IdGen();
|
//private IdGen ids = new IdGen();
|
||||||
private Map<Integer, List<Method>> idMap = new HashMap<>();
|
//private Map<Integer, List<Method>> idMap = new HashMap<>();
|
||||||
private Map<List<Method>, Integer> insMap = new HashMap<>();
|
//private Map<List<Method>, Integer> insMap = new HashMap<>();
|
||||||
private Graph graph = new SparseDirectedGraph();
|
// private Graph graph = new Graph();
|
||||||
|
|
||||||
public MethodContext(Execution execution)
|
public MethodContext(Execution execution)
|
||||||
{
|
{
|
||||||
this.execution = execution;
|
this.execution = execution;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Integer, List<Method>> getIdMap()
|
// public Map<Integer, List<Method>> getIdMap()
|
||||||
{
|
// {
|
||||||
return idMap;
|
// 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.
|
Collection<Instruction> i = visited.getCollection(from);
|
||||||
MIKey key = execution.isBuildGraph() ? new MIKey(prevVertex.intValue(), from) : new MIKey(-1, from);
|
|
||||||
Collection<Instruction> i = visited.getCollection(key);
|
|
||||||
if (i != null && i.contains(to))
|
if (i != null && i.contains(to))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
visited.put(key, to);
|
visited.put(from, to);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getIdFor(List<Method> i)
|
// private int getIdFor(List<Method> i)
|
||||||
{
|
// {
|
||||||
if (insMap.containsKey(i))
|
// if (insMap.containsKey(i))
|
||||||
return insMap.get(i);
|
// return insMap.get(i);
|
||||||
|
//
|
||||||
assert idMap.values().contains(i) == false;
|
// assert idMap.values().contains(i) == false;
|
||||||
|
//
|
||||||
int id = ids.get();
|
// int id = ids.get();
|
||||||
|
//
|
||||||
//graph.add(id);
|
// //graph.add(id);
|
||||||
|
//
|
||||||
this.idMap.put(id, i);
|
// this.idMap.put(id, i);
|
||||||
this.insMap.put(i, id);
|
// this.insMap.put(i, id);
|
||||||
|
//
|
||||||
return id;
|
// return id;
|
||||||
}
|
// }
|
||||||
|
|
||||||
protected void buildGraph(Frame frame, Instruction i)
|
// protected void buildGraph(Frame frame, Instruction i)
|
||||||
{
|
// {
|
||||||
if (!execution.isBuildGraph())
|
// if (!execution.isBuildGraph())
|
||||||
return;
|
// return;
|
||||||
|
//
|
||||||
List<Method> methods;
|
// List<Object> to;
|
||||||
if (i instanceof InvokeInstruction)
|
// //List<Method> methods;
|
||||||
{
|
// if (i instanceof InvokeInstruction)
|
||||||
if (i instanceof InvokeStatic)
|
// {
|
||||||
return;
|
// if (i instanceof InvokeStatic)
|
||||||
|
// return;
|
||||||
InvokeInstruction ii = (InvokeInstruction) i;
|
//
|
||||||
|
// InvokeInstruction ii = (InvokeInstruction) i;
|
||||||
methods = ii.getMethods();
|
//
|
||||||
if (methods.isEmpty())
|
// List<Method> methods = ii.getMethods();
|
||||||
return;
|
// if (methods.isEmpty())
|
||||||
}
|
// return;
|
||||||
|
//
|
||||||
|
// to = (List) methods;
|
||||||
|
// }
|
||||||
// else if (i instanceof FieldInstruction)
|
// else if (i instanceof FieldInstruction)
|
||||||
// {
|
// {
|
||||||
// FieldInstruction fi = (FieldInstruction) i;
|
// FieldInstruction fi = (FieldInstruction) i;
|
||||||
//
|
//
|
||||||
// if (fi.getMyField() == null)
|
// if (fi.getMyField() == null)
|
||||||
// return;
|
// return;
|
||||||
|
//
|
||||||
|
// to = Arrays.asList(fi.getMyField());
|
||||||
// }
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (frame.prevVertex.intValue() == -1)
|
// to.stream().forEach(o -> graph.addEdge(frame.getMethod(), o));
|
||||||
{
|
//
|
||||||
int id = getIdFor(methods);
|
//// if (frame.prevVertex.intValue() == -1)
|
||||||
//int id = ids.get();
|
//// {
|
||||||
//graph.add(id);
|
//// int id = getIdFor(methods);
|
||||||
frame.prevVertex.setValue(id);
|
//// //int id = ids.get();
|
||||||
//this.idMap.put(id, i);
|
//// //graph.add(id);
|
||||||
return;
|
//// frame.prevVertex.setValue(id);
|
||||||
}
|
//// //this.idMap.put(id, i);
|
||||||
|
//// return;
|
||||||
int id = getIdFor(methods);
|
//// }
|
||||||
//int id = ids.get();
|
////
|
||||||
//graph.add(id);
|
//// int id = getIdFor(methods);
|
||||||
//idMap.put(id, i);
|
//// //int id = ids.get();
|
||||||
|
//// //graph.add(id);
|
||||||
if (frame.prevVertex.intValue() == id)
|
//// //idMap.put(id, i);
|
||||||
return;
|
////
|
||||||
|
//// if (frame.prevVertex.intValue() == id)
|
||||||
List<Method> from = this.idMap.get(frame.prevVertex.intValue()), to = this.idMap.get(id);
|
//// return;
|
||||||
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() +
|
//// DirectedEdge edge = new SimpleDirectedEdge(frame.prevVertex.intValue(), id);
|
||||||
" (" + frame.prevVertex.intValue() + " -> " + id + ")");
|
////
|
||||||
|
//// if (graph.contains(edge) == false)
|
||||||
DirectedEdge edge = new SimpleDirectedEdge(frame.prevVertex.intValue(), id);
|
//// {
|
||||||
graph.add(edge);
|
//// List<Method> 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() +
|
||||||
frame.prevVertex.setValue(id);
|
//// " to " + to.get(0).getMethods().getClassFile().getName() + "." + to.get(0).getName() +
|
||||||
}
|
//// " (" + frame.prevVertex.intValue() + " -> " + id + ")");
|
||||||
|
////
|
||||||
|
//// graph.add(edge);
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// frame.prevVertex.setValue(id);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.runelite.deob.signature;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -47,6 +48,15 @@ public class Signature
|
|||||||
Signature a = (Signature) other;
|
Signature a = (Signature) other;
|
||||||
return arguments.equals(a.arguments) && rv.equals(a.rv);
|
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
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
|
|||||||
@@ -1,134 +1,133 @@
|
|||||||
package net.runelite.deob.execution;
|
//package net.runelite.deob.execution;
|
||||||
|
//
|
||||||
import edu.ucla.sspace.graph.Graph;
|
//import net.runelite.deob.ClassGroup;
|
||||||
import net.runelite.deob.ClassGroup;
|
//import net.runelite.deob.ClassGroupFactory;
|
||||||
import net.runelite.deob.ClassGroupFactory;
|
//import net.runelite.deob.Method;
|
||||||
import net.runelite.deob.Method;
|
//import net.runelite.deob.attributes.Code;
|
||||||
import net.runelite.deob.attributes.Code;
|
//import net.runelite.deob.attributes.code.Instruction;
|
||||||
import net.runelite.deob.attributes.code.Instruction;
|
//import net.runelite.deob.attributes.code.Instructions;
|
||||||
import net.runelite.deob.attributes.code.Instructions;
|
//import net.runelite.deob.attributes.code.instructions.Goto;
|
||||||
import net.runelite.deob.attributes.code.instructions.Goto;
|
//import net.runelite.deob.attributes.code.instructions.IConst_0;
|
||||||
import net.runelite.deob.attributes.code.instructions.IConst_0;
|
//import net.runelite.deob.attributes.code.instructions.If0;
|
||||||
import net.runelite.deob.attributes.code.instructions.If0;
|
//import net.runelite.deob.attributes.code.instructions.InvokeStatic;
|
||||||
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
|
//import net.runelite.deob.attributes.code.instructions.NOP;
|
||||||
import net.runelite.deob.attributes.code.instructions.NOP;
|
//import net.runelite.deob.attributes.code.instructions.VReturn;
|
||||||
import net.runelite.deob.attributes.code.instructions.VReturn;
|
//import net.runelite.deob.deobfuscators.rename.graph.Graph;
|
||||||
import net.runelite.deob.signature.Signature;
|
//import org.junit.Assert;
|
||||||
import org.junit.Assert;
|
//import org.junit.Test;
|
||||||
import org.junit.Test;
|
//
|
||||||
|
//public class FrameTest
|
||||||
public class FrameTest
|
//{
|
||||||
{
|
// // invoke instruction,
|
||||||
// invoke instruction,
|
// // conditional jump out,
|
||||||
// conditional jump out,
|
// // both jump in,
|
||||||
// both jump in,
|
// // jump,
|
||||||
// jump,
|
// // invoke
|
||||||
// invoke
|
// // check that num edges = 4
|
||||||
// check that num edges = 4
|
// @Test
|
||||||
@Test
|
// public void testGraph()
|
||||||
public void testGraph()
|
// {
|
||||||
{
|
// ClassGroup group = ClassGroupFactory.generateGroup();
|
||||||
ClassGroup group = ClassGroupFactory.generateGroup();
|
// Code code = group.findClass("test").findMethod("func").getCode();
|
||||||
Code code = group.findClass("test").findMethod("func").getCode();
|
// Instructions ins = code.getInstructions();
|
||||||
Instructions ins = code.getInstructions();
|
//
|
||||||
|
// code.setMaxStack(1);
|
||||||
code.setMaxStack(1);
|
//
|
||||||
|
// Method void1 = group.findClass("test").findMethod("void1"),
|
||||||
Method void1 = group.findClass("test").findMethod("void1"),
|
// void2 = group.findClass("test").findMethod("void2"),
|
||||||
void2 = group.findClass("test").findMethod("void2"),
|
// void3 = group.findClass("test").findMethod("void3"),
|
||||||
void3 = group.findClass("test").findMethod("void3"),
|
// void4 = group.findClass("test").findMethod("void4");
|
||||||
void4 = group.findClass("test").findMethod("void4");
|
//
|
||||||
|
// NOP label1 = new NOP(ins),
|
||||||
NOP label1 = new NOP(ins),
|
// label2 = new NOP(ins),
|
||||||
label2 = new NOP(ins),
|
// label3 = new NOP(ins);
|
||||||
label3 = new NOP(ins);
|
//
|
||||||
|
// Instruction body[] = {
|
||||||
Instruction body[] = {
|
// new InvokeStatic(ins, void1.getPoolMethod()),
|
||||||
new InvokeStatic(ins, void1.getPoolMethod()),
|
//
|
||||||
|
// new IConst_0(ins),
|
||||||
new IConst_0(ins),
|
// new If0(ins, label1),
|
||||||
new If0(ins, label1),
|
//
|
||||||
|
// new InvokeStatic(ins, void2.getPoolMethod()),
|
||||||
new InvokeStatic(ins, void2.getPoolMethod()),
|
// new Goto(ins, label2),
|
||||||
new Goto(ins, label2),
|
//
|
||||||
|
// label1,
|
||||||
label1,
|
// new InvokeStatic(ins, void3.getPoolMethod()),
|
||||||
new InvokeStatic(ins, void3.getPoolMethod()),
|
//
|
||||||
|
// label2,
|
||||||
label2,
|
// // do something dumb
|
||||||
// do something dumb
|
//
|
||||||
|
// new Goto(ins, label3),
|
||||||
new Goto(ins, label3),
|
// label3,
|
||||||
label3,
|
//
|
||||||
|
// new InvokeStatic(ins, void4.getPoolMethod()),
|
||||||
new InvokeStatic(ins, void4.getPoolMethod()),
|
//
|
||||||
|
// new VReturn(ins)
|
||||||
new VReturn(ins)
|
// };
|
||||||
};
|
//
|
||||||
|
// for (Instruction i : body)
|
||||||
for (Instruction i : body)
|
// ins.addInstruction(i);
|
||||||
ins.addInstruction(i);
|
//
|
||||||
|
// Execution e = new Execution(group);
|
||||||
Execution e = new Execution(group);
|
// e.setBuildGraph(true);
|
||||||
e.setBuildGraph(true);
|
// e.populateInitialMethods();
|
||||||
e.populateInitialMethods();
|
// e.run();
|
||||||
e.run();
|
//
|
||||||
|
// Graph graph = e.processedFrames.get(0).getMethodCtx().getGraph();
|
||||||
Graph graph = e.processedFrames.get(0).getMethodCtx().getGraph();
|
// Assert.assertEquals(4, graph.size());
|
||||||
Assert.assertEquals(4, graph.size());
|
// }
|
||||||
}
|
//
|
||||||
|
// // invoke instruction,
|
||||||
// invoke instruction,
|
// // conditional jump out,
|
||||||
// conditional jump out,
|
// // both jump in,
|
||||||
// both jump in,
|
// // invoke
|
||||||
// invoke
|
// // check that num edges = 4
|
||||||
// check that num edges = 4
|
// @Test
|
||||||
@Test
|
// public void testGraph2()
|
||||||
public void testGraph2()
|
// {
|
||||||
{
|
// ClassGroup group = ClassGroupFactory.generateGroup();
|
||||||
ClassGroup group = ClassGroupFactory.generateGroup();
|
// Code code = group.findClass("test").findMethod("func").getCode();
|
||||||
Code code = group.findClass("test").findMethod("func").getCode();
|
// Instructions ins = code.getInstructions();
|
||||||
Instructions ins = code.getInstructions();
|
//
|
||||||
|
// code.setMaxStack(1);
|
||||||
code.setMaxStack(1);
|
//
|
||||||
|
// Method void1 = group.findClass("test").findMethod("void1"),
|
||||||
Method void1 = group.findClass("test").findMethod("void1"),
|
// void2 = group.findClass("test").findMethod("void2"),
|
||||||
void2 = group.findClass("test").findMethod("void2"),
|
// void3 = group.findClass("test").findMethod("void3"),
|
||||||
void3 = group.findClass("test").findMethod("void3"),
|
// void4 = group.findClass("test").findMethod("void4");
|
||||||
void4 = group.findClass("test").findMethod("void4");
|
//
|
||||||
|
// NOP label1 = new NOP(ins),
|
||||||
NOP label1 = new NOP(ins),
|
// label2 = new NOP(ins);
|
||||||
label2 = new NOP(ins);
|
//
|
||||||
|
// Instruction body[] = {
|
||||||
Instruction body[] = {
|
// new InvokeStatic(ins, void1.getPoolMethod()),
|
||||||
new InvokeStatic(ins, void1.getPoolMethod()),
|
//
|
||||||
|
// new IConst_0(ins),
|
||||||
new IConst_0(ins),
|
// new If0(ins, label1),
|
||||||
new If0(ins, label1),
|
//
|
||||||
|
// new InvokeStatic(ins, void2.getPoolMethod()),
|
||||||
new InvokeStatic(ins, void2.getPoolMethod()),
|
// new Goto(ins, label2),
|
||||||
new Goto(ins, label2),
|
//
|
||||||
|
// label1,
|
||||||
label1,
|
// new InvokeStatic(ins, void3.getPoolMethod()),
|
||||||
new InvokeStatic(ins, void3.getPoolMethod()),
|
//
|
||||||
|
// label2,
|
||||||
label2,
|
// // do something dumb
|
||||||
// do something dumb
|
//
|
||||||
|
// new InvokeStatic(ins, void4.getPoolMethod()),
|
||||||
new InvokeStatic(ins, void4.getPoolMethod()),
|
//
|
||||||
|
// new VReturn(ins)
|
||||||
new VReturn(ins)
|
// };
|
||||||
};
|
//
|
||||||
|
// for (Instruction i : body)
|
||||||
for (Instruction i : body)
|
// ins.addInstruction(i);
|
||||||
ins.addInstruction(i);
|
//
|
||||||
|
// Execution e = new Execution(group);
|
||||||
Execution e = new Execution(group);
|
// e.setBuildGraph(true);
|
||||||
e.setBuildGraph(true);
|
// e.populateInitialMethods();
|
||||||
e.populateInitialMethods();
|
// e.run();
|
||||||
e.run();
|
//
|
||||||
|
// Graph graph = e.processedFrames.get(0).getMethodCtx().getGraph();
|
||||||
Graph graph = e.processedFrames.get(0).getMethodCtx().getGraph();
|
// Assert.assertEquals(4, graph.size());
|
||||||
Assert.assertEquals(4, graph.size());
|
// }
|
||||||
}
|
//}
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user