Remove old graph stuff, all tests pass

This commit is contained in:
Adam
2016-02-13 22:51:11 -05:00
parent c1bd2d199e
commit 8f6efa7717
21 changed files with 9 additions and 2573 deletions

View File

@@ -17,7 +17,6 @@ import net.runelite.deob.deobfuscators.arithmetic.ModArith;
import net.runelite.deob.deobfuscators.arithmetic.MultiplicationDeobfuscator;
import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator;
import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator;
import net.runelite.deob.deobfuscators.rename.Rename2;
import net.runelite.deob.execution.Execution;
import net.runelite.deob.util.JarUtil;
@@ -107,9 +106,9 @@ public class Deob
{
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);
//
// Rename2 rename = new Rename2();
// rename.run(group1, group2);
}
public static boolean isObfuscated(String name)

View File

@@ -1,51 +0,0 @@
package net.runelite.deob.deobfuscators.rename;
import java.util.Objects;
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
public class ConstantWrapper
{
private Object object;
private PushConstantInstruction pci;
public ConstantWrapper(Object object, PushConstantInstruction pci)
{
this.object = object;
this.pci = pci;
}
@Override
public String toString()
{
return "constant " + object.getClass().getName() + " " + object + " from instruction " + pci;
}
@Override
public int hashCode()
{
int hash = 3;
hash = 53 * hash + Objects.hashCode(this.object);
return hash;
}
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final ConstantWrapper other = (ConstantWrapper) obj;
if (!Objects.equals(this.object, other.object))
{
return false;
}
return true;
}
}

View File

@@ -1,62 +0,0 @@
package net.runelite.deob.deobfuscators.rename;
import java.util.Objects;
import net.runelite.deob.Field;
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
import net.runelite.deob.signature.Type;
public class FieldWrapper
{
private static final int FIELD_MASK = Field.ACC_FINAL | Field.ACC_STATIC;
private FieldInstruction fi;
public Field field;
private Type type;
private short accessFlags;
public FieldWrapper(FieldInstruction fi ,Field field)
{
this.fi = fi;
this.field = field;
this.type = field.getType();
this.accessFlags = field.getAccessFlags();
}
@Override
public String toString()
{
return field.toString() + " access from instruction " + fi;
}
@Override
public int hashCode()
{
int hash = 3;
hash = 29 * hash + Objects.hashCode(this.type);
hash = 29 * hash + (this.accessFlags & FIELD_MASK);
return hash;
}
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final FieldWrapper other = (FieldWrapper) obj;
if (!Objects.equals(this.type, other.type))
{
return false;
}
if ((this.accessFlags & FIELD_MASK) != (other.accessFlags & FIELD_MASK))
{
return false;
}
return true;
}
}

View File

@@ -1,149 +0,0 @@
package net.runelite.deob.deobfuscators.rename;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.runelite.deob.Field;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.code.Instruction;
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.PushConstantInstruction;
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
import net.runelite.deob.pool.PoolEntry;
import net.runelite.deob.signature.Signature;
public class InstructionList
{
private final List<Instruction> instructions;
public InstructionList(List<Instruction> instructions)
{
this.instructions = instructions;
}
public boolean couldBeEqual(InstructionList other)
{
Multiset<Signature> sig1 = HashMultiset.create(),
sig2 = HashMultiset.create();
// check signatures and field types
instructions.stream().filter(i -> i instanceof InvokeInstruction).forEach(i -> {
assert !(i instanceof InvokeStatic);
InvokeInstruction iv = (InvokeInstruction) i;
for (Method m : iv.getMethods())
sig1.add(m.getDescriptor());
});
other.instructions.stream().filter(i -> i instanceof InvokeInstruction).forEach(i -> {
assert !(i instanceof InvokeStatic);
InvokeInstruction iv = (InvokeInstruction) i;
for (Method m : iv.getMethods())
sig2.add(m.getDescriptor());
});
if (!sig1.equals(sig2))
return false;
Set<FieldWrapper> type1 = new HashSet<>(),
type2 = new HashSet<>();
instructions.stream().filter(i -> i instanceof GetFieldInstruction).forEach(i -> {
GetFieldInstruction gfi = (GetFieldInstruction) i;
Field f = gfi.getMyField();
if (f != null)
type1.add(new FieldWrapper(gfi, f));
});
other.instructions.stream().filter(i -> i instanceof GetFieldInstruction).forEach(i -> {
GetFieldInstruction gfi = (GetFieldInstruction) i;
Field f = gfi.getMyField();
if (f != null)
type2.add(new FieldWrapper(gfi, f));
});
if (!type1.equals(type2))
{
for (FieldWrapper fw : type1)
{
if (!type2.contains(fw))
{
// 2726 -> 2738
System.out.println(fw + " not in type2");
for (FieldWrapper fw2 : type2)
{
if (fw2.field.getName().equals("field2738"))
{
int i= 5;
}
}
}
}
return false;
}
Multiset<FieldWrapper> ms1 = HashMultiset.create(),
ms2 = HashMultiset.create();
instructions.stream().filter(i -> i instanceof SetFieldInstruction).forEach(i -> {
SetFieldInstruction sfi = (SetFieldInstruction) i;
Field f = sfi.getMyField();
if (f != null)
ms1.add(new FieldWrapper(sfi, f));
});
other.instructions.stream().filter(i -> i instanceof SetFieldInstruction).forEach(i -> {
SetFieldInstruction sfi = (SetFieldInstruction) i;
Field f = sfi.getMyField();
if (f != null)
ms2.add(new FieldWrapper(sfi, f));
});
if (!ms1.equals(ms2))
return false;
Set<ConstantWrapper> constants1 = new HashSet<>(),
constants2 = new HashSet<>();
instructions.stream().filter(i -> i instanceof PushConstantInstruction).forEach(i -> {
PushConstantInstruction pci = (PushConstantInstruction) i;
PoolEntry e = pci.getConstant();
Object o = e.getObject();
if (o instanceof Integer || o instanceof Long)
return;
constants1.add(new ConstantWrapper(o, pci));
});
other.instructions.stream().filter(i -> i instanceof PushConstantInstruction).forEach(i -> {
PushConstantInstruction pci = (PushConstantInstruction) i;
PoolEntry e = pci.getConstant();
Object o = e.getObject();
if (o instanceof Integer || o instanceof Long)
return;
constants2.add(new ConstantWrapper(o, pci));
});
if (!constants1.equals(constants2))
{
for (ConstantWrapper o : constants1)
{
if (!constants2.contains(o))
{
System.out.println(o);
}
}
return false;
}
return true;
}
}

View File

