Invokeinterface, among others
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target/
|
||||||
@@ -102,6 +102,19 @@ public class ClassFile
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Method findMethod(NameAndType nat)
|
||||||
|
{
|
||||||
|
Method m = methods.findMethod(nat);
|
||||||
|
if (m != null)
|
||||||
|
return m;
|
||||||
|
|
||||||
|
ClassFile parent = getParent();
|
||||||
|
if (parent != null)
|
||||||
|
return parent.findMethod(nat);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void buildClassGraph()
|
public void buildClassGraph()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package info.sigterm.deob;
|
|||||||
import info.sigterm.deob.attributes.AttributeType;
|
import info.sigterm.deob.attributes.AttributeType;
|
||||||
import info.sigterm.deob.attributes.Attributes;
|
import info.sigterm.deob.attributes.Attributes;
|
||||||
import info.sigterm.deob.attributes.Code;
|
import info.sigterm.deob.attributes.Code;
|
||||||
|
import info.sigterm.deob.pool.UTF8;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -32,6 +33,18 @@ public class Method
|
|||||||
{
|
{
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
UTF8 u = (UTF8) methods.getClassFile().getPool().getEntry(nameIndex);
|
||||||
|
return u.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescriptor()
|
||||||
|
{
|
||||||
|
UTF8 u = (UTF8) methods.getClassFile().getPool().getEntry(descriptorIndex);
|
||||||
|
return u.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
public Code getCode()
|
public Code getCode()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package info.sigterm.deob;
|
package info.sigterm.deob;
|
||||||
|
|
||||||
|
import info.sigterm.deob.pool.NameAndType;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -27,6 +29,14 @@ public class Methods
|
|||||||
{
|
{
|
||||||
return classFile;
|
return classFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Method findMethod(NameAndType nat)
|
||||||
|
{
|
||||||
|
for (Method m : methods)
|
||||||
|
if (m.getName().equals(nat.getName()) && m.getDescriptor().equals(nat.getDescriptor()))
|
||||||
|
return m;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void buildInstructionGraph()
|
public void buildInstructionGraph()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -188,7 +188,6 @@ public enum InstructionType
|
|||||||
INVOKESPECIAL(0xb7, "invokespecial", InvokeSpecial.class),
|
INVOKESPECIAL(0xb7, "invokespecial", InvokeSpecial.class),
|
||||||
INVOKESTATIC(0xb8, "invokestatic", InvokeStatic.class),
|
INVOKESTATIC(0xb8, "invokestatic", InvokeStatic.class),
|
||||||
INVOKEINTERFACE(0xb9, "invokeinterface", InvokeInterface.class),
|
INVOKEINTERFACE(0xb9, "invokeinterface", InvokeInterface.class),
|
||||||
INVOKEDYNAMIC(0xba, "invokedynamic", InvokeDynamic.class),
|
|
||||||
NEW(0xbb, "new", New.class),
|
NEW(0xbb, "new", New.class),
|
||||||
NEWARRAY(0xbc, "newarray", NewArray.class),
|
NEWARRAY(0xbc, "newarray", NewArray.class),
|
||||||
ANEWARRAY(0xbd, "anewarray", ANewArray.class),
|
ANEWARRAY(0xbd, "anewarray", ANewArray.class),
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package info.sigterm.deob.attributes.code.instructions;
|
|||||||
|
|
||||||
import info.sigterm.deob.ClassFile;
|
import info.sigterm.deob.ClassFile;
|
||||||
import info.sigterm.deob.ConstantPool;
|
import info.sigterm.deob.ConstantPool;
|
||||||
import info.sigterm.deob.attributes.ConstantValue;
|
|
||||||
import info.sigterm.deob.attributes.code.Instruction;
|
import info.sigterm.deob.attributes.code.Instruction;
|
||||||
import info.sigterm.deob.attributes.code.InstructionType;
|
import info.sigterm.deob.attributes.code.InstructionType;
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
@@ -12,7 +11,6 @@ import info.sigterm.deob.execution.StaticFieldInstance;
|
|||||||
import info.sigterm.deob.pool.Class;
|
import info.sigterm.deob.pool.Class;
|
||||||
import info.sigterm.deob.pool.Field;
|
import info.sigterm.deob.pool.Field;
|
||||||
import info.sigterm.deob.pool.NameAndType;
|
import info.sigterm.deob.pool.NameAndType;
|
||||||
import info.sigterm.deob.pool.PoolEntry;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -51,10 +49,7 @@ public class GetStatic extends Instruction
|
|||||||
|
|
||||||
ClassInstance ci = frame.getPath().getClassInstance(cf);
|
ClassInstance ci = frame.getPath().getClassInstance(cf);
|
||||||
StaticFieldInstance fi = ci.findStaticField(nat);
|
StaticFieldInstance fi = ci.findStaticField(nat);
|
||||||
ConstantValue value = fi.getValue();
|
Object ovalue = fi.getValue();
|
||||||
|
|
||||||
PoolEntry pe = value.getValue();
|
|
||||||
Object ovalue = pe.getObject();
|
|
||||||
|
|
||||||
frame.getStack().push(ovalue);
|
frame.getStack().push(ovalue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package info.sigterm.deob.attributes.code.instructions;
|
|
||||||
|
|
||||||
import info.sigterm.deob.attributes.code.Instruction;
|
|
||||||
import info.sigterm.deob.attributes.code.InstructionType;
|
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class InvokeDynamic extends Instruction
|
|
||||||
{
|
|
||||||
private int index;
|
|
||||||
|
|
||||||
public InvokeDynamic(Instructions instructions, InstructionType type, int pc) throws IOException
|
|
||||||
{
|
|
||||||
super(instructions, type, pc);
|
|
||||||
|
|
||||||
DataInputStream is = instructions.getCode().getAttributes().getStream();
|
|
||||||
index = is.readUnsignedShort();
|
|
||||||
is.skip(2);
|
|
||||||
length += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,15 @@
|
|||||||
package info.sigterm.deob.attributes.code.instructions;
|
package info.sigterm.deob.attributes.code.instructions;
|
||||||
|
|
||||||
|
import info.sigterm.deob.ClassFile;
|
||||||
|
import info.sigterm.deob.ConstantPool;
|
||||||
|
import info.sigterm.deob.Method;
|
||||||
import info.sigterm.deob.attributes.code.Instruction;
|
import info.sigterm.deob.attributes.code.Instruction;
|
||||||
import info.sigterm.deob.attributes.code.InstructionType;
|
import info.sigterm.deob.attributes.code.InstructionType;
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
|
import info.sigterm.deob.execution.ClassInstance;
|
||||||
|
import info.sigterm.deob.execution.Frame;
|
||||||
|
import info.sigterm.deob.execution.ObjectInstance;
|
||||||
|
import info.sigterm.deob.pool.InterfaceMethod;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -23,4 +30,24 @@ public class InvokeInterface extends Instruction
|
|||||||
length += 4;
|
length += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Frame e)
|
||||||
|
{
|
||||||
|
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
|
||||||
|
|
||||||
|
ConstantPool pool = thisClass.getPool();
|
||||||
|
InterfaceMethod method = (InterfaceMethod) pool.getEntry(index);
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
Method meth = objectType.getClassFile().findMethod(method.getNameAndType());
|
||||||
|
e.getPath().invoke(meth, args);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package info.sigterm.deob.attributes.code.instructions;
|
|||||||
import info.sigterm.deob.attributes.code.Instruction;
|
import info.sigterm.deob.attributes.code.Instruction;
|
||||||
import info.sigterm.deob.attributes.code.InstructionType;
|
import info.sigterm.deob.attributes.code.InstructionType;
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
|
import info.sigterm.deob.execution.Frame;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -20,4 +21,38 @@ public class NewArray extends Instruction
|
|||||||
length += 1;
|
length += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Frame e)
|
||||||
|
{
|
||||||
|
int count = (int) e.getStack().pop();
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
e.getStack().push(new boolean[count]);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
e.getStack().push(new char[count]);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
e.getStack().push(new float[count]);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
e.getStack().push(new double[count]);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
e.getStack().push(new byte[count]);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
e.getStack().push(new short[count]);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
e.getStack().push(new int[count]);
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
e.getStack().push(new long[count]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
package info.sigterm.deob.attributes.code.instructions;
|
package info.sigterm.deob.attributes.code.instructions;
|
||||||
|
|
||||||
|
import info.sigterm.deob.ClassFile;
|
||||||
|
import info.sigterm.deob.ConstantPool;
|
||||||
import info.sigterm.deob.attributes.code.Instruction;
|
import info.sigterm.deob.attributes.code.Instruction;
|
||||||
import info.sigterm.deob.attributes.code.InstructionType;
|
import info.sigterm.deob.attributes.code.InstructionType;
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
|
import info.sigterm.deob.execution.FieldInstance;
|
||||||
|
import info.sigterm.deob.execution.Frame;
|
||||||
|
import info.sigterm.deob.execution.ObjectInstance;
|
||||||
|
import info.sigterm.deob.pool.Field;
|
||||||
|
import info.sigterm.deob.pool.NameAndType;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -20,4 +27,20 @@ public class PutField extends Instruction
|
|||||||
length += 2;
|
length += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Frame e)
|
||||||
|
{
|
||||||
|
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
|
||||||
|
|
||||||
|
ConstantPool pool = thisClass.getPool();
|
||||||
|
Field entry = (Field) pool.getEntry(index);
|
||||||
|
NameAndType nat = entry.getNameAndType();
|
||||||
|
|
||||||
|
ObjectInstance object = (ObjectInstance) e.getStack().pop();
|
||||||
|
Object value = e.getStack().pop();
|
||||||
|
|
||||||
|
FieldInstance field = object.getField(nat);
|
||||||
|
field.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
package info.sigterm.deob.attributes.code.instructions;
|
package info.sigterm.deob.attributes.code.instructions;
|
||||||
|
|
||||||
|
import info.sigterm.deob.ClassFile;
|
||||||
|
import info.sigterm.deob.ConstantPool;
|
||||||
import info.sigterm.deob.attributes.code.Instruction;
|
import info.sigterm.deob.attributes.code.Instruction;
|
||||||
import info.sigterm.deob.attributes.code.InstructionType;
|
import info.sigterm.deob.attributes.code.InstructionType;
|
||||||
import info.sigterm.deob.attributes.code.Instructions;
|
import info.sigterm.deob.attributes.code.Instructions;
|
||||||
|
import info.sigterm.deob.execution.ClassInstance;
|
||||||
|
import info.sigterm.deob.execution.Frame;
|
||||||
|
import info.sigterm.deob.execution.StaticFieldInstance;
|
||||||
|
import info.sigterm.deob.pool.Class;
|
||||||
|
import info.sigterm.deob.pool.Field;
|
||||||
|
import info.sigterm.deob.pool.NameAndType;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -20,4 +28,25 @@ public class PutStatic extends Instruction
|
|||||||
length += 2;
|
length += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Frame e)
|
||||||
|
{
|
||||||
|
ClassFile thisClass = this.getInstructions().getCode().getAttributes().getClassFile();
|
||||||
|
|
||||||
|
ConstantPool pool = thisClass.getPool();
|
||||||
|
Field entry = (Field) pool.getEntry(index);
|
||||||
|
Class clazz = entry.getClassEntry();
|
||||||
|
NameAndType nat = entry.getNameAndType();
|
||||||
|
|
||||||
|
Object value = e.getStack().pop();
|
||||||
|
|
||||||
|
ClassFile cf = thisClass.getGroup().findClass(clazz.getName());
|
||||||
|
if (cf == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ClassInstance ci = e.getPath().getClassInstance(cf);
|
||||||
|
StaticFieldInstance fi = ci.findStaticField(nat);
|
||||||
|
fi.setField(value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class Execution
|
|||||||
public void run(Method method, Object... args)
|
public void run(Method method, Object... args)
|
||||||
{
|
{
|
||||||
Path p = new Path(this);
|
Path p = new Path(this);
|
||||||
p.init(method, args);
|
p.invoke(method, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPath(Path p)
|
public void addPath(Path p)
|
||||||
|
|||||||
@@ -24,4 +24,9 @@ public class FieldInstance
|
|||||||
{
|
{
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setValue(Object obj)
|
||||||
|
{
|
||||||
|
value = obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,6 @@ public class Frame
|
|||||||
{
|
{
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(Object[] args)
|
|
||||||
{
|
|
||||||
for (Object o : args)
|
|
||||||
stack.push(o);
|
|
||||||
|
|
||||||
execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute()
|
public void execute()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,13 +64,6 @@ public class Path
|
|||||||
{
|
{
|
||||||
return frames.peek();
|
return frames.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(Method method, Object[] args)
|
|
||||||
{
|
|
||||||
Frame f = new Frame(this, method);
|
|
||||||
frames.push(f);
|
|
||||||
f.init(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path dup()
|
public Path dup()
|
||||||
{
|
{
|
||||||
@@ -78,4 +71,14 @@ public class Path
|
|||||||
execution.addPath(other);
|
execution.addPath(other);
|
||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void invoke(Method method, Object[] args)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
f.execute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ public class StaticFieldInstance
|
|||||||
{
|
{
|
||||||
private ClassInstance clazz;
|
private ClassInstance clazz;
|
||||||
private Field field;
|
private Field field;
|
||||||
private ConstantValue value;
|
private Object value;
|
||||||
|
|
||||||
public StaticFieldInstance(ClassInstance clazz, Field field, ConstantValue value)
|
public StaticFieldInstance(ClassInstance clazz, Field field, ConstantValue value)
|
||||||
{
|
{
|
||||||
this.clazz = clazz;
|
this.clazz = clazz;
|
||||||
this.field = field;
|
this.field = field;
|
||||||
this.value = value;
|
this.value = value.getValue().getObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Field getField()
|
public Field getField()
|
||||||
@@ -21,8 +21,13 @@ public class StaticFieldInstance
|
|||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConstantValue getValue()
|
public Object getValue()
|
||||||
{
|
{
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setField(Object obj)
|
||||||
|
{
|
||||||
|
value = obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,14 @@ public class InterfaceMethod extends PoolEntry
|
|||||||
classIndex = is.readUnsignedShort();
|
classIndex = is.readUnsignedShort();
|
||||||
nameAndTypeIndex = is.readUnsignedShort();
|
nameAndTypeIndex = is.readUnsignedShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Class getClassEntry()
|
||||||
|
{
|
||||||
|
return (Class) this.getPool().getEntry(classIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NameAndType getNameAndType()
|
||||||
|
{
|
||||||
|
return (NameAndType) this.getPool().getEntry(nameAndTypeIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user