This commit is contained in:
Adam
2015-12-05 18:42:16 -05:00
parent b9b2ef70f2
commit 9b2b5fdecf
11 changed files with 278 additions and 122 deletions

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 // // remove except RuntimeException
run(group, new RuntimeExceptions()); // run(group, new RuntimeExceptions());
//
// remove unused methods // // remove unused methods
run(group, new UnreachedCode()); // run(group, new UnreachedCode());
run(group, new UnusedMethods()); // run(group, new UnusedMethods());
//
// remove illegal state exceptions, frees up some parameters // // remove illegal state exceptions, frees up some parameters
run(group, new IllegalStateExceptions()); // run(group, new IllegalStateExceptions());
//
// remove constant logically dead parameters // // remove constant logically dead parameters
run(group, new ConstantParameter()); // run(group, new ConstantParameter());
//
// remove unhit blocks // // remove unhit blocks
run(group, new UnreachedCode()); // run(group, new UnreachedCode());
run(group, new UnusedMethods()); // run(group, new UnusedMethods());
//
// remove unused parameters // // remove unused parameters
run(group, new UnusedParameters()); // run(group, new UnusedParameters());
//
// remove unused fields // remove unused fields
run(group, new UnusedFields()); run(group, new UnusedFields());
//
// remove unused methods, again? // // remove unused methods, again?
run(group, new UnusedMethods()); // run(group, new UnusedMethods());
//
// run(group, new MethodInliner()); //// run(group, new MethodInliner());
// run(group, new UnusedMethods()); // inliner might leave unused methods //// run(group, new UnusedMethods()); // inliner might leave unused methods
//
// // broken because rename was removed //// // broken because rename was removed
// //run(group, new MethodMover()); //// //run(group, new MethodMover());
//
run(group, new FieldInliner()); // run(group, new FieldInliner());
//
// // XXX this is broken because when moving clinit around, some fields can depend on other fields //// // XXX this is broken because when moving clinit around, some fields can depend on other fields
// // (like multianewarray) //// // (like multianewarray)
// //new FieldMover().run(group); //// //new FieldMover().run(group);
//
run(group, new UnusedClass()); // run(group, new UnusedClass());
//
ModArith mod = new ModArith(); // ModArith mod = new ModArith();
mod.run(group); // mod.run(group);
//
int last = -1, cur; // int last = -1, cur;
while ((cur = mod.runOnce()) > 0) // while ((cur = mod.runOnce()) > 0)
{ // {
new MultiplicationDeobfuscator().run(group); // new MultiplicationDeobfuscator().run(group);
//
new MultiplyOneDeobfuscator().run(group); // new MultiplyOneDeobfuscator().run(group);
//
new MultiplyZeroDeobfuscator().run(group); // new MultiplyZeroDeobfuscator().run(group);
//
if (last == cur) // if (last == cur)
break; // break;
//
last = cur; // last = cur;
} // }
//
mod.annotateEncryption(); // 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

View File

@@ -26,9 +26,7 @@ public class AAStore extends Instruction implements ArrayStore
StackContext index = stack.pop(); StackContext index = stack.pop();
StackContext array = stack.pop(); StackContext array = stack.pop();
ins.pop(value); ins.pop(value, index, array);
ins.pop(index);
ins.pop(array);
frame.addInstructionContext(ins); frame.addInstructionContext(ins);
} }

View File

@@ -41,6 +41,12 @@ public class InvokeStatic extends Instruction implements InvokeInstruction
this.method = method; this.method = method;
} }
@Override
public String toString()
{
return "invokestatic " + method + " in " + this.getInstructions().getCode().getAttributes().getMethod();
}
@Override @Override
public void load(DataInputStream is) throws IOException public void load(DataInputStream is) throws IOException
{ {
@@ -96,15 +102,6 @@ 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();
Frame f = 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

@@ -34,6 +34,12 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction
super(instructions, type, pc); super(instructions, type, pc);
} }
@Override
public String toString()
{
return "invokevirtual " + method + " in " + this.getInstructions().getCode().getAttributes().getMethod();
}
@Override @Override
public void load(DataInputStream is) throws IOException public void load(DataInputStream is) throws IOException
{ {

View File

@@ -22,6 +22,11 @@ public class NewArray extends Instruction
super(instructions, type, pc); super(instructions, type, pc);
} }
public int getArrayType()
{
return type;
}
@Override @Override
public void load(DataInputStream is) throws IOException public void load(DataInputStream is) throws IOException
{ {

View File

@@ -30,27 +30,19 @@ public class UnusedFields implements Deobfuscator
if (ins instanceof FieldInstruction) if (ins instanceof FieldInstruction)
{ {
FieldInstruction fi = (FieldInstruction) ins; FieldInstruction fi = (FieldInstruction) ins;
net.runelite.deob.pool.Field ff = fi.getField();
// pool to Field if (fi.getMyField() != field)
ClassFile clazz = group.findClass(ff.getClassEntry().getName());
if (clazz == null)
continue; continue;
Field f = clazz.findFieldDeep(ff.getNameAndType()); if (ins instanceof GetFieldInstruction)
++get;
if (field == f) if (ins instanceof SetFieldInstruction)
{ ++set;
if (ins instanceof GetFieldInstruction)
++get;
if (ins instanceof SetFieldInstruction)
++set;
}
} }
} }
} }
if (get == 0 && set == 0) if (get == 0)
return true; return true;
return false; return false;