@@ -1,246 +0,0 @@
//package net.runelite.deob.deobfuscators.rename;
//
//import edu.ucla.sspace.graph.Edge;
//import edu.ucla.sspace.graph.Graph;
//import edu.ucla.sspace.graph.isomorphism.IsomorphismTester;
//import edu.ucla.sspace.graph.isomorphism.VF2IsomorphismTester;
//import java.util.HashMap;
//import java.util.HashSet;
//import java.util.List;
//import java.util.Map;
//import java.util.Map.Entry;
//import java.util.Optional;
//import java.util.Set;
//import java.util.stream.Collectors;
//import net.runelite.deob.ClassGroup;
//import net.runelite.deob.Method;
//import net.runelite.deob.execution.Execution;
//import net.runelite.deob.execution.Frame;
//import net.runelite.deob.execution.MethodContext;
//
//public class Rename
//{
// private ClassGroup groupOne, groupTwo;
//
// // respective executions
// //private Execution eone, etwo;
//
// // old -> new object mapping
// private Map<Object, Object> objMap = new HashMap<>();
//
// // methods which have been processed in the original
// private Set<Method> processed = new HashSet<>();
//
// private static String cname(Method m) { return m.getMethods().getClassFile().getName(); }
// private static String mname(Method m) { return cname(m) + "." + m.getName(); }
//
// private void compare(MethodContext m1, Graph g1, MethodContext m2, Graph g2)
// {
// Set<Edge> edges = new HashSet<>(g1.edges()); // edges in g1 not in g2
// for (Edge e : (Set<Edge>) g2.edges())
// {
// edges.remove(e);
// }
//
// for (Edge e : edges)
// {
// Method me1 = m1.getIdMap().get(e.from()).get(0);
// Method me2 = m1.getIdMap().get(e.to()).get(0);
//
// System.out.println("EDGE IN 1 NOT IN 2: " + mname(me1) + " -> " + mname(me2));
//
// Method om1 = m2.getIdMap().get(e.from()).get(0);
// Method om2 = m2.getIdMap().get(e.to()).get(0);
//
// System.out.println(" OTHER SIDE: " + mname(om1) + " -> " + mname(om2));
// }
// //System.out.println(edges);
//
// if (g2.order() == g1.order())
// {
// int[] v1 = g1.vertices().toPrimitiveArray(),
// v2 = g2.vertices().toPrimitiveArray();
// for (int i = 0; i < g1.order(); ++i)
// {
// Method me1 = m1.getIdMap().get(v1[i]).get(0);
// Method me2 = m2.getIdMap().get(v2[i]).get(0);
//
// System.out.println("VMATCH " + mname(me1) + " -> " + mname(me2));
// }
// }
// }
//
// private boolean compare(Frame f1, Frame f2)
// {
// Graph g1 = f1.getMethodCtx().getGraph(), g2 = f2.getMethodCtx().getGraph();
//
// IsomorphismTester isoTest = new /*Typed*/VF2IsomorphismTester();
// if (g1.size() != g2.size() || g1.order() != g2.order() || !isoTest.areIsomorphic(g1, g2))
// {
// System.out.println("IN " + mname(f1.getMethod()) + " -> " + mname(f2.getMethod()));
// compare(f1.getMethodCtx(), g1, f2.getMethodCtx(), g2);
// System.out.println("Not isomorphic " + g1.size() + " " + g2.size());
// return false;
// }
//
// Map<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();
//// continue;
//// }
//
// List<Method> i1 = map1.get(e.getKey());
// List<Method> i2 = map2.get(e.getValue());
//
// //assert i1.getClass() == i2.getClass();
//
// //InvokeInstruction ii1 = (InvokeInstruction) i1, ii2 = (InvokeInstruction) i2;
//
// //assert ii1.getMethods().size() == ii2.getMethods().size();
//
// assert i1.size() == i2.size();
//
// for (int i = 0; i < i1.size(); ++i)
// {
// Method m1 = i1.get(i), m2 = i2.get(i);
//
//// assert objMap.containsKey(m1) == false || objMap.get(m1) == m2;
// objMap.put(m1, m2);
// }
//
// System.out.println("MATCH " + i1.get(0).getName() + " -> " + i2.get(0).getName());
// }
//
// return true;
// }
//
// private void process(Method one, Method two)
// {
// Execution eone = new Execution(groupOne);
// eone.setBuildGraph(true);
// eone.setFollowInvokes(false);
// eone.addMethod(one);
// eone.run();
//
// Execution etwo = new Execution(groupTwo);
// etwo.setBuildGraph(true);
// etwo.setFollowInvokes(false);
// etwo.addMethod(two);
// etwo.run();
//
// // get frames for respective methods
// List<Frame> f1 = eone.processedFrames, f2 = etwo.processedFrames;
//
// f1 = f1.stream().filter(f -> f.getMethod() == one).collect(Collectors.toList());
// f2 = f2.stream().filter(f -> f.getMethod() == two).collect(Collectors.toList());
//
// //List<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 (;;)
// {
// Optional next = objMap.keySet().stream()
// .filter(m -> !processed.contains(m))
// .findAny();
// if (!next.isPresent())
// break;
//
// Method m = (Method) next.get();
// Method m2 = (Method) objMap.get(m);
//
// if (m.getCode() == null || m2.getCode() == null)
// {
// processed.add(m);
// continue;
// }
//
// System.out.println("Scanning " + m.getMethods().getClassFile().getName() + "." + m.getName() + " -> " + m2.getMethods().getClassFile().getName() + "." + m2.getName());
// process(m, m2);
// processed.add(m);
// }
//
// for (Entry<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());
// }
//}

View File

