From 4dc6bfc949d060e6102c336fb60deb85975fca58 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 8 Feb 2015 16:35:58 -0500 Subject: [PATCH] Doesn't execute all paths correctly --- src/main/java/info/sigterm/deob/Deob.java | 2 +- .../deob/attributes/code/Instruction.java | 2 +- .../attributes/code/instructions/AALoad.java | 5 ++- .../attributes/code/instructions/ALoad_0.java | 1 - .../attributes/code/instructions/ALoad_3.java | 1 - .../code/instructions/AStore_0.java | 1 - .../code/instructions/AStore_3.java | 1 - .../attributes/code/instructions/ILoad.java | 2 +- .../attributes/code/instructions/ILoad_1.java | 1 - .../attributes/code/instructions/IMul.java | 5 ++- .../attributes/code/instructions/IStore.java | 1 - .../code/instructions/InvokeSpecial.java | 2 +- .../code/instructions/InvokeStatic.java | 5 ++- .../code/instructions/InvokeVirtual.java | 7 +-- .../code/instructions/LookupSwitch.java | 17 ++++---- .../code/instructions/PutField.java | 5 +++ .../code/instructions/TableSwitch.java | 15 ++++--- .../sigterm/deob/execution/Execution.java | 43 ++++++++++++++++++- .../info/sigterm/deob/execution/Frame.java | 42 ++++++++++++++++-- .../deob/execution/ObjectInstance.java | 2 +- .../info/sigterm/deob/execution/Path.java | 40 ++++++++++++++--- .../info/sigterm/deob/pool/NameAndType.java | 2 + 22 files changed, 160 insertions(+), 42 deletions(-) diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index 441ce73600..7f826bf760 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -33,7 +33,7 @@ public class Deob execute(group); } - + private static void execute(ClassGroup group) throws IOException { ClassFile cf = group.findClass("client"); diff --git a/src/main/java/info/sigterm/deob/attributes/code/Instruction.java b/src/main/java/info/sigterm/deob/attributes/code/Instruction.java index 1d2a6ed6e9..82ce6f3ecb 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/Instruction.java +++ b/src/main/java/info/sigterm/deob/attributes/code/Instruction.java @@ -39,7 +39,7 @@ public abstract class Instruction public String getDesc(Frame frame) { - return type.getName(); + return type.getName() + " at pc " + frame.getPc() + " in " + frame.getMethod().getName() + " " + frame.getMethod().getDescriptor() + " class " + frame.getMethod().getCode().getAttributes().getClassFile().getName(); } protected void addJump(int offset) diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/AALoad.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/AALoad.java index 7b2546d12c..ef28876614 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/AALoad.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/AALoad.java @@ -22,6 +22,9 @@ public class AALoad extends Instruction int index = (int) stack.pop(); ArrayInstance array = (ArrayInstance) stack.pop(); - stack.push(this, array.get(index)); + if (index >= 0 && index < array.getLength()) + stack.push(this, array.get(index)); + else + frame.getPath().throwException(this, null); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/ALoad_0.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/ALoad_0.java index 4fc5bbbfd6..19ab7c30f0 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/ALoad_0.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/ALoad_0.java @@ -18,7 +18,6 @@ public class ALoad_0 extends Instruction public void execute(Frame frame) { Object obj = frame.getVariables().get(0); - assert obj != null; frame.getStack().push(this, obj); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/ALoad_3.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/ALoad_3.java index 0a6932165d..dce3479ff8 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/ALoad_3.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/ALoad_3.java @@ -18,7 +18,6 @@ public class ALoad_3 extends Instruction public void execute(Frame frame) { Object obj = frame.getVariables().get(3); - assert obj != null; frame.getStack().push(this, obj); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/AStore_0.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/AStore_0.java index 96c1349ec0..7105335631 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/AStore_0.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/AStore_0.java @@ -18,7 +18,6 @@ public class AStore_0 extends Instruction public void execute(Frame frame) { Object obj = frame.getStack().pop(); - assert obj != null; frame.getVariables().set(0, obj); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/AStore_3.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/AStore_3.java index f3eb1c7854..92e977cfe5 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/AStore_3.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/AStore_3.java @@ -18,7 +18,6 @@ public class AStore_3 extends Instruction public void execute(Frame frame) { Object obj = frame.getStack().pop(); - assert obj != null; frame.getVariables().set(3, obj); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/ILoad.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/ILoad.java index 5944ff6c6c..36849b2038 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/ILoad.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/ILoad.java @@ -24,7 +24,7 @@ public class ILoad extends Instruction @Override public void execute(Frame frame) { - int i = (int) frame.getVariables().get(index); + Object i = frame.getVariables().get(index); frame.getStack().push(this, i); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/ILoad_1.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/ILoad_1.java index 63d1096ee0..0c999aabc0 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/ILoad_1.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/ILoad_1.java @@ -18,7 +18,6 @@ public class ILoad_1 extends Instruction public void execute(Frame frame) { Object obj = frame.getVariables().get(1); - assert obj instanceof Integer; frame.getStack().push(this, obj); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/IMul.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/IMul.java index c641f32063..0d0d084027 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/IMul.java @@ -21,6 +21,9 @@ public class IMul extends Instruction Integer two = (Integer) stack.pop(); Integer one = (Integer) stack.pop(); - stack.push(this, one * two); + if (one == null || two == null) + stack.push(this, 0); + else + stack.push(this, one * two); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/IStore.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/IStore.java index cab39883b8..f263586b95 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/IStore.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/IStore.java @@ -25,7 +25,6 @@ public class IStore extends Instruction public void execute(Frame frame) { Object obj = frame.getStack().pop(); - assert obj instanceof Integer; frame.getVariables().set(index, obj); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeSpecial.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeSpecial.java index 1baaf3e494..20ce8162e4 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeSpecial.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeSpecial.java @@ -45,7 +45,7 @@ public class InvokeSpecial extends Instruction if (object == null) { - System.out.println("invokespecial for nonexistant function " + method.getNameAndType().getName() + " " + method.getNameAndType().getDescriptor() + " on " + method.getClassEntry().getName() + " (void: " + !method.getNameAndType().isNonVoid() + ")"); + //System.out.println("invokespecial for nonexistant function " + method.getNameAndType().getName() + " " + method.getNameAndType().getDescriptor() + " on " + method.getClassEntry().getName() + " (void: " + !method.getNameAndType().isNonVoid() + ")"); if (method.getNameAndType().isNonVoid()) e.getStack().push(this, null); return; diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeStatic.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeStatic.java index efeea58879..e47184b66f 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeStatic.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeStatic.java @@ -42,8 +42,9 @@ public class InvokeStatic extends Instruction if (otherClass == null) { - System.out.println("invokestatic for nonexistant class " + clazz.getName()); - e.getStack().push(this, null); + //System.out.println("invokestatic for nonexistant class " + clazz.getName()); + if (method.getNameAndType().isNonVoid()) + e.getStack().push(this, null); return; } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeVirtual.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeVirtual.java index 2a52d11cb3..037d187d60 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeVirtual.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeVirtual.java @@ -42,7 +42,7 @@ public class InvokeVirtual extends Instruction ObjectInstance object = (ObjectInstance) e.getStack().pop(); if (object == null) { - System.out.println("invokevirtual on null object for method " + method.getNameAndType().getName() + " " + method.getNameAndType().getDescriptor() + " on " + method.getClassEntry().getName()); + //System.out.println("invokevirtual on null object for method " + method.getNameAndType().getName() + " " + method.getNameAndType().getDescriptor() + " on " + method.getClassEntry().getName()); e.getStack().push(this, null); return; } @@ -54,8 +54,9 @@ public class InvokeVirtual extends Instruction info.sigterm.deob.Method meth = objectType.getClassFile().findMethod(method.getNameAndType()); if (meth == null) { - System.out.println("Unknown method " + method.getNameAndType().getName() + " " + method.getNameAndType().getDescriptor() + " in " + objectType.getClassFile().getName()); - e.getStack().push(this, null); + //System.out.println("Unknown method " + method.getNameAndType().getName() + " " + method.getNameAndType().getDescriptor() + " in " + objectType.getClassFile().getName()); + if (method.getNameAndType().isNonVoid()) + e.getStack().push(this, null); return; } e.getPath().invoke(meth, args); diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/LookupSwitch.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/LookupSwitch.java index 7cb5867c15..9cfd3c4cc7 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/LookupSwitch.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/LookupSwitch.java @@ -4,6 +4,7 @@ import info.sigterm.deob.attributes.code.Instruction; import info.sigterm.deob.attributes.code.InstructionType; import info.sigterm.deob.attributes.code.Instructions; import info.sigterm.deob.execution.Frame; +import info.sigterm.deob.execution.Path; import java.io.DataInputStream; import java.io.IOException; @@ -51,15 +52,15 @@ public class LookupSwitch extends Instruction @Override public void execute(Frame e) { - int key = (int) e.getStack().pop(); + e.getStack().pop(); - for (int i = 0; i < count; ++i) - if (match[i] == key) - { - e.jump(branch[i]); - return; - } + for (int i : branch) + { + Path p = e.getPath().dup(); + p.getCurrentFrame().jump(i); + } - e.jump(def); + Path p = e.getPath().dup(); + p.getCurrentFrame().jump(def); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/PutField.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/PutField.java index 366a61464c..651f444991 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/PutField.java @@ -39,6 +39,11 @@ public class PutField extends Instruction ObjectInstance object = (ObjectInstance) e.getStack().pop(); Object value = e.getStack().pop(); + if (object == null) + { + return; + } + FieldInstance field = object.getField(nat); field.setValue(value); } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/TableSwitch.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/TableSwitch.java index 857a3ac1dc..3f670cbfc4 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/TableSwitch.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/TableSwitch.java @@ -4,6 +4,7 @@ import info.sigterm.deob.attributes.code.Instruction; import info.sigterm.deob.attributes.code.InstructionType; import info.sigterm.deob.attributes.code.Instructions; import info.sigterm.deob.execution.Frame; +import info.sigterm.deob.execution.Path; import java.io.DataInputStream; import java.io.IOException; @@ -49,11 +50,15 @@ public class TableSwitch extends Instruction @Override public void execute(Frame e) { - int index = (int) e.getStack().pop(); + e.getStack().pop(); - if (index < low || index > high) - e.jump(def); - else - e.jump(jumps[index - low]); + for (int i : jumps) + { + Path p = e.getPath().dup(); + p.getCurrentFrame().jump(i); + } + + Path p = e.getPath().dup(); + p.getCurrentFrame().jump(def); } } diff --git a/src/main/java/info/sigterm/deob/execution/Execution.java b/src/main/java/info/sigterm/deob/execution/Execution.java index 336e4c9215..82b749de88 100644 --- a/src/main/java/info/sigterm/deob/execution/Execution.java +++ b/src/main/java/info/sigterm/deob/execution/Execution.java @@ -5,11 +5,15 @@ import info.sigterm.deob.ClassGroup; import info.sigterm.deob.Method; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; public class Execution { private ClassGroup group; private ArrayList paths = new ArrayList(); // paths of execution + private HashMap> visited = new HashMap>(); + //protected HashSet methods = new HashSet(); public Execution(ClassGroup group) { @@ -22,13 +26,50 @@ public class Execution ClassInstance instance = p.getClassInstance(cf); ObjectInstance object = p.createObject(instance); + int count = 1; p.invoke(method, object); - //process(); + while (!paths.isEmpty()) + { + p = paths.remove(0); + ++count; + try + { + System.out.println("Resuming path with " + paths.size() + " remaining"); + p.resume(); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + System.out.println("Done " + count + " paths"); } public void addPath(Path p) { paths.add(p); } + + public boolean visit(Method m) + { + if (visited.containsKey(m)) + return false; + + visited.put(m, new HashSet()); + return true; + } + + public boolean visit(Method m, int pc) + { + HashSet map = visited.get(m); + if (map == null || !map.contains(pc)) + { + map.add(pc); + return true; + } + + return false; + } } diff --git a/src/main/java/info/sigterm/deob/execution/Frame.java b/src/main/java/info/sigterm/deob/execution/Frame.java index a31d5709f9..c1737edb90 100644 --- a/src/main/java/info/sigterm/deob/execution/Frame.java +++ b/src/main/java/info/sigterm/deob/execution/Frame.java @@ -1,6 +1,7 @@ package info.sigterm.deob.execution; import java.util.Collection; +import java.util.HashSet; import info.sigterm.deob.Method; import info.sigterm.deob.attributes.Code; @@ -47,6 +48,11 @@ public class Frame { return method; } + + public int getPc() + { + return pc; + } public Stack getStack() { @@ -67,6 +73,12 @@ public class Frame Instruction i = ins.findInstruction(pc); + if (i == null) + { + System.err.println("Cant find ins at pc " + pc + " in method " + method.getName() + " in " + method.getCode().getAttributes().getClassFile().getName()); + System.exit(-1); + } + try { i.execute(this); @@ -74,7 +86,7 @@ public class Frame } catch (Throwable ex) { - System.err.println("Error executing instruction " + i.getDesc(this) + " in " + method.getName() + " " + method.getDescriptor() + " in class " + method.getMethods().getClassFile().getName() + " at pc " + pc); + System.err.println("Error executing instruction " + i.getDesc(this)); System.err.println("Frame stack (grows downward):"); while (stack.getSize() > 0) { @@ -87,8 +99,8 @@ public class Frame } System.err.println("end of stack"); ex.printStackTrace(); - System.exit(-1); - //throw ex; + //System.exit(-1); + throw ex; } if (oldPc == pc) @@ -102,15 +114,39 @@ public class Frame } } + public void resume() + { + execute(); + } + + public void skip() + { + /* for resume, skip current ins? */ + Instructions ins = method.getCode().getInstructions(); + Instruction i = ins.findInstruction(pc); + pc += i.getLength(); + } + + private void checkLoop() + { + if (!this.getPath().getExecution().visit(method, pc)) + { + System.out.println("Ending frame " + this); + executing = false; + } + } + public void jump(int offset) { assert offset != 0; pc += offset; + checkLoop(); } public void jumpAbsolute(int pc) { this.pc = pc; + checkLoop(); } public Collection getExceptionHandlers() diff --git a/src/main/java/info/sigterm/deob/execution/ObjectInstance.java b/src/main/java/info/sigterm/deob/execution/ObjectInstance.java index dc3882f8e1..a396b192f6 100644 --- a/src/main/java/info/sigterm/deob/execution/ObjectInstance.java +++ b/src/main/java/info/sigterm/deob/execution/ObjectInstance.java @@ -27,7 +27,7 @@ public class ObjectInstance extends ObjectInstanceBase Attributes attributes = field.getAttributes(); ConstantValue cv = (ConstantValue) attributes.findType(AttributeType.CONSTANT_VALUE); - FieldInstance fi = new FieldInstance(this, field, cv.getValue().getObject()); + FieldInstance fi = new FieldInstance(this, field, cv != null ? cv.getValue().getObject() : null); this.fields.add(fi); } } diff --git a/src/main/java/info/sigterm/deob/execution/Path.java b/src/main/java/info/sigterm/deob/execution/Path.java index 33b995819e..532fd1ef54 100644 --- a/src/main/java/info/sigterm/deob/execution/Path.java +++ b/src/main/java/info/sigterm/deob/execution/Path.java @@ -90,20 +90,42 @@ public class Path return other; } + public void resume() + { + for (Frame f : frames) + { + /* top most is at the correct pc */ + if (f == frames.peek()) + break; + + /* move pc past invoke function */ + f.skip(); + } + + /* resume execution */ + while (!frames.isEmpty()) + { + Frame top = frames.peek(); + top.resume(); + if (!frames.isEmpty() && frames.peek() == top) + frames.pop(); // XXX throwing doesnt remove + } + } + public void invoke(Method method, Object... args) { + if (!this.getExecution().visit(method)) + return; + Frame f = new Frame(this, method); Variables vars = f.getVariables(); for (int i = 0; i < args.length; ++i) vars.set(i, args[i]); frames.push(f); - - while (!frames.isEmpty()) - { - f = frames.peek(); - f.execute(); - frames.pop(); - } + System.out.println("Executing frame " + method.getName() + " " + method.getDescriptor()); + f.execute(); + if (frames.isEmpty() == false && frames.peek() == f) + System.err.println("Unpopped frame post execute"); } public void returnFrame(Instruction i, Object value) @@ -144,5 +166,9 @@ public class Path /* handler pc is absolute from the beginning instruction */ other.getCurrentFrame().jumpAbsolute(handler.getHandlerPc()); } + + /* this path stops executing */ + for (Frame f : frames) + f.executing = false; } } diff --git a/src/main/java/info/sigterm/deob/pool/NameAndType.java b/src/main/java/info/sigterm/deob/pool/NameAndType.java index 650a6532ff..0b663c8e1d 100644 --- a/src/main/java/info/sigterm/deob/pool/NameAndType.java +++ b/src/main/java/info/sigterm/deob/pool/NameAndType.java @@ -83,6 +83,8 @@ public class NameAndType extends PoolEntry public boolean isNonVoid() { java.lang.String methodRefType = this.getDescriptor(); + if (this.getName().equals("")) + return true; return !methodRefType.endsWith(")V"); } }