More execution work
This commit is contained in:
@@ -20,10 +20,13 @@ public class AAStore extends Instruction
|
||||
{
|
||||
Stack stack = frame.getStack();
|
||||
|
||||
ObjectInstance value = (ObjectInstance) stack.pop(); // Strings are objects too, so this cast fails
|
||||
Object value = stack.pop();
|
||||
int index = (int) stack.pop();
|
||||
ArrayInstance array = (ArrayInstance) stack.pop();
|
||||
|
||||
if (array == null)
|
||||
return;
|
||||
|
||||
array.put(value, index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ public class AStore extends Instruction
|
||||
public void execute(Frame frame)
|
||||
{
|
||||
Object obj = frame.getStack().pop();
|
||||
assert obj != null;
|
||||
frame.getVariables().set(index, obj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import info.sigterm.deob.execution.ClassInstance;
|
||||
import info.sigterm.deob.execution.Frame;
|
||||
import info.sigterm.deob.execution.ObjectInstance;
|
||||
import info.sigterm.deob.pool.Method;
|
||||
import info.sigterm.deob.pool.PoolEntry;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -36,15 +37,31 @@ public class InvokeSpecial extends Instruction
|
||||
int count = method.getNameAndType().getNumberOfArgs();
|
||||
|
||||
ObjectInstance object = (ObjectInstance) e.getStack().pop();
|
||||
ClassInstance objectType = object.getType();
|
||||
|
||||
Object[] args = new Object[count + 1];
|
||||
args[0] = object;
|
||||
for (int i = 1; i < count + 1; ++i)
|
||||
args[i] = e.getStack().pop();
|
||||
|
||||
if (object == null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
ClassInstance objectType = object.getType();
|
||||
info.sigterm.deob.Method meth = objectType.getClassFile().findMethod(method.getNameAndType());
|
||||
e.getPath().invoke(meth, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDesc(Frame frame)
|
||||
{
|
||||
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
|
||||
Method method = (Method) thisClass.getPool().getEntry(index);
|
||||
|
||||
return "invokespecial " + method.getNameAndType().getDescriptor() + " on " + method.getClassEntry().getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class InvokeVirtual extends Instruction
|
||||
ObjectInstance object = (ObjectInstance) e.getStack().pop();
|
||||
if (object == null)
|
||||
{
|
||||
System.out.println("Invoke on a null object");
|
||||
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;
|
||||
}
|
||||
@@ -56,7 +56,6 @@ public class InvokeVirtual extends Instruction
|
||||
{
|
||||
System.out.println("Unknown method " + method.getNameAndType().getName() + " " + method.getNameAndType().getDescriptor() + " in " + objectType.getClassFile().getName());
|
||||
e.getStack().push(this, null);
|
||||
//meth.getDescriptor()
|
||||
return;
|
||||
}
|
||||
e.getPath().invoke(meth, args);
|
||||
|
||||
@@ -1,22 +1,30 @@
|
||||
package info.sigterm.deob.execution;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
public class ArrayInstance extends ObjectInstanceBase
|
||||
{
|
||||
private ObjectInstance[] array;
|
||||
private Object[] array;
|
||||
|
||||
public ArrayInstance(Path path, ClassInstance type, int len)
|
||||
{
|
||||
super(path, type);
|
||||
this.array = new ObjectInstance[len];
|
||||
this.array = new Object[len];
|
||||
}
|
||||
|
||||
public void put(ObjectInstance obj, int idx)
|
||||
private ArrayInstance(ArrayInstance other, Path path, ClassInstance type)
|
||||
{
|
||||
super(path, type);
|
||||
this.array = Arrays.copyOf(other.array, other.array.length);
|
||||
}
|
||||
|
||||
public void put(Object obj, int idx)
|
||||
{
|
||||
array[idx] = obj;
|
||||
}
|
||||
|
||||
public ObjectInstance get(int idx)
|
||||
public Object get(int idx)
|
||||
{
|
||||
return array[idx];
|
||||
}
|
||||
@@ -25,4 +33,10 @@ public class ArrayInstance extends ObjectInstanceBase
|
||||
{
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectInstanceBase dup(Path path, ClassInstance type)
|
||||
{
|
||||
return new ArrayInstance(this, path, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,14 @@ public class ClassInstance
|
||||
this.fields.add(fi);
|
||||
}
|
||||
}
|
||||
|
||||
protected ClassInstance(Path path, ClassInstance other)
|
||||
{
|
||||
this.path = path;
|
||||
this.clazz = other.clazz;
|
||||
for (StaticFieldInstance f : other.fields)
|
||||
this.fields.add(new StaticFieldInstance(other, f));
|
||||
}
|
||||
|
||||
public Path getPath()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,13 @@ public class FieldInstance
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
protected FieldInstance(ObjectInstance object, FieldInstance other)
|
||||
{
|
||||
this.object = object;
|
||||
this.field = other.field;
|
||||
this.value = other.value;
|
||||
}
|
||||
|
||||
public Field getField()
|
||||
{
|
||||
return field;
|
||||
|
||||
@@ -24,6 +24,16 @@ public class Frame
|
||||
stack = new Stack(code.getMaxStack());
|
||||
variables = new Variables(code.getMaxLocals());
|
||||
}
|
||||
|
||||
protected Frame(Path path, Frame other)
|
||||
{
|
||||
this.path = path;
|
||||
this.method = other.method;
|
||||
this.executing = other.executing;
|
||||
this.pc = other.pc;
|
||||
this.stack = new Stack(other.stack);
|
||||
this.variables = new Variables(other.variables);
|
||||
}
|
||||
|
||||
public Path getPath()
|
||||
{
|
||||
@@ -60,7 +70,20 @@ public class Frame
|
||||
catch (Throwable ex)
|
||||
{
|
||||
System.err.println("Error executing instruction in " + method.getName() + " " + method.getDescriptor() + " in class " + method.getMethods().getClassFile().getName() + " at pc " + pc);
|
||||
throw ex;
|
||||
System.err.println("Frame stack (grows downward):");
|
||||
while (stack.getSize() > 0)
|
||||
{
|
||||
Instruction stacki = stack.getIns();
|
||||
Object obj = stack.pop();
|
||||
if (obj != null)
|
||||
System.err.println(" " + obj + " (class " + obj.getClass().getName() + ") pushed by instruction " + stacki + " at pc " + stacki.getPc());
|
||||
else
|
||||
System.err.println(" " + obj + " pushed by instruction " + stacki + " at pc " + stacki.getPc());
|
||||
}
|
||||
System.err.println("end of stack");
|
||||
ex.printStackTrace();
|
||||
System.exit(-1);
|
||||
//throw ex;
|
||||
}
|
||||
|
||||
if (oldPc == pc)
|
||||
|
||||
@@ -32,6 +32,15 @@ public class ObjectInstance extends ObjectInstanceBase
|
||||
}
|
||||
}
|
||||
|
||||
private ObjectInstance(ObjectInstance other, Path path, ClassInstance type)
|
||||
{
|
||||
super(path, type);
|
||||
|
||||
/* copy fields */
|
||||
for (FieldInstance field : other.fields)
|
||||
this.fields.add(new FieldInstance(this, field));
|
||||
}
|
||||
|
||||
public FieldInstance getField(NameAndType nat)
|
||||
{
|
||||
for (FieldInstance f : fields)
|
||||
@@ -39,4 +48,10 @@ public class ObjectInstance extends ObjectInstanceBase
|
||||
return f;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectInstanceBase dup(Path path, ClassInstance type)
|
||||
{
|
||||
return new ObjectInstance(this, path, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,6 @@ public abstract class ObjectInstanceBase
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public abstract ObjectInstanceBase dup(Path path, ClassInstance type);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,13 @@ import info.sigterm.deob.Method;
|
||||
import info.sigterm.deob.attributes.code.Instruction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Path
|
||||
{
|
||||
private Execution execution;
|
||||
private ArrayList<ClassInstance> classes = new ArrayList<ClassInstance>();
|
||||
private ArrayList<ObjectInstance> objects = new ArrayList<ObjectInstance>();
|
||||
private ArrayList<ObjectInstanceBase> objects = new ArrayList<ObjectInstanceBase>();
|
||||
private java.util.Stack<Frame> frames = new java.util.Stack<Frame>(); // current execution frames
|
||||
|
||||
public Path(Execution execution)
|
||||
@@ -20,11 +21,23 @@ public class Path
|
||||
|
||||
private Path(Path other)
|
||||
{
|
||||
HashMap<ClassInstance, ClassInstance> classmap = new HashMap<ClassInstance, ClassInstance>();
|
||||
|
||||
this.execution = other.execution;
|
||||
this.classes = new ArrayList<ClassInstance>(other.classes);
|
||||
this.objects = new ArrayList<ObjectInstance>(other.objects);
|
||||
this.frames = new java.util.Stack<Frame>();
|
||||
this.frames.addAll(other.frames);
|
||||
|
||||
for (ClassInstance c : other.classes)
|
||||
{
|
||||
ClassInstance newclass = new ClassInstance(this, c);
|
||||
classmap.put(c, newclass);
|
||||
this.classes.add(newclass);
|
||||
}
|
||||
|
||||
for (ObjectInstanceBase o : other.objects)
|
||||
o.dup(this, classmap.get(o.getType()));
|
||||
|
||||
/* iteration order of a Stack is in reverse */
|
||||
for (Frame f : other.frames)
|
||||
frames.push(new Frame(this, f));
|
||||
}
|
||||
|
||||
public Execution getExecution()
|
||||
@@ -58,7 +71,9 @@ public class Path
|
||||
|
||||
public ArrayInstance createArray(ClassInstance type, int len)
|
||||
{
|
||||
return new ArrayInstance(this, type, len);
|
||||
ArrayInstance arr = new ArrayInstance(this, type, len);
|
||||
objects.add(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public Frame getCurrentFrame()
|
||||
@@ -99,7 +114,7 @@ public class Path
|
||||
|
||||
public void throwException(ObjectInstance exception)
|
||||
{
|
||||
System.out.println("throw " + exception);
|
||||
System.out.println("XXX throw " + exception);
|
||||
//XXX
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package info.sigterm.deob.execution;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import info.sigterm.deob.attributes.code.Instruction;
|
||||
|
||||
public class Stack
|
||||
@@ -13,6 +15,13 @@ public class Stack
|
||||
stack = new Object[sz];
|
||||
ins = new Instruction[sz];
|
||||
}
|
||||
|
||||
protected Stack(Stack other)
|
||||
{
|
||||
this.size = other.size;
|
||||
this.stack = Arrays.copyOf(other.stack, other.stack.length);
|
||||
this.ins = Arrays.copyOf(other.ins, other.ins.length);
|
||||
}
|
||||
|
||||
public void push(Instruction i, Object obj)
|
||||
{
|
||||
@@ -24,6 +33,14 @@ public class Stack
|
||||
|
||||
++size;
|
||||
}
|
||||
|
||||
public Instruction getIns()
|
||||
{
|
||||
if (size <= 0)
|
||||
throw new RuntimeException("Stack underflow");
|
||||
|
||||
return ins[size - 1];
|
||||
}
|
||||
|
||||
public Object pop()
|
||||
{
|
||||
@@ -32,4 +49,9 @@ public class Stack
|
||||
|
||||
return stack[--size];
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,13 @@ public class StaticFieldInstance
|
||||
if (value != null)
|
||||
this.value = value.getValue().getObject();
|
||||
}
|
||||
|
||||
protected StaticFieldInstance(ClassInstance clazz, StaticFieldInstance other)
|
||||
{
|
||||
this.clazz = clazz;
|
||||
this.field = other.field;
|
||||
this.value = other.value;
|
||||
}
|
||||
|
||||
public Field getField()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package info.sigterm.deob.execution;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Variables
|
||||
{
|
||||
private Object[] variables;
|
||||
@@ -8,6 +10,11 @@ public class Variables
|
||||
{
|
||||
variables = new Object[sz];
|
||||
}
|
||||
|
||||
protected Variables(Variables other)
|
||||
{
|
||||
this.variables = Arrays.copyOf(other.variables, other.variables.length);
|
||||
}
|
||||
|
||||
public void set(int index, Object value)
|
||||
{
|
||||
|
||||
@@ -79,4 +79,10 @@ public class NameAndType extends PoolEntry
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean isNonVoid()
|
||||
{
|
||||
java.lang.String methodRefType = this.getDescriptor();
|
||||
return !methodRefType.endsWith(")V");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user