@@ -1,728 +0,0 @@
package net.runelite.deob.deobfuscators.rename;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import net.runelite.deob.ClassFile;
import net.runelite.deob.ClassGroup;
import net.runelite.deob.Deob;
import net.runelite.deob.Field;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.Annotations;
import net.runelite.deob.attributes.AttributeType;
import net.runelite.deob.attributes.Attributes;
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.Graph;
import net.runelite.deob.deobfuscators.rename.graph.GraphBuilder;
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.execution.Frame;
import net.runelite.deob.execution.InstructionContext;
import net.runelite.deob.signature.Signature;
import net.runelite.deob.signature.Type;
import net.runelite.deob.util.JarUtil;
import net.runelite.deob.util.NameMappings;
public class Rename2
{
private Graph g1, g2;
private static String cname(Method m) { return m.getMethods().getClassFile().getName(); }
public 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 m0 = (Method) o0;
Method m1 = (Method) o1;
Method m2 = (Method) o2;
System.out.println("COLLISION on " + mname(m0) + ": " + 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;
}
private Map<Type, Field> findField(ClassFile cf)
{
Map<Type, Field> set = new HashMap<>();
Set collided = new HashSet();
for (Field f : cf.getFields().getFields())
{
if (f.isStatic())
continue;
Type t = f.getType();
if (set.containsKey(t) || collided.contains(t))
{
collided.add(t);
set.remove(t);
continue;
}
set.put(t, f);
}
return set;
}
private 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 mapClassFields(Map<Type, Field> one, Map<Type, Field> two)
{
if (!one.keySet().equals(two.keySet()))
return;
for (Type t : one.keySet())
{
Field f1 = one.get(t), f2 = two.get(t);
Vertex v1 = g1.getVertexFor(f1), v2 = g2.getVertexFor(f2);
v1.is(v2);
v2.is(v1);
System.out.println(fname(f1) + " is " + fname(f2));
}
}
private void mapDeobfuscatedMethods(ClassFile cf1, ClassFile cf2)
{
List<Method> m1 = cf1.getMethods().getMethods().stream().filter(m -> !Deob.isObfuscated(m.getName())).collect(Collectors.toList()),
m2 = cf2.getMethods().getMethods().stream().filter(m -> !Deob.isObfuscated(m.getName())).collect(Collectors.toList());
for (Method m : m1)
{
Optional<Method> opt = m2.stream().filter(m2m -> m.getName().equals(m2m.getName()) && m.getDescriptor().equals(m2m.getDescriptor())).findAny();
if (!opt.isPresent())
continue;
Vertex v1 = g1.getVertexFor(m);
Vertex v2 = g2.getVertexFor(opt.get());
v1.is(v2);
v2.is(v1);
System.out.println(mname(m) + " is " + mname(opt.get()));
executeMethod(m, opt.get());
}
}
private List<Field> getClientFields(ClassGroup group, Execution e)
{
Method clinit = group.findClass("client").findMethod("<clinit>");
Frame frame = e.processedFrames.stream().filter(f -> f.getMethod() == clinit).findFirst().get();
List<Field> fields = new ArrayList<>();
for (InstructionContext i : frame.getInstructions())
{
if (i.getInstruction() instanceof SetFieldInstruction)
{
SetFieldInstruction sfi = (SetFieldInstruction) i.getInstruction();
Field f = sfi.getMyField();
if (f != null)
fields.add(f);
}
}
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<Frame> 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<Vertex> solved = g1.getVerticies().stream().filter(v -> v.getOther() != null).collect(Collectors.toList());
for (Vertex s : solved)
{
Vertex other = s.getOther();
assert s.getGraph() != other.getGraph();
for (Edge e : s.getEdges())
{
assert e.getFrom() == s;
boolean b = false;
if (e.getTo().getOther() != null)
continue; // skip solved edges
Vertex v = e.getTo(); // end of edge in g1
// if (v.toString().equals("Vertex{object=static J class114.field1961}"))
// {
// b = true;
// }
List<Vertex> l = new ArrayList<>();
for (Edge e2 : other.getEdges())
{
if (e2.getTo().getOther() != null)
continue; // skip solved edges
if (e.toString().equals("Edge{from=Vertex{object=class139.mousePressed(Ljava/awt/event/MouseEvent;)V}, to=Vertex{object=static J class114.field1961}, type=SETFIELD}")
&& e2.toString().equals("Edge{from=Vertex{object=class139.mousePressed(Ljava/awt/event/MouseEvent;)V}, to=Vertex{object=static J class114.field1962}, type=SETFIELD}"))
b = true;
if (b && e.getType() == EdgeType.SETFIELD && e2.getType() == EdgeType.SETFIELD)
{
//Edge{from=Vertex{object=class139.mousePressed(Ljava/awt/event/MouseEvent;)V}, to=Vertex{object=static J class114.field1961}, type=SETFIELD}
//Edge{from=Vertex{object=class139.mousePressed(Ljava/awt/event/MouseEvent;)V}, to=Vertex{object=static J class114.field1962}, type=SETFIELD}
int i = 5;
}
if (!e.getTo().couldBeEqual(e2.getTo()))
{
// System.out.println(e.getTo() + " != " + e2.getTo());
continue;
}
if (!e.couldBeEqual(e2))
{
e.couldBeEqual(e2);
continue;
}
e.couldBeEqual(e2);
Vertex v2 = e2.getTo();
l.add(v2);
}
if (b)
v.merge(l);
else
v.merge(l);
}
}
}
static int pass = 0, asserts = 0;
private void executeNewMethods()
{
for (Vertex v : g1.getVerticies())
{
Vertex other = v.getOther();
if (other == null || !(v.getObject() instanceof Method))
continue;
try
{
executeMethod((Method) v.getObject(), (Method) other.getObject());
++pass;
}
catch (Exception | AssertionError ex)
{
ex.printStackTrace();
++asserts;
}
}
}
static int count = 0;
private Set<Method> executed = new HashSet<>();
private void executeMethod(Method m1, Method m2)
{
if (executed.contains(m1))
return;
executed.add(m1);
// assert (m1.getCode() == null) == (m2.getCode() == null);
//
// if (m1.getCode() == null)
// return;
//
if (!MappingExecutorUtil.isMappable(m1, m2))
return;
if (m1.getName().equals("<clinit>") || m1.getName().equals("<init>"))
return;
ParallelExecutorMapping mapping = MappingExecutorUtil.map(m1, m2);
System.out.println("EXEC " + count++ + " " + mname(m1) + " " + mname(m2) + " " + mapping);
for (Entry<Object, Object> e : mapping.getMap().entrySet())
{
if (e.getKey() instanceof Method)
{
try
{
executeMethod((Method) e.getKey(), (Method) e.getValue());
++pass;
}
catch (Exception | AssertionError ex)
{
ex.printStackTrace();
++asserts;
}
Method m = (Method) e.getKey();
if (m.isStatic())
{
// we can map execute these, though.
continue;
}
}
Vertex v1 = g1.getVertexFor(e.getKey()),
v2 = g2.getVertexFor(e.getValue());
v1.is(v2);
v2.is(v1);
}
// XXX next is use mappings. and then use executeMethod() on more than just the initial method mappings
}
public NameMappings run(ClassGroup one, ClassGroup two)
{
Execution eone = new Execution(one);
//eone.setBuildGraph(true);
eone.populateInitialMethods();
eone.run();
Execution etwo = new Execution(two);
//etwo.setBuildGraph(true);
etwo.populateInitialMethods();
etwo.run();
g1 = GraphBuilder.build(one);
g2 = GraphBuilder.build(two);
// System.out.println(eone.getGraph());
// System.out.println(etwo.getGraph());
for (int i = 0; i < 250; ++i)
{
ClassFile c1 = one.findClass("class" + i);
ClassFile c2 = two.findClass("class" + i);
if (c1 == null || c2 == null)
continue;
Map m1 = this.find(c1);
Map m2 = this.find(c2);
mapClassMethods(m1, m2);
mapDeobfuscatedMethods(c1, c2);
m1 = findField(c1);
m2 = findField(c2);
mapClassFields(m1, m2);
}
ClassFile cf1 = one.findClass("client"), cf2 = two.findClass("client");
mapDeobfuscatedMethods(cf1, cf2);
List<Field> fl1 = getClientFields(one, eone);
List<Field> fl2 = getClientFields(two, etwo);
for (int i = 0; i < Math.min(fl1.size(), fl2.size()); ++i)
{
Field f1 = fl1.get(i), f2 = fl2.get(i);
Vertex v1 = g1.getVertexFor(f1);
Vertex v2 = g2.getVertexFor(f2);
v1.is(v2);
v2.is(v1);
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<Vertex> reachable = g1.reachableVerticiesFromSolvedVerticies();
for (Vertex v : g1.getVerticies())
if (!reachable.contains(v))
{
System.out.println("unreachable " + v);
}
for (;;)
{
int before = g1.solved(null);
System.out.println("Before " + before);
solve();
g1.getVerticies().forEach(v -> v.finish());
executeNewMethods();
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));
List<Edge> unsolved = new ArrayList<>();
//Vertex stored = null;
for (Vertex v : g1.getVerticies())
{
if (v.getOther() == null)
continue;
//if (v.getObject() instanceof Method) continue;
//assert stored == null;
//stored = v;
for (Edge e : v.getEdges())
{
if (e.getTo().getOther() == null)
{
unsolved.add(e);
if (e.getType() == EdgeType.SETFIELD)
System.out.println("Edge " + e + " is unsolved");
}
}
}
for (EdgeType t : EdgeType.values())
{
long count = unsolved.stream().filter(e -> e.getType() == t).count();
if (count >0)
System.out.println(t + " " + count);
}
// NameMappings col = buildCollisionMap(one, two);
// rename(col, two);
//
// NameMappings mappings = buildMappings(one, two); // two -> one
//
// show(mappings);
System.out.println("Solved methods "+ g1.solved(VertexType.METHOD) + ", solved fields " + g1.solved(VertexType.FIELD) + ", unsolved methods " +g1.unsolved(VertexType.METHOD) + ", unsolved fields " + g1.unsolved(VertexType.FIELD));
System.out.println("asserts " + asserts + ", pass " + pass);
//rename(mappings, two);
// for (Vertex v : g1.getVerticies())
// {
//// if (v.getOther() != null)
//// System.out.println(v.getObject() + " -> " + v.getOther().getOther());
//// else
// if (v.getObject() instanceof Field)
// System.out.println(v.getObject() + " -> unk");
// }
try
{
JarUtil.saveJar(two, new File("d:/rs/07/adamout.jar"));
}
catch (IOException ex)
{
Logger.getLogger(Rename2.class.getName()).log(Level.SEVERE, null, ex);
}
//checkExports(one);
return null;
}
private void show(NameMappings mappings)
{
for (Entry<Object, String> e : mappings.getMap().entrySet())
{
Object o = e.getKey();
String n = e.getValue();
if (o instanceof net.runelite.deob.pool.Method)
{
net.runelite.deob.pool.Method m = (net.runelite.deob.pool.Method) o;
System.out.println("FINAL " + n + " -> " + m.getNameAndType().getName());
}
else if (o instanceof net.runelite.deob.pool.Field)
{
net.runelite.deob.pool.Field f = (net.runelite.deob.pool.Field) o;
System.out.println("FINAL " + n + " -> " + f.getNameAndType().getName());
}
}
System.out.println("Mappins size " + mappings.getMap().size());
}
private NameMappings buildCollisionMap(ClassGroup one, ClassGroup two)
{
NameMappings mappings = new NameMappings();
int count = 0;
for (ClassFile cf : two.getClasses())
{
for (Method m : cf.getMethods().getMethods())
{
if (m.isStatic() && !m.getName().equals("<clinit>"))
continue;
Vertex v = g2.getVertexFor(m);
Vertex other = v.getOther();
if (m.getName().equals("<init>") || m.getName().equals("<clinit>"))
continue;
if (other == null)
continue;
Method m2 = (Method) other.getObject();
if (m.getName().equals(m2.getName()))
continue; // already correct
Method existingMethod = cf.findMethod(m2.getName());
if (existingMethod != null)
{
mappings.map(existingMethod.getPoolMethod(), "collidedMethod" + count++);
}
}
// for (Field f : cf.getFields().getFields())
// {
// Vertex v = g2.getVertexFor(f);
// Vertex other = v.getOther();
//
// if (other == null)
// continue;
//
// Field f2 = (Field) other.getObject();
//
// Field existingField = cf.findField(f2.getName());
// if (existingField != null)
// mappings.map(existingField.getPoolField(), "collidedField" + count++);
// }
}
return mappings;
}
private NameMappings buildMappings(ClassGroup one, ClassGroup two)
{
NameMappings mappings = new NameMappings();
for (ClassFile cf : two.getClasses())
{
for (Method m : cf.getMethods().getMethods())
{
if (m.isStatic() && !m.getName().equals("<clinit>"))
continue;
Vertex v = g2.getVertexFor(m);
Vertex other = v.getOther();
if (m.getName().equals("<init>") || m.getName().equals("<clinit>"))
continue;
if (other == null)
continue;
Method m2 = (Method) other.getObject();
if (!m.getName().equals(m2.getName()))
{
Method existingMethod = cf.findMethod(m2.getName());
assert existingMethod == null;
}
mappings.map(m.getPoolMethod(), m2.getName());
}
// for (Field f : cf.getFields().getFields())
// {
// Vertex v = g2.getVertexFor(f);
// Vertex other = v.getOther();
//
// if (other == null)
// continue;
//
// Field f2 = (Field) other.getObject();
//
// Field existingField = cf.findField(f2.getName());
// assert existingField == null;
//
// mappings.map(f.getPoolField(), f2.getName());
// }
}
return mappings;
}
private void rename(NameMappings mappings, ClassGroup group)
{
Renamer renamer = new Renamer(mappings);
renamer.run(group);
}
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
private boolean isExported(Attributes attr)
{
Annotations an = (Annotations) attr.findType(AttributeType.RUNTIMEVISIBLEANNOTATIONS);
if (an == null)
return false;
for (Annotation a : an.getAnnotations())
{
if (a.getType().equals(EXPORT))
{
return true;
}
}
return false;
}
private void checkExports(ClassGroup one)
{
for (ClassFile cf : one.getClasses())
{
for (Field f : cf.getFields().getFields())
{
if (!isExported(f.getAttributes()))
continue;
Vertex v = g1.getVertexFor(f);
assert v != null;
if (v.getOther() == null)
{
System.out.println("Unsolved exported field " + f);
}
}
for (Method m : cf.getMethods().getMethods())
{
if (!isExported(m.getAttributes()))
continue;
Vertex v = g1.getVertexFor(m);
assert v != null;
if (v.getOther() == null)
{
System.out.println("Unsolved exported method " + m);
}
}
}
}
}

