More execution work

This commit is contained in:
Adam
2015-02-01 17:49:33 -05:00
parent cec4f0ac59
commit e38b4c5212
15 changed files with 161 additions and 17 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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()
{

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -16,4 +16,6 @@ public abstract class ObjectInstanceBase
{
return type;
}
public abstract ObjectInstanceBase dup(Path path, ClassInstance type);
}

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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()
{

View File

@@ -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)
{

View File

@@ -79,4 +79,10 @@ public class NameAndType extends PoolEntry
return count;
}
public boolean isNonVoid()
{
java.lang.String methodRefType = this.getDescriptor();
return !methodRefType.endsWith(")V");
}
}