total crap

This commit is contained in:
Adam
2015-11-28 23:27:34 -05:00
parent 1f778cfd67
commit a2581e62c1
21 changed files with 482 additions and 104 deletions

View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>net.runelite</groupId> <groupId>net.runelite</groupId>
<artifactId>deob</artifactId> <artifactId>deob</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>

View File

@@ -31,67 +31,67 @@ public class Deob
ClassGroup group = JarUtil.loadJar(new File(args[0])); ClassGroup group = JarUtil.loadJar(new File(args[0]));
// run(group, new RenameUnique()); run(group, new RenameUnique());
//
// // remove except RuntimeException
// run(group, new RuntimeExceptions());
//
// // remove unused methods
// run(group, new UnreachedCode());
// run(group, new UnusedMethods());
//
// // remove illegal state exceptions, frees up some parameters
// run(group, new IllegalStateExceptions());
//
// // remove constant logically dead parameters
// run(group, new ConstantParameter());
//
// // remove unhit blocks
// run(group, new UnreachedCode());
// run(group, new UnusedMethods());
//
// // remove unused parameters
// run(group, new UnusedParameters());
//
// // remove unused fields
// run(group, new UnusedFields());
//
// // remove unused methods, again?
// run(group, new UnusedMethods());
//
//// run(group, new MethodInliner());
//// run(group, new UnusedMethods()); // inliner might leave unused methods
//
//// // broken because rename was removed
//// //run(group, new MethodMover());
//
// run(group, new FieldInliner());
//
//// // XXX this is broken because when moving clinit around, some fields can depend on other fields
//// // (like multianewarray)
//// //new FieldMover().run(group);
//
// run(group, new UnusedClass());
// ModArith mod = new ModArith(); // remove except RuntimeException
// mod.run(group); run(group, new RuntimeExceptions());
//
// int last = -1, cur; // remove unused methods
// while ((cur = mod.runOnce()) > 0) run(group, new UnreachedCode());
// { run(group, new UnusedMethods());
// new MultiplicationDeobfuscator().run(group);
// // remove illegal state exceptions, frees up some parameters
// new MultiplyOneDeobfuscator().run(group); run(group, new IllegalStateExceptions());
//
// new MultiplyZeroDeobfuscator().run(group); // remove constant logically dead parameters
// run(group, new ConstantParameter());
// if (last == cur)
// break; // remove unhit blocks
// run(group, new UnreachedCode());
// last = cur; run(group, new UnusedMethods());
// }
// // remove unused parameters
// mod.annotateEncryption(); run(group, new UnusedParameters());
// remove unused fields
run(group, new UnusedFields());
// remove unused methods, again?
run(group, new UnusedMethods());
// run(group, new MethodInliner());
// run(group, new UnusedMethods()); // inliner might leave unused methods
// // broken because rename was removed
// //run(group, new MethodMover());
run(group, new FieldInliner());
// // XXX this is broken because when moving clinit around, some fields can depend on other fields
// // (like multianewarray)
// //new FieldMover().run(group);
run(group, new UnusedClass());
ModArith mod = new ModArith();
mod.run(group);
int last = -1, cur;
while ((cur = mod.runOnce()) > 0)
{
new MultiplicationDeobfuscator().run(group);
new MultiplyOneDeobfuscator().run(group);
new MultiplyZeroDeobfuscator().run(group);
if (last == cur)
break;
last = cur;
}
mod.annotateEncryption();
// eval constant fields (only set once to a constant in ctor) maybe just inline them // eval constant fields (only set once to a constant in ctor) maybe just inline them
@@ -105,8 +105,8 @@ public class Deob
private static void merge() throws IOException private static void merge() throws IOException
{ {
ClassGroup group1 = JarUtil.loadJar(new File("/Users/adam/w/rs/07/adamin1.jar")), ClassGroup group1 = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")),
group2 = JarUtil.loadJar(new File("/Users/adam/w/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);

View File

@@ -54,7 +54,7 @@ public class Field
out.writeShort(accessFlags); out.writeShort(accessFlags);
out.writeShort(pool.makeUTF8(name)); out.writeShort(pool.makeUTF8(name));
out.writeShort(pool.makeUTF8(type.toString())); out.writeShort(pool.makeUTF8(type.getFullType()));
attributes.write(out); attributes.write(out);
} }

View File

@@ -65,7 +65,7 @@ public class Annotation
{ {
ConstantPool pool = annotations.getAttributes().getClassFile().getPool(); ConstantPool pool = annotations.getAttributes().getClassFile().getPool();
out.writeShort(pool.makeUTF8(type.toString())); out.writeShort(pool.makeUTF8(type.getFullType()));
out.writeShort(elements.size()); out.writeShort(elements.size());
for (Element e : elements) for (Element e : elements)
{ {

View File

@@ -64,7 +64,7 @@ public class Element
{ {
ConstantPool pool = annotation.getAnnotations().getAttributes().getClassFile().getPool(); ConstantPool pool = annotation.getAnnotations().getAttributes().getClassFile().getPool();
out.writeShort(pool.makeUTF8(type.toString())); out.writeShort(pool.makeUTF8(type.getFullType()));
byte type; byte type;
switch (value.getType()) switch (value.getType())
{ {

View File

@@ -95,7 +95,16 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
// add possible method call to execution // add possible method call to execution
Execution execution = frame.getExecution(); Execution execution = frame.getExecution();
execution.invoke(ins, method); Frame f = execution.invoke(ins, method);
if (f != null)
{
assert f.getMethod() == method;
//assert f.lastField == frame.lastField;
//assert f.staticReturn == frame;
//frame.stop();
}
} }
frame.addInstructionContext(ins); frame.addInstructionContext(ins);

View File

@@ -42,7 +42,7 @@ public class ModArith implements Deobfuscator
private List<Pair> pairs = new ArrayList<>(); private List<Pair> pairs = new ArrayList<>();
private Encryption encryption = new Encryption(); private Encryption encryption = new Encryption();
private List<InstructionContext> getInsInExpr(InstructionContext ctx, Set<Instruction> set) private static List<InstructionContext> getInsInExpr(InstructionContext ctx, Set<Instruction> set)
{ {
List<InstructionContext> l = new ArrayList<>(); List<InstructionContext> l = new ArrayList<>();

View File

@@ -25,6 +25,8 @@ import net.runelite.deob.attributes.annotation.Annotation;
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.deob.deobfuscators.Renamer; import net.runelite.deob.deobfuscators.Renamer;
import net.runelite.deob.deobfuscators.rename.graph.Edge; 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.Graph;
import net.runelite.deob.deobfuscators.rename.graph.Vertex; import net.runelite.deob.deobfuscators.rename.graph.Vertex;
import net.runelite.deob.deobfuscators.rename.graph.VertexType; import net.runelite.deob.deobfuscators.rename.graph.VertexType;
@@ -193,6 +195,47 @@ public class Rename2
return fields; 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() private void solve()
{ {
List<Vertex> solved = g1.getVerticies().stream().filter(v -> v.getOther() != null).collect(Collectors.toList()); List<Vertex> solved = g1.getVerticies().stream().filter(v -> v.getOther() != null).collect(Collectors.toList());
@@ -231,14 +274,14 @@ public class Rename2
if (e2.getTo().getOther() != null) if (e2.getTo().getOther() != null)
continue; // skip solved edges continue; // skip solved edges
if (b2) // if (b2)
{ // {
Method m = (Method) e2.getTo().getObject(); // Method m = (Method) e2.getTo().getObject();
if (m.getName().equals("method2489")) // if (m.getName().equals("method2489"))
{ // {
b2 = true; // b2 = true;
} // }
} // }
if (!e.getTo().couldBeEqual(e2.getTo())) if (!e.getTo().couldBeEqual(e2.getTo()))
{ {
@@ -320,6 +363,9 @@ public class Rename2
System.out.println(fname(f1) + " is " + fname(f2)); 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()); System.out.println("g1 verticies " + g1.getVerticies().size() + " reachable " + g1.reachableVerticiesFromSolvedVerticies().size());
Set<Vertex> reachable = g1.reachableVerticiesFromSolvedVerticies(); Set<Vertex> reachable = g1.reachableVerticiesFromSolvedVerticies();
for (Vertex v : g1.getVerticies()) for (Vertex v : g1.getVerticies())
@@ -384,7 +430,7 @@ public class Rename2
try try
{ {
JarUtil.saveJar(two, new File("/Users/adam/w/rs/07/adamout.jar")); JarUtil.saveJar(two, new File("d:/rs/07/adamout.jar"));
} }
catch (IOException ex) catch (IOException ex)
{ {

View File

@@ -1,15 +1,18 @@
package net.runelite.deob.deobfuscators.rename.graph; package net.runelite.deob.deobfuscators.rename.graph;
import java.util.Objects; import java.util.Objects;
import net.runelite.deob.attributes.code.Instruction;
public class Edge public class Edge
{ {
private final Instruction ins; // craetor
private final Vertex from, to; private final Vertex from, to;
private final EdgeType type; private final EdgeType type;
private int weight; private int weight;
public Edge(Vertex from, Vertex to, EdgeType type) public Edge(Instruction ins, Vertex from, Vertex to, EdgeType type)
{ {
this.ins = ins;
this.from = from; this.from = from;
this.to = to; this.to = to;
this.type = type; this.type = type;
@@ -17,6 +20,11 @@ public class Edge
assert from.getGraph() == to.getGraph(); assert from.getGraph() == to.getGraph();
} }
public Instruction getIns()
{
return ins;
}
public Vertex getFrom() public Vertex getFrom()
{ {
return from; return from;
@@ -94,8 +102,8 @@ public class Edge
if (this.type != other.type) if (this.type != other.type)
return false; return false;
//if (this.weight != other.weight) // if (this.weight != other.weight)
// return false; // return false;
return true; return true;
} }

View File

@@ -8,5 +8,17 @@ public enum EdgeType
INVOKED_FROM, INVOKED_FROM,
GETFIELD_FROM, GETFIELD_FROM,
SETFIELD_FROM; SETFIELD_FROM,
FIELD_ASSOCIATION,
FIELD_ASSOCIATION_FROM,
METHOD_ASSOCIATION,
METHOD_ASSOCIATION_FROM,
PREV_FIELD,
PREV_FIELD_FROM,
FIELD_ASSIGNMENT_FIELD,
FIELD_ASSIGNMENT_FIELD_FROM;
} }

View File

@@ -0,0 +1,39 @@
package net.runelite.deob.deobfuscators.rename.graph;
import net.runelite.deob.attributes.code.Instruction;
public class FieldEdge extends Edge
{
private int id;
public FieldEdge(Instruction ins, Vertex from, Vertex to, EdgeType type, int id)
{
super(ins, from, to, type);
this.id = id;
}
@Override
public boolean equals(Object obj)
{
if (!super.equals(obj))
{
return false;
}
final FieldEdge other = (FieldEdge) obj;
if (this.id != other.id)
{
return false;
}
return true;
}
@Override
public int hashCode()
{
int hash = 5;
hash = 89 * hash + this.id;
return hash ^ super.hashCode();
}
}

View File

@@ -46,15 +46,9 @@ public class Graph
return v; return v;
} }
public void addEdge(Object from, Object to, EdgeType type) public void addEdge(Edge e)
{ {
assert from != null; e.getFrom().addEdge(e);
assert to != null;
Vertex v1 = getVertexFor(from), v2 = getVertexFor(to);
Edge e = new Edge(v1, v2, type);
v1.addEdge(e);
} }
public List<Vertex> getVerticies() public List<Vertex> getVerticies()

View File

@@ -0,0 +1,53 @@
package net.runelite.deob.deobfuscators.rename.graph;
import java.util.Objects;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.code.Instruction;
public class MethodEdge extends Edge
{
private final Method method;
public MethodEdge(Instruction i, Vertex from, Vertex to, EdgeType type, Method method)
{
super(i, from, to, type);
this.method = method;
}
@Override
public int hashCode()
{
int hash = 7;
hash = 61 * hash + Objects.hashCode(this.method);
return hash ^ super.hashCode();
}
@Override
public boolean equals(Object obj)
{
if (!super.equals(obj))
{
return false;
}
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final MethodEdge other = (MethodEdge) obj;
if (!Objects.equals(this.method, other.method))
{
return false;
}
return true;
}
}

View File

@@ -16,6 +16,7 @@ import net.runelite.deob.attributes.Code;
import net.runelite.deob.attributes.ConstantValue; import net.runelite.deob.attributes.ConstantValue;
import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instruction;
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.deob.attributes.code.instructions.InvokeStatic; import net.runelite.deob.attributes.code.instructions.InvokeStatic;
import net.runelite.deob.deobfuscators.rename.InstructionList; import net.runelite.deob.deobfuscators.rename.InstructionList;
import net.runelite.deob.deobfuscators.rename.Rename2; import net.runelite.deob.deobfuscators.rename.Rename2;
@@ -35,6 +36,8 @@ public class Vertex
private Collection<Vertex> mightBe; private Collection<Vertex> mightBe;
private Vertex is; private Vertex is;
private Set<Instruction> edgeFrom = new HashSet<>();
public Vertex(Graph graph, Object object) public Vertex(Graph graph, Object object)
{ {
this.graph = graph; this.graph = graph;
@@ -107,7 +110,11 @@ public class Vertex
Edge c = edges.get(edge); Edge c = edges.get(edge);
if (c != null) if (c != null)
{ {
c.increase(); if (edge.getIns() instanceof SetFieldInstruction && !edgeFrom.contains(edge.getIns()))
{
edgeFrom.add(edge.getIns());
c.increase();
}
return; return;
} }

View File

@@ -18,9 +18,13 @@ import net.runelite.deob.Field;
import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; import net.runelite.deob.attributes.code.instruction.types.FieldInstruction;
import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; 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.InvokeInstruction;
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.deob.attributes.code.instructions.InvokeStatic; 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.EdgeType;
import net.runelite.deob.deobfuscators.rename.graph.FieldEdge;
import net.runelite.deob.deobfuscators.rename.graph.Graph; 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 net.runelite.deob.deobfuscators.rename.graph.VertexType;
import org.apache.commons.collections4.map.MultiValueMap; import org.apache.commons.collections4.map.MultiValueMap;
@@ -100,14 +104,15 @@ public class Execution
frames.add(frame); frames.add(frame);
} }
public void invoke(InstructionContext from, Method to) public Frame invoke(InstructionContext from, Method to)
{ {
if (hasInvoked(from, to)) if (hasInvoked(from, to))
return; return null;
Frame f = new Frame(this, to); Frame f = new Frame(this, to);
f.initialize(from); f.initialize(from);
this.addFrame(f); this.addFrame(f);
return f;
} }
public void addMethod(Method to) public void addMethod(Method to)
@@ -132,7 +137,9 @@ public class Execution
frame.execute(); frame.execute();
assert frames.get(0) == frame; assert frames.get(0) == frame;
frames.remove(0); assert !frame.isExecuting();
frames.remove(frame);
processedFrames.add(frame); processedFrames.add(frame);
} }
@@ -189,12 +196,13 @@ public class Execution
} }
} }
protected void buildGraph(Frame frame, Instruction i) protected void buildGraph(Frame frame, Instruction i, InstructionContext ctx)
{ {
if (!isBuildGraph()) if (!isBuildGraph())
return; return;
assert frame.getMethod() == frame.nonStatic || frame.nonStatic.isStatic() == false; assert frame.getMethod() == frame.nonStatic || frame.nonStatic.isStatic() == false;
assert ctx.getInstruction() == i;
if (i instanceof InvokeInstruction) if (i instanceof InvokeInstruction)
{ {
@@ -209,8 +217,8 @@ public class Execution
for (Method m : methods) for (Method m : methods)
{ {
graph.addEdge(frame.nonStatic, m, EdgeType.INVOKE); graph.addEdge(new Edge(i, graph.getVertexFor(frame.nonStatic), graph.getVertexFor(m), EdgeType.INVOKE));
graph.addEdge(m, frame.nonStatic, EdgeType.INVOKED_FROM); graph.addEdge(new Edge(i, graph.getVertexFor(m), graph.getVertexFor(frame.nonStatic), EdgeType.INVOKED_FROM));
} }
} }
else if (i instanceof FieldInstruction) else if (i instanceof FieldInstruction)
@@ -220,13 +228,87 @@ public class Execution
if (fi.getMyField() == null) if (fi.getMyField() == null)
return; return;
//int id = frame.getMethodCtx().fcount++;
EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD; EdgeType type = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD : EdgeType.SETFIELD;
graph.addEdge(frame.nonStatic, fi.getMyField(), type); graph.addEdge(new Edge(i, graph.getVertexFor(frame.nonStatic), graph.getVertexFor(fi.getMyField()), type));
EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM; EdgeType typeRev = fi instanceof GetFieldInstruction ? EdgeType.GETFIELD_FROM : EdgeType.SETFIELD_FROM;
graph.addEdge(fi.getMyField(), frame.nonStatic, typeRev); graph.addEdge(new Edge(i, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(frame.nonStatic), typeRev));
if (fi instanceof SetFieldInstruction && frame.lastField != null)
{
graph.addEdge(new MethodEdge(i, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(frame.lastField), EdgeType.PREV_FIELD, frame.nonStatic));
graph.addEdge(new MethodEdge(i, graph.getVertexFor(frame.lastField), graph.getVertexFor(fi.getMyField()), EdgeType.PREV_FIELD_FROM, frame.nonStatic));
}
// if (fi instanceof SetFieldInstruction)
// {
// StackContext sctx = ctx.getPops().get(0);
// if (sctx.getPushed().getInstruction() instanceof GetFieldInstruction)
// {
// GetFieldInstruction gfi = (GetFieldInstruction) sctx.getPushed().getInstruction();
//
// if (gfi.getMyField() != null)
// {
// // XXX dup edges
// graph.addEdge(new MethodEdge(i, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(gfi.getMyField()), EdgeType.FIELD_ASSIGNMENT_FIELD, frame.nonStatic));
// graph.addEdge(new MethodEdge(i, graph.getVertexFor(gfi.getMyField()), graph.getVertexFor(fi.getMyField()), EdgeType.FIELD_ASSIGNMENT_FIELD_FROM, frame.nonStatic));
// }
// }
// }
// associated fields
for (InstructionContext ic : getInsInExpr(ctx, new HashSet<>()))
{
Instruction i2 = (Instruction) ic.getInstruction();
if (i2 instanceof FieldInstruction)
{
FieldInstruction fi2 = (FieldInstruction) i2;
if (fi2.getMyField() == null)
continue;
// these are within the context of a method
graph.addEdge(new MethodEdge(i2, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(fi2.getMyField()), EdgeType.FIELD_ASSOCIATION, frame.nonStatic));
graph.addEdge(new MethodEdge(i2, graph.getVertexFor(fi2.getMyField()), graph.getVertexFor(fi.getMyField()), EdgeType.FIELD_ASSOCIATION_FROM, frame.nonStatic));
}
else if (i2 instanceof InvokeInstruction)
{
InvokeInstruction ii2 = (InvokeInstruction) i2;
if (ii2 instanceof InvokeStatic)
continue;
for (Method m : ii2.getMethods())
{
graph.addEdge(new MethodEdge(i2, graph.getVertexFor(fi.getMyField()), graph.getVertexFor(m), EdgeType.METHOD_ASSOCIATION, frame.nonStatic));
graph.addEdge(new MethodEdge(i2, graph.getVertexFor(m), graph.getVertexFor(fi.getMyField()), EdgeType.METHOD_ASSOCIATION_FROM, frame.nonStatic));
}
}
}
} }
} }
private static List<InstructionContext> getInsInExpr(InstructionContext ctx, Set<Instruction> set)
{
List<InstructionContext> l = new ArrayList<>();
if (ctx == null || set.contains(ctx.getInstruction()))
return l;
set.add(ctx.getInstruction());
l.add(ctx);
for (StackContext s : ctx.getPops())
l.addAll(getInsInExpr(s.getPushed(), set));
for (StackContext s : ctx.getPushes())
for (InstructionContext i : s.getPopped())
l.addAll(getInsInExpr(i, set));
return l;
}
public Graph getGraph() public Graph getGraph()
{ {
return graph; return graph;

View File

@@ -3,6 +3,7 @@ package net.runelite.deob.execution;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.runelite.deob.Field;
import net.runelite.deob.Method; import net.runelite.deob.Method;
import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.Code;
import net.runelite.deob.attributes.code.Exception; import net.runelite.deob.attributes.code.Exception;
@@ -11,6 +12,9 @@ import net.runelite.deob.attributes.code.Instructions;
import net.runelite.deob.pool.NameAndType; import net.runelite.deob.pool.NameAndType;
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.attributes.code.instruction.types.ReturnInstruction; import net.runelite.deob.attributes.code.instruction.types.ReturnInstruction;
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.deob.attributes.code.instructions.AThrow;
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
public class Frame public class Frame
{ {
@@ -23,6 +27,8 @@ public class Frame
private List<InstructionContext> instructions = new ArrayList<>(); // instructions executed in this frame private List<InstructionContext> instructions = new ArrayList<>(); // instructions executed in this frame
private MethodContext ctx; private MethodContext ctx;
protected Method nonStatic; // next non static method up the stack protected Method nonStatic; // next non static method up the stack
public Field lastField;
public Frame staticReturn;
public Frame(Execution execution, Method method) public Frame(Execution execution, Method method)
{ {
@@ -63,6 +69,9 @@ public class Frame
if (this.getMethod().isStatic()) if (this.getMethod().isStatic())
{ {
this.nonStatic = ctx.getFrame().nonStatic; this.nonStatic = ctx.getFrame().nonStatic;
// this.lastField = ctx.getFrame().lastField;
// this.staticReturn = ctx.getFrame();
//this.ctx = ctx.getFrame().ctx;
} }
// initialize LVT. the last argument is popped first, and is at arguments[0] // initialize LVT. the last argument is popped first, and is at arguments[0]
@@ -99,6 +108,8 @@ public class Frame
this.variables = new Variables(other.variables); this.variables = new Variables(other.variables);
this.ctx = other.ctx; this.ctx = other.ctx;
this.nonStatic = other.nonStatic; this.nonStatic = other.nonStatic;
this.lastField = other.lastField;
this.staticReturn = other.staticReturn;
} }
public Frame dup() public Frame dup()
@@ -167,6 +178,21 @@ public class Frame
{ {
Instruction oldCur = cur; Instruction oldCur = cur;
if ((cur instanceof ReturnInstruction || cur instanceof AThrow) && this.staticReturn != null)
{
Frame newFrame = this.staticReturn.dup();
newFrame.lastField = this.lastField;
newFrame.executing = true;
assert newFrame.cur instanceof InvokeStatic;
int i = newFrame.method.getCode().getInstructions().getInstructions().indexOf(newFrame.cur);
assert i != -1;
newFrame.cur = newFrame.method.getCode().getInstructions().getInstructions().get(i + 1);
assert execution.frames.contains(newFrame);
//this.execution.frames.add(newFrame);
}
try try
{ {
cur.execute(this); cur.execute(this);
@@ -199,7 +225,13 @@ public class Frame
if (!executing) if (!executing)
break; break;
execution.buildGraph(this, oldCur); execution.buildGraph(this, oldCur, ictx);
if (oldCur instanceof SetFieldInstruction)
{
SetFieldInstruction sfi = (SetFieldInstruction) oldCur;
if (sfi.getMyField() != null)
this.lastField = sfi.getMyField();
}
if (oldCur == cur) if (oldCur == cur)
{ {

View File

@@ -1,6 +1,7 @@
package net.runelite.deob.execution; package net.runelite.deob.execution;
import java.util.Collection; import java.util.Collection;
import net.runelite.deob.Field;
import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instruction;
import org.apache.commons.collections4.map.MultiValueMap; import org.apache.commons.collections4.map.MultiValueMap;

View File

@@ -28,7 +28,7 @@ public class Type
private static String asmTypeToClass(String type) private static String asmTypeToClass(String type)
{ {
switch (type.toString()) switch (type)
{ {
case "B": case "B":
return byte.class.getCanonicalName(); return byte.class.getCanonicalName();

View File

@@ -61,7 +61,7 @@ public class NameAndType extends PoolEntry
if (signature != null) if (signature != null)
descriptorIndex = pool.makeUTF8(signature.toString()); descriptorIndex = pool.makeUTF8(signature.toString());
else else
descriptorIndex = pool.makeUTF8(type.toString()); descriptorIndex = pool.makeUTF8(type.getFullType());
} }
@Override @Override
@@ -97,7 +97,7 @@ public class NameAndType extends PoolEntry
public Object getStackObject() public Object getStackObject()
{ {
switch (type.toString()) switch (type.getFullType())
{ {
case "B": case "B":
return (byte) 0; return (byte) 0;

View File

@@ -64,9 +64,9 @@ public class Signature
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append('('); sb.append('(');
for (Type a : arguments) for (Type a : arguments)
sb.append(a.toString()); sb.append(a.getFullType());
sb.append(')'); sb.append(')');
sb.append(rv.toString()); sb.append(rv.getFullType());
return sb.toString(); return sb.toString();
} }

View File

@@ -0,0 +1,95 @@
package net.runelite.deob.deobfuscators.rename;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import net.runelite.deob.ClassGroup;
import net.runelite.deob.Field;
import net.runelite.deob.Method;
import net.runelite.deob.attributes.Code;
import net.runelite.deob.attributes.code.Instruction;
import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction;
import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction;
import net.runelite.deob.attributes.code.instructions.InvokeStatic;
import net.runelite.deob.execution.Execution;
import net.runelite.deob.execution.Frame;
import net.runelite.deob.util.JarUtil;
import org.junit.Test;
public class Rename
{
private List<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;
}
@Test
public void test() throws IOException
{
ClassGroup one = JarUtil.loadJar(new File("d:/rs/07/adamin1.jar")), two = JarUtil.loadJar(new File("d:/rs/07/adamin2.jar"));
Execution eone = new Execution(one);
eone.setBuildGraph(true);
eone.populateInitialMethods();
eone.run();
Execution etwo = new Execution(two);
etwo.setBuildGraph(true);
etwo.populateInitialMethods();
etwo.run();
// Method m1 = one.findClass("client").findMethod("vmethod3096"), m2 = two.findClass("client").findMethod("vmethod2975");
//
// List<SetFieldInstruction> l1 = (List<SetFieldInstruction>) getInstructionsInMethodInclStatic(m1, new HashSet()).stream().filter(i -> i instanceof SetFieldInstruction).collect(Collectors.toList()),
// l2 = (List<SetFieldInstruction>) getInstructionsInMethodInclStatic(m2, new HashSet()).stream().filter(i -> i instanceof SetFieldInstruction).collect(Collectors.toList());
//
//
// List<Field> lf1 =(List) l1.stream().filter(i -> i.getMyField() != null).map(i -> i.getMyField()).distinct().collect(Collectors.toList()),
// lf2 = l2.stream().filter(i -> i.getMyField() != null).map(i -> i.getMyField()).distinct().collect(Collectors.toList());
//
// for (int i = 0; i< 100; ++i)
// {
// Field f1 = lf1.get(i), f2 = lf2.get(i);
//
// System.out.println(f1 + " <-> " + f2);
// }
// number of setfields
//List<Frame> f1 = eone.processedFrames.stream().filter(f -> f.getMethod() == m1).collect(Collectors.toList()),
// f2 = etwo.processedFrames.stream().filter(f -> f.getMethod() == m2).collect(Collectors.toList());
//System.out.println(ll1);
}
}