View File

@@ -1,407 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import net.runelite.deob.Field;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.code.Instruction;
import net.runelite.deob.attributes.code.instruction.types.DupInstruction;
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.LVTInstruction;
import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction;
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
import net.runelite.deob.attributes.code.instructions.NewArray;
import net.runelite.deob.execution.InstructionContext;
import net.runelite.deob.execution.StackContext;
import net.runelite.deob.execution.VariableContext;
import net.runelite.deob.execution.Variables;
public class Edge
{
private final InstructionContext ins;
private final Vertex from, to;
private final EdgeType type;
private int weight;
public Edge(InstructionContext ins, Vertex from, Vertex to, EdgeType type)
{
this.ins = ins;
this.from = from;
this.to = to;
this.type = type;
assert from.getGraph() == to.getGraph();
}
public InstructionContext getIns()
{
return ins;
}
public Vertex getFrom()
{
return from;
}
public Vertex getTo()
{
return to;
}
public EdgeType getType()
{
return type;
}
public void increase()
{
++weight;
}
public int getWeight()
{
return weight;
}
@Override
public String toString()
{
return "Edge{" + "from=" + from + ", to=" + to + ", type=" + type + '}';
}
@Override
public int hashCode()
{
int hash = 5;
hash = 89 * hash + Objects.hashCode(this.from);
hash = 89 * hash + Objects.hashCode(this.to);
hash = 89 * hash + Objects.hashCode(this.type);
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;
}
if (this.type != other.type)
{
return false;
}
return true;
}
public boolean couldBeEqual(Edge other)
{
if (this.type != other.type)
return false;
if (this.type == EdgeType.SETFIELD)// || this.type == EdgeType.SETFIELD_FROM)
{
// if (!compareSetField(getGraph(), other.getGraph(),
// (Field) this.getTo().getObject(), (Field) other.getTo().getObject(),
// other.getIns()))
// return false;
}
// if (this.weight != other.weight)
// return false;
return true;
}
private InstructionContext resolve(
InstructionContext ctx,
StackContext from // pushed from ctx
)
{
if (ctx.getInstruction() instanceof SetFieldInstruction)
{
StackContext s = ctx.getPops().get(0);
return resolve(s.getPushed(), s);
}
if (ctx.getInstruction() instanceof DupInstruction)
{
DupInstruction d = (DupInstruction) ctx.getInstruction();
StackContext s = d.getOriginal(from);
return resolve(s.getPushed(), s);
}
if (ctx.getInstruction() instanceof LVTInstruction)
{
LVTInstruction lvt = (LVTInstruction) ctx.getInstruction();
Variables variables = ctx.getVariables();
if (lvt.store())
{
StackContext s = ctx.getPops().get(0); // is this right?
return resolve(s.getPushed(), s);
}
else
{
VariableContext vctx = variables.get(lvt.getVariableIndex()); // variable being loaded
assert vctx != null;
InstructionContext storedCtx = vctx.getInstructionWhichStored();
if (storedCtx == null)
return ctx; // initial parameter
if (vctx.isIsParameter())
return ctx; // parameter (storedCtx is invoking instruction in another frame). this lvt index is fixed.
return resolve(storedCtx, null);
}
}
return ctx;
}
private List<InstructionContext> resolveUp(
List<InstructionContext> ctxs,
StackContext from // popped by ctxs
)
{
List<InstructionContext> list = new ArrayList<>();
for (InstructionContext ctx : ctxs)
{
if (ctx.getInstruction() instanceof DupInstruction)
{
DupInstruction d = (DupInstruction) ctx.getInstruction();
//StackContext s = d.
//return resolve(s.getPushed(), s);
}
list.add(ctx);
}
return list;
// if (ctx.getInstruction() instanceof SetFieldInstruction)
// {
// StackContext s = ctx.getPops().get(0);
// return resolve(s.getPushed(), s);
// }
//
//
// if (ctx.getInstruction() instanceof LVTInstruction)
// {
// LVTInstruction lvt = (LVTInstruction) ctx.getInstruction();
// Variables variables = ctx.getVariables();
//
// if (lvt.store())
// {
// StackContext s = ctx.getPops().get(0); // is this right?
// return resolve(s.getPushed(), s);
// }
// else
// {
// VariableContext vctx = variables.get(lvt.getVariableIndex()); // variable being loaded
// assert vctx != null;
//
// InstructionContext storedCtx = vctx.getInstructionWhichStored();
// if (storedCtx == null)
// return ctx; // parameter?
//
// return resolve(storedCtx, null);
// }
// }
// return ctx;
}
private boolean compareSetField(Graph g1, Graph g2, Field field1, Field field2, InstructionContext other)
{
InstructionContext thisp = resolve(ins.getPops().get(0).getPushed(), ins.getPops().get(0)),
otherp = resolve(other.getPops().get(0).getPushed(), other.getPops().get(0));
return couldBeEqual(g1, g2, field1, field2, thisp, otherp, null);
}
private boolean couldBeEqual(Graph g1, Graph g2, Field field1, Field field2, InstructionContext one, InstructionContext two, InstructionContext from)
{
Instruction i1 = one.getInstruction(), i2 = two.getInstruction();
if (i1 instanceof LVTInstruction && i2 instanceof LVTInstruction)
{
LVTInstruction l1 = (LVTInstruction) i1, l2 = (LVTInstruction) i2;
assert !l1.store();
assert !l2.store();
VariableContext v1 = one.getVariables().get(l1.getVariableIndex()),
v2 = two.getVariables().get(l2.getVariableIndex());
assert v1.isIsParameter();
assert v2.isIsParameter();
// resolve() resolves these unless they are parameters, so compare indexes
if (l1.getVariableIndex() != l2.getVariableIndex())
return false;
return v1.getType().equals(v2.getType());
}
if (i1 instanceof NewArray && i2 instanceof NewArray)
{
NewArray a1 = (NewArray) i1, a2 = (NewArray) i2;
if (a1.getArrayType() != a2.getArrayType())
return false;
}
// XXX check for invokestatic vs.
if (i1 instanceof InvokeInstruction && i2 instanceof InvokeInstruction)
{
InvokeInstruction ii1 = (InvokeInstruction) i1, ii2 = (InvokeInstruction) i2;
List<Method> methods1 = ii1.getMethods(), methods2 = ii2.getMethods();
if (methods1.size() != methods2.size())
{
return false;
}
if (methods1.isEmpty())
{
// compare pool Method
return ii1.getMethod().equals(ii2.getMethod());
}
Method m1 = methods1.get(0), m2 = methods2.get(0);
if (!m1.getDescriptor().equals(m2.getDescriptor()))
return false;
}
else if (i1 instanceof InvokeStatic || i2 instanceof InvokeStatic)
{
return true;
}
if (i1 instanceof FieldInstruction && i2 instanceof FieldInstruction)
{
assert i1 instanceof GetFieldInstruction;
assert i2 instanceof GetFieldInstruction;
GetFieldInstruction gf1 = (GetFieldInstruction) i1, gf2 = (GetFieldInstruction) i2;
Field f1 = gf1.getMyField(), f2 = gf2.getMyField();
if ((f1 != null) != (f2 != null))
return false;
//if (f1 == null || f2 == null)
// return
if (!f1.getType().equals(f2.getType()))
return false;
// lookup already solved fields.
Vertex v1 = g1.getVertexFor(f1), v2 = g2.getVertexFor(f2); // vertex of fields whose value is being set to
// get solved field
v1 = v1.getOther();
v2 = v2.getOther();
if ((v1 != null) != (v2 != null))
return false;
if (v1 != null || v2 != null)
{
if (v1.getObject() != f2 || v2.getObject() != f1)
return false;
}
}
if (i1 instanceof PushConstantInstruction && i2 instanceof PushConstantInstruction)
{
PushConstantInstruction pc1 = (PushConstantInstruction) i1, pc2 = (PushConstantInstruction) i2;
return pc1.getConstant().equals(pc2.getConstant());
}
if (!i1.getClass().equals(i2.getClass()))
{
return false;
}
// check down
assert one.getPops().size() == two.getPops().size();
for (int i = 0; i < one.getPops().size(); ++i)
{
StackContext s1 = one.getPops().get(i), s2 = two.getPops().get(i);
if (resolve(s1.getPushed(), s1) == from)
continue;
if (!couldBeEqual(
g1, g2,
field1, field2,
resolve(s1.getPushed(), s1),
resolve(s2.getPushed(), s2),
one
))
return false;
}
// check up
// assert one.getPushes().size() == two.getPushes().size();
// for (int i = 0; i < one.getPushes().size(); ++i)
// {
// StackContext s1 = one.getPushes().get(i), s2 = two.getPushes().get(i);
// List<InstructionContext> p1 = s1.getPopped(), p2 = s2.getPopped(); // instructions which popped the push
//
// assert p1.size() == p2.size();
//
// //resolveUp(p1, s1);
//
// for (int j = 0; j < p1.size(); ++i)
// {
// InstructionContext ic1 = p1.get(j), ic2 = p2.get(j);
//
// if (from == ic1)
// continue;
//
//// resolveUp(ic1, s1);
//// resolveUp(ic2, s2);
//
// if (!couldBeEqual(
// field1, field2,
// ic1, ic2,
// one
// )) {}
// //return false;
// }
// }
return true;
}
private Graph getGraph()
{
assert from.getGraph() == to.getGraph();
return from.getGraph();
}
}