View File

@@ -246,28 +246,21 @@ public class Rename2
assert s.getGraph() != other.getGraph(); assert s.getGraph() != other.getGraph();
boolean b =false;
if (s.toString().equals("Vertex{object=B[] class118.field1980}")
&& other.toString().equals("Vertex{object=B[] class118.field1986}"))
{
b=true;
}
for (Edge e : s.getEdges()) for (Edge e : s.getEdges())
{ {
assert e.getFrom() == s; assert e.getFrom() == s;
boolean b = false;
if (e.toString().equals("Edge{from=Vertex{object=client.init()V}, to=Vertex{object=static Ljava/lang/String;[] class14.field209}, type=SETFIELD}"))
{
b = true;
}
if (e.getTo().getOther() != null) if (e.getTo().getOther() != null)
continue; // skip solved edges continue; // skip solved edges
Vertex v = e.getTo(); // end of edge in g1 Vertex v = e.getTo(); // end of edge in g1
boolean b2 = false;
if (b && v.toString().equals("Vertex{object=class118.method2566()B}"))
{
b2 = true;
}
List<Vertex> l = new ArrayList<>(); List<Vertex> l = new ArrayList<>();
for (Edge e2 : other.getEdges()) for (Edge e2 : other.getEdges())
{ {
@@ -289,6 +282,11 @@ public class Rename2
continue; continue;
} }
if (b)
{
int i = 5;
}
if (!e.couldBeEqual(e2)) if (!e.couldBeEqual(e2))
{ {
// System.out.println(e + " != " + e2); // System.out.println(e + " != " + e2);
@@ -397,13 +395,14 @@ public class Rename2
System.out.println("methods " +g1.solved(VertexType.METHOD)); System.out.println("methods " +g1.solved(VertexType.METHOD));
System.out.println("f " +g1.solved(VertexType.FIELD)); System.out.println("f " +g1.solved(VertexType.FIELD));
Vertex stored = null; List<Edge> unsolved = new ArrayList<>();
//Vertex stored = null;
for (Vertex v : g1.getVerticies()) for (Vertex v : g1.getVerticies())
{ {
if (v.getOther() == null) if (v.getOther() == null)
continue; continue;
if (v.getObject() instanceof Method) continue; //if (v.getObject() instanceof Method) continue;
//assert stored == null; //assert stored == null;
//stored = v; //stored = v;
@@ -412,10 +411,19 @@ public class Rename2
{ {
if (e.getTo().getOther() == null) if (e.getTo().getOther() == null)
{ {
System.out.println("Edge " + e + " on vertex " + v + " is unsolved"); 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); // NameMappings col = buildCollisionMap(one, two);
// rename(col, two); // rename(col, two);
@@ -430,9 +438,10 @@ public class Rename2
// for (Vertex v : g1.getVerticies()) // for (Vertex v : g1.getVerticies())
// { // {
// if (v.getOther() != null) //// if (v.getOther() != null)
// System.out.println(v.getObject() + " -> " + v.getOther().getOther()); //// System.out.println(v.getObject() + " -> " + v.getOther().getOther());
// else //// else
// if (v.getObject() instanceof Field)
// System.out.println(v.getObject() + " -> unk"); // System.out.println(v.getObject() + " -> unk");
// } // }

View File

@@ -1,10 +1,21 @@
package net.runelite.deob.deobfuscators.rename.graph; package net.runelite.deob.deobfuscators.rename.graph;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Objects; 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.DupInstruction;
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.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.InstructionContext;
import net.runelite.deob.execution.StackContext; import net.runelite.deob.execution.StackContext;
import net.runelite.deob.execution.VariableContext;
import net.runelite.deob.execution.Variables;
public class Edge public class Edge
{ {
@@ -105,9 +116,9 @@ public class Edge
if (this.type != other.type) if (this.type != other.type)
return false; return false;
if (this.type == EdgeType.SETFIELD) if (this.type == EdgeType.SETFIELD)// || this.type == EdgeType.SETFIELD_FROM)
{ {
if (!compareSetField(other.getIns())) if (!compareSetField((Field) this.getTo().getObject(), (Field) other.getTo().getObject(), other.getIns()))
return false; return false;
} }
// if (this.weight != other.weight) // if (this.weight != other.weight)
@@ -116,29 +127,146 @@ public class Edge
return true; return true;
} }
private InstructionContext handleDup(InstructionContext i, StackContext sctx) private InstructionContext resolve(
InstructionContext ctx,
StackContext from // pushed from ctx
)
{ {
DupInstruction d = (DupInstruction) i.getInstruction(); if (ctx.getInstruction() instanceof SetFieldInstruction)
return d.getOriginal(sctx).getPushed(); {
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; // parameter?
return resolve(storedCtx, null);
}
}
return ctx;
} }
private boolean compareSetField(InstructionContext other) // private static final String[][] map = {
// {"field1989", "field2042"},
// {"field164", "field2156"},
// {"field2904", "field2881"},
// {"field296", "field287"},
// {"field297", "field425"},
// {"field416", "field420"},
// {"field329", "field331"},
// {"field2203", "field2216"},
// {"field2202", "field2222"},
// {"field2100", "field2109"},
// };
//
// private boolean isEqual(SetFieldInstruction sf1, SetFieldInstruction sf2)
// {
// for (int i = 0; i < map.length; ++i)
// {
// if (sf1.getMyField() != null && sf1.getMyField().getName().equals(map[i][0]) &&
// sf2.getMyField() != null && sf2.getMyField().getName().equals(map[i][1]))
// return true;
// }
// return false;
// }
private boolean compareSetField(Field field1, Field field2, InstructionContext other)
{ {
InstructionContext thisp = ins.getPops().get(0).getPushed(), InstructionContext thisp = resolve(ins.getPops().get(0).getPushed(), ins.getPops().get(0)),
otherp = other.getPops().get(0).getPushed(); otherp = resolve(other.getPops().get(0).getPushed(), other.getPops().get(0));
if (thisp.getInstruction() instanceof DupInstruction) return couldBeEqual(field1, field2, thisp, otherp);
}
private boolean couldBeEqual(Field field1, Field field2, InstructionContext one, InstructionContext two)
{
if (field2.getName().equals("field209"))
{ {
thisp = handleDup(thisp, ins.getPops().get(0)); int i =5;
} }
if (otherp.getInstruction() instanceof DupInstruction) Instruction i1 = one.getInstruction(), i2 = two.getInstruction();
if (i1 instanceof LVTInstruction && i2 instanceof LVTInstruction)
{ {
otherp = handleDup(otherp, other.getPops().get(0)); 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.getInstructionWhichStored() == null;
assert v2.getInstructionWhichStored() == null;
return v1.getType().equals(v2.getType());
} }
Class[] c1 = thisp.getInstruction().getClass().getInterfaces(), if (i1 instanceof NewArray && i2 instanceof NewArray)
c2 = otherp.getInstruction().getClass().getInterfaces(); {
NewArray a1 = (NewArray) i1, a2 = (NewArray) i2;
return a1.getArrayType() == a2.getArrayType();
}
return Arrays.equals(c1, c2); // 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;
//int i = 5;
}
if (!i1.getClass().equals(i2.getClass()))
{
return false;
}
return true;
} }
} }

View File

@@ -48,6 +48,12 @@ public class Class extends PoolEntry
index = pool.makeUTF8(name); index = pool.makeUTF8(name);
} }
@Override
public java.lang.String toString()
{
return name;
}
@Override @Override
public boolean equals(Object other) public boolean equals(Object other)
{ {

View File

@@ -29,6 +29,12 @@ public class Method extends PoolEntry
natIndex = is.readUnsignedShort(); natIndex = is.readUnsignedShort();
} }
@Override
public java.lang.String toString()
{
return clazz + "." + nat;
}
@Override @Override
public void resolve(ConstantPool pool) public void resolve(ConstantPool pool)
{ {

View File

@@ -64,6 +64,15 @@ public class NameAndType extends PoolEntry
descriptorIndex = pool.makeUTF8(type.getFullType()); descriptorIndex = pool.makeUTF8(type.getFullType());
} }
@Override
public java.lang.String toString()
{
if (type != null)
return name + " " + type;
else
return name + signature;
}
@Override @Override
public boolean equals(Object other) public boolean equals(Object other)
{ {