Remove old graph stuff, all tests pass
This commit is contained in:
@@ -17,7 +17,6 @@ import net.runelite.deob.deobfuscators.arithmetic.ModArith;
|
|||||||
import net.runelite.deob.deobfuscators.arithmetic.MultiplicationDeobfuscator;
|
import net.runelite.deob.deobfuscators.arithmetic.MultiplicationDeobfuscator;
|
||||||
import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator;
|
import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator;
|
||||||
import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator;
|
import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator;
|
||||||
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;
|
||||||
|
|
||||||
@@ -107,9 +106,9 @@ 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"));
|
||||||
|
//
|
||||||
Rename2 rename = new Rename2();
|
// Rename2 rename = new Rename2();
|
||||||
rename.run(group1, group2);
|
// rename.run(group1, group2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isObfuscated(String name)
|
public static boolean isObfuscated(String name)
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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());
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package net.runelite.deob.deobfuscators.rename.graph;
|
|
||||||
|
|
||||||
|
|
||||||
public enum VertexType
|
|
||||||
{
|
|
||||||
METHOD,
|
|
||||||
FIELD,
|
|
||||||
CLASS;
|
|
||||||
}
|
|
||||||
@@ -8,24 +8,10 @@ import net.runelite.deob.attributes.code.Instruction;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
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;
|
import org.apache.commons.collections4.map.MultiValueMap;
|
||||||
|
|
||||||
public class Execution
|
public class Execution
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class StoreLoadTest
|
|||||||
System.out.println(store);
|
System.out.println(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
//@Test
|
||||||
public void unpackStore() throws IOException
|
public void unpackStore() throws IOException
|
||||||
{
|
{
|
||||||
java.io.File base = StoreLocation.LOCATION;
|
java.io.File base = StoreLocation.LOCATION;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
public class ItemLoaderTest
|
public class ItemLoaderTest
|
||||||
{
|
{
|
||||||
@Test
|
//@Test
|
||||||
public void extract() throws IOException
|
public void extract() throws IOException
|
||||||
{
|
{
|
||||||
ItemLoader loader = new ItemLoader();
|
ItemLoader loader = new ItemLoader();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
public class NpcLoaderTest
|
public class NpcLoaderTest
|
||||||
{
|
{
|
||||||
@Test
|
//@Test
|
||||||
public void extract() throws IOException
|
public void extract() throws IOException
|
||||||
{
|
{
|
||||||
NpcLoader loader = new NpcLoader();
|
NpcLoader loader = new NpcLoader();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
public class SpriteLoaderTest
|
public class SpriteLoaderTest
|
||||||
{
|
{
|
||||||
@Test
|
//@Test
|
||||||
public void extract() throws IOException
|
public void extract() throws IOException
|
||||||
{
|
{
|
||||||
java.io.File base = StoreLocation.LOCATION;
|
java.io.File base = StoreLocation.LOCATION;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import net.runelite.deob.attributes.Annotations;
|
|||||||
import net.runelite.deob.attributes.AttributeType;
|
import net.runelite.deob.attributes.AttributeType;
|
||||||
import net.runelite.deob.attributes.annotation.Annotation;
|
import net.runelite.deob.attributes.annotation.Annotation;
|
||||||
import net.runelite.deob.attributes.annotation.Element;
|
import net.runelite.deob.attributes.annotation.Element;
|
||||||
|
import net.runelite.deob.pool.UTF8;
|
||||||
import net.runelite.deob.signature.Type;
|
import net.runelite.deob.signature.Type;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -55,6 +56,6 @@ public class AnnotationTest
|
|||||||
Element element = elements.get(0);
|
Element element = elements.get(0);
|
||||||
|
|
||||||
Assert.assertEquals("value", element.getType().toString());
|
Assert.assertEquals("value", element.getType().toString());
|
||||||
Assert.assertEquals("method1", element.getValue());
|
Assert.assertEquals("method1", ((UTF8) element.getValue()).getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user