View File

@@ -1,24 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
public enum EdgeType
{
INVOKE,
GETFIELD,
SETFIELD,
INVOKED_FROM,
GETFIELD_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;
}

View File

@@ -1,40 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
import net.runelite.deob.attributes.code.Instruction;
import net.runelite.deob.execution.InstructionContext;
public class FieldEdge extends Edge
{
private int id;
public FieldEdge(InstructionContext 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();
}
}

View File

@@ -1,129 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Graph
{
private List<Vertex> verticies = new ArrayList<>();
private Map<Object, Vertex> o2v = new HashMap<>();
// 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 Vertex getVertexFor(Object o)
{
Vertex v = o2v.get(o);
assert v != null;
return v;
}
public Vertex addVertex(Object o, VertexType type)
{
assert o2v.get(o) == null;
Vertex v = new Vertex(this, o);
//v.setType(type);
assert type == v.getType();
verticies.add(v);
o2v.put(o, v);
return v;
}
public void removeVertex(Object o)
{
Vertex v = this.getVertexFor(o);
assert v.getEdges().isEmpty();
assert v.getEdgesFrom().isEmpty();
verticies.remove(v);
o2v.remove(o);
}
public void addEdge(Edge e)
{
e.getFrom().addEdge(e);
}
public List<Vertex> getVerticies()
{
return verticies;
}
public int vertexCount()
{
return verticies.size();
}
@Override
public String toString()
{
return "Graph{" + "verticies=" + verticies.size() + "}";
}
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;
}
public int unsolved(VertexType type)
{
int solved = 0;
for (Vertex v : verticies)
if (v.getOther() == null && type == v.getType())
++solved;
return solved;
}
private void recurse(Vertex v, Set<Vertex> verticies)
{
if (verticies.contains(v))
return;
verticies.add(v);
for (Edge e : v.getEdges())
recurse(e.getTo(), verticies);
}
public Set<Vertex> reachableVerticiesFromSolvedVerticies()
{
Set<Vertex> verticies = new HashSet<>();
for (Vertex v : this.verticies)
if (v.getOther() != null)
recurse(v, verticies);
return verticies;
}
}

View File

@@ -1,169 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
import java.util.HashSet;
import java.util.List;
import net.runelite.deob.ClassFile;
import net.runelite.deob.ClassGroup;
import net.runelite.deob.Field;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.Code;
import net.runelite.deob.attributes.code.Instruction;
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction;
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
public class GraphBuilder
{
public static Graph build(ClassGroup group)
{
// statically build
Graph g = new Graph();
// add verticies
for (ClassFile cf : group.getClasses())
{
//g.addVertex(cf, VertexType.CLASS);
for (Field f : cf.getFields().getFields())
{
g.addVertex(f, VertexType.FIELD);
}
for (Method m : cf.getMethods().getMethods())
{
g.addVertex(m, VertexType.METHOD);
}
}
for (ClassFile cf : group.getClasses())
{
for (Method m : cf.getMethods().getMethods())
{
processMethod(g, m);
}
}
// remove static methods
for (ClassFile cf : group.getClasses())
{
for (Method m : cf.getMethods().getMethods())
{
if (m.isStatic() && !m.getName().equals("<clinit>"))
{
removeMethod(g, m);
Vertex v = g.getVertexFor(m);
assert v.getEdges().isEmpty();
assert v.getEdgesFrom().isEmpty();
g.removeVertex(m);
}
}
}
return g;
}
private static void processMethod(Graph graph, Method method)
{
Code code = method.getCode();
if (code == null)
return;
for (Instruction i : code.getInstructions().getInstructions())
{
if (i instanceof InvokeInstruction)
{
if (i instanceof InvokeStatic)
return;
InvokeInstruction ii = (InvokeInstruction) i;
List<Method> methods = ii.getMethods();
if (methods.isEmpty())
return;
Vertex methodVertex = graph.getVertexFor(method);
for (Method m : methods)
{
Vertex otherMethodVertex = graph.getVertexFor(m);
graph.addEdge(new Edge(null, methodVertex, otherMethodVertex, EdgeType.INVOKE));
graph.addEdge(new Edge(null, otherMethodVertex, methodVertex, EdgeType.INVOKED_FROM));
}
}
else if (i instanceof FieldInstruction)
{
FieldInstruction fi = (FieldInstruction) i;
if (fi.getMyField() == null)
return;
Vertex methodVertex = graph.getVertexFor(method),
fieldVertex = graph.getVertexFor(fi.getMyField());
EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD;
graph.addEdge(new Edge(null, methodVertex, fieldVertex, type));
EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM;
graph.addEdge(new Edge(null, fieldVertex, methodVertex, typeRev));
}
}
}
private static void removeMethod(Graph g, Method m)
{
Vertex v = g.getVertexFor(m);
// for every object that points to m, make it point to
// everything that m points to, with edge type of the edge from m.
for (Edge e : new HashSet<>(v.getEdgesFrom()))
{
// edge is TO v
assert e.getTo() == v;
Vertex from = e.getFrom();
// add an edge from -> everything v is to
for (Edge e2 : new HashSet<>(v.getEdges()))
{
assert e2.getFrom() == v;
Vertex to = e2.getTo();
EdgeType type = e2.getType();
// add edge
from.addEdge(new Edge(null, from, to, type));
}
// remove
from.removeEdge(e);
}
// for every object m points to, everything that points to m should point to it.
for (Edge e : new HashSet<>(v.getEdges()))
{
assert e.getFrom() == v;
Vertex to = e.getTo();
EdgeType type = e.getType();
for (Edge e2 : new HashSet<>(v.getEdgesFrom()))
{
assert e2.getTo() == v;
// add edge from -> to
Vertex from = e2.getFrom();
from.addEdge(new Edge(null, from, to, type));
}
v.removeEdge(e);
}
}
}

View File

@@ -1,53 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
import java.util.Objects;
import net.runelite.deob.Method;
import net.runelite.deob.execution.InstructionContext;
public class MethodEdge extends Edge
{
private final Method method;
public MethodEdge(InstructionContext 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;
}
}

View File

@@ -1,465 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
import com.google.common.base.Objects;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.runelite.deob.ClassFile;
import net.runelite.deob.Field;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.AttributeType;
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;
import org.apache.commons.collections4.CollectionUtils;
public class Vertex
{
private static final int FIELD_MASK = Field.ACC_FINAL | Field.ACC_STATIC;
private static final int METHOD_MASK = Method.ACC_ABSTRACT | Method.ACC_FINAL | Method.ACC_STATIC | Method.ACC_SYNCHRONIZED;
private Graph graph;
private final Object object;
private VertexType type;
private final Set<Edge> edges = new HashSet<>(),
from = new HashSet<>();
private Collection<Vertex> mightBe;
private Vertex is;
//private Set<Instruction> edgeFrom = new HashSet<>();
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 if (object instanceof ClassFile)
type = VertexType.CLASS;
else
assert false;
}
@Override
public String toString()
{
return "Vertex{" + "object=" + object + '}';
}
@Override
public int hashCode()
{
int hash = 7;
hash = 79 * hash + java.util.Objects.hashCode(this.object);
return hash;
}
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final Vertex other = (Vertex) obj;
if (!java.util.Objects.equals(this.object, other.object))
{
return false;
}
return true;
}
public Graph getGraph()
{
return graph;
}
public Object getObject()
{
return object;
}
public VertexType getType()
{
return type;
}
public void setType(VertexType type)
{
this.type = type;
}
public void addEdge(Edge edge)
{
assert edge.getFrom() == this;
//assert edge.getTo() != this;
if (edges.contains(edge))
//if (c != null)
{
// if (edge.getIns() instanceof SetFieldInstruction && !edgeFrom.contains(edge.getIns()))
// {
// edgeFrom.add(edge.getIns());
// c.increase();
// }
return;
}
Vertex to = edge.getTo();
assert to.from.contains(edge) == false;
edges.add(edge);
to.from.add(edge);
//edges.put(edge, edge);
}
public void removeEdge(Edge edge)
{
assert edge.getFrom() == this;
assert edges.contains(edge);
Vertex to = edge.getTo();
assert to.from.contains(edge);
edges.remove(edge);
to.from.remove(edge);
}
public Set<Edge> getEdges()
{
return edges;
}
public Set<Edge> getEdgesFrom()
{
return from;
}
public void merge(Collection<Vertex> maybe)
{
boolean b = false;
if (this.object instanceof Method)
{
Method m = (Method) object;
if (m.getName().equals("method2566"))
{
b = true;
}
}
if (mightBe == null)
mightBe = maybe;
else
{
int old = mightBe.size();
mightBe = CollectionUtils.intersection(mightBe, maybe);
if (b && old == 1 && mightBe.isEmpty())
{
int i = 6;
}
}
}
public void finish()
{
if (this.toString().equals("Vertex{object=class207.<init>()V}"))
{
int i =5;
}
if (mightBe == null)
return;
if (mightBe != null && mightBe.size() > 1)
{
// System.out.println("Can't decide for " + this);
// for(Vertex v : mightBe)
// System.out.println(v);
// int i = 5;
}
if (mightBe.isEmpty())
{
System.out.println("empty " + this);
int i = 5;
}
if (mightBe != null && mightBe.size() == 1)
{
Vertex v = mightBe.stream().findAny().get();
//if (v.getOther() == null || v.getOther() == this)
{
is(v);
is.is(this);
mightBe = null;
System.out.println(this + " is " + is);
}
if (object instanceof Method)
{
//Method m = (Method) object;
//if (m.getName().equals
}
}
}
public void is(Vertex other)
{
if (is != null)
{
assert is.is == this;
is.is = null;
is = null;
//Rename2.collide(object, is.object, other.object);
}
assert is == null;
assert other.graph != graph;
if (object instanceof Method)
{
Method thism = (Method) object;
Method otherm = (Method) other.object;
assert thism.getMethods().getClassFile().getName().equals(otherm.getMethods().getClassFile().getName());
}
this.is = other;
}
public Vertex getOther()
{
return is;
}
private boolean couldBeEqual(ClassFile cf1, ClassFile cf2)
{
if (!cf1.getClassName().equals(cf2.getClassName()))
return false;
if (!cf1.getInterfaces().getInterfaces().equals(cf2.getInterfaces().getInterfaces()))
return false;
if (!cf1.getParentClass().equals(cf2.getParentClass()))
return false;
return true;
}
private List<Instruction> getInstructionsInMethodInclStatic(Method method, Set<Method> visited)
{
List<Instruction> 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<Method> methods = ii.getMethods();
if (methods.isEmpty())
continue;
Method m = methods.get(0);
ilist.addAll(this.getInstructionsInMethodInclStatic(m, visited));
}
else
{
ilist.add(i);
}
}
return ilist;
}
private boolean couldBeEqual(Method m1, Method m2)
{
InstructionList il1 = new InstructionList(this.getInstructionsInMethodInclStatic(m1, new HashSet())),
il2 = new InstructionList(this.getInstructionsInMethodInclStatic(m2, new HashSet()));
return il1.couldBeEqual(il2);
}
private static boolean recurse = true;
public boolean couldBeEqual(Vertex other)
{
assert this != other;
assert graph != other.graph;
// assert is == null;
//assert other.is == null;
if (this.getOther() != null || other.getOther() != null)
{
return this.getOther() == other && other.getOther() == this;
}
if (this.getType() != other.getType())
return false;
// if (this.getEdges().size() != other.getEdges().size())
// return false;
//
// for (EdgeType e : EdgeType.values())
// {
// // for each edge of this type, it must be equal with just one of the others
//
// if (this.edgesOf(e) != other.edgesOf(e))// ||
// //this.solvedEdgesOfType(e) != other.solvedEdgesOfType(e))
// {
// int thise = edgesOf(e), othere = other.edgesOf(e);
// int thisse = this.solvedEdgesOfType(e), otherse = other.solvedEdgesOfType(e);
// return false;
// }
// }
// must be 1->1
// map v -> possibles
// start with the ones with the least possibilities
// if (recurse)
// {
// Set<Edge> others = new HashSet<>(other.getEdges());
// for (Edge e : edges.values())
// {
// Vertex v = e.getTo();
//
// boolean found = false;
// List<Vertex> lv = new ArrayList();
// for (Edge e2 : others)
// {
// Vertex v2 = e2.getTo();
// lv.add(v2);
//
// recurse = false;
// if (v.couldBeEqual(v2))
// // if (e.couldBeEqual(e2))
// {
// recurse = true;
// // others.remove(e2);
// found = true;
// break;
// }
// recurse = true;
// }
//
// if (!found)
// {
// Vertex v2 = null;
// for (Vertex vt : lv)
// if (vt.getObject() instanceof Method)
// {
// Method m = (Method) vt.getObject();
// if (m.getName().equals("vmethod2975"))
// {
// v2 = vt;
// break;
// }
// }
// //v.couldBeEqual(v2);
// 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() & METHOD_MASK) != (m2.getAccessFlags() & METHOD_MASK))
return false;
if ((m1.getCode() == null) != (m2.getCode() == null))
return false;
ClassFile cf1 = m1.getMethods().getClassFile(), cf2 = m2.getMethods().getClassFile();
if (!couldBeEqual(cf1, cf2))
return false;
if (!couldBeEqual(m1, m2))
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.getAccessFlags() & FIELD_MASK) != (f2.getAccessFlags() & FIELD_MASK))
return false;
if (!f1.isStatic())
{
ClassFile cf1 = f1.getFields().getClassFile(), cf2 = f2.getFields().getClassFile();
if (!couldBeEqual(cf1, cf2))
return false;
}
// compare other edges,
ConstantValue cf1 = (ConstantValue) f1.getAttributes().findType(AttributeType.CONSTANT_VALUE);
ConstantValue cf2 = (ConstantValue) f2.getAttributes().findType(AttributeType.CONSTANT_VALUE);
//if (!Objects.equal(cf1, cf2))
// return false;
}
else
assert false;
return true;
}
private int edgesOf(EdgeType type)
{
int t = 0;
for (Edge e : this.edges)
if (e.getType() == type)
++t;
return t;
}
private int solvedEdgesOfType(EdgeType type)
{
return (int) edges.stream().filter(e -> e.getType() == type).filter(e -> e.getTo().getOther() != null).count();
}
}

View File

@@ -1,9 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
public enum VertexType
{
METHOD,
FIELD,
CLASS;
}

View File

@@ -8,24 +8,10 @@ import net.runelite.deob.attributes.code.Instruction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
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;
public class Execution

View File

@@ -15,7 +15,7 @@ public class StoreLoadTest
System.out.println(store);
}
@Test
//@Test
public void unpackStore() throws IOException
{
java.io.File base = StoreLocation.LOCATION;

View File

@@ -16,7 +16,7 @@ import org.junit.Test;
public class ItemLoaderTest
{
@Test
//@Test
public void extract() throws IOException
{
ItemLoader loader = new ItemLoader();

View File

@@ -16,7 +16,7 @@ import org.junit.Test;
public class NpcLoaderTest
{
@Test
//@Test
public void extract() throws IOException
{
NpcLoader loader = new NpcLoader();

View File

@@ -19,7 +19,7 @@ import org.junit.Test;
public class SpriteLoaderTest
{
@Test
//@Test
public void extract() throws IOException
{
java.io.File base = StoreLocation.LOCATION;

View File

@@ -14,6 +14,7 @@ import net.runelite.deob.attributes.Annotations;
import net.runelite.deob.attributes.AttributeType;
import net.runelite.deob.attributes.annotation.Annotation;
import net.runelite.deob.attributes.annotation.Element;
import net.runelite.deob.pool.UTF8;
import net.runelite.deob.signature.Type;
import org.junit.Assert;
import org.junit.Test;
@@ -55,6 +56,6 @@ public class AnnotationTest
Element element = elements.get(0);
Assert.assertEquals("value", element.getType().toString());
Assert.assertEquals("method1", element.getValue());
Assert.assertEquals("method1", ((UTF8) element.getValue()).getValue());
}
}

View File

@@ -1,18 +0,0 @@
package net.runelite.deob.deobfuscators.rename.graph;
import java.io.File;
import java.io.IOException;
import net.runelite.deob.ClassGroup;
import net.runelite.deob.util.JarUtil;
import org.junit.Test;
public class GraphBuilderTest
{
@Test
public void test() throws IOException
{
ClassGroup group = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar"));
GraphBuilder.build(group);
}
}