diff --git a/.classpath b/.classpath index bb4ae148a3..9a1998c196 100644 --- a/.classpath +++ b/.classpath @@ -6,17 +6,17 @@ - - - - - - + + + + + + diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index 60748290c7..440a8be1d9 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -43,7 +43,7 @@ public class Deob group.buildCallGraph(); checkCallGraph(group); - //checkParameters(group); + checkParameters(group); //execute(group); diff --git a/src/main/java/info/sigterm/deob/Field.java b/src/main/java/info/sigterm/deob/Field.java index 0931b0824a..61119de692 100644 --- a/src/main/java/info/sigterm/deob/Field.java +++ b/src/main/java/info/sigterm/deob/Field.java @@ -2,6 +2,7 @@ package info.sigterm.deob; import info.sigterm.deob.attributes.Attributes; import info.sigterm.deob.attributes.code.Instruction; +import info.sigterm.deob.signature.Type; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -23,7 +24,8 @@ public class Field private Fields fields; private short accessFlags; - private String name, descriptor; + private String name; + private Type type; private Attributes attributes; private ArrayList instructions = new ArrayList(); // instructions which reference this field @@ -37,7 +39,7 @@ public class Field accessFlags = is.readShort(); name = pool.getUTF8(is.readUnsignedShort()); - descriptor = pool.getUTF8(is.readUnsignedShort()); + type = new Type(pool.getUTF8(is.readUnsignedShort())); attributes = new Attributes(this); } @@ -47,7 +49,7 @@ public class Field out.writeShort(accessFlags); out.writeShort(pool.makeUTF8(name)); - out.writeShort(pool.makeUTF8(descriptor)); + out.writeShort(pool.makeUTF8(type.toString())); attributes.write(out); } @@ -66,9 +68,9 @@ public class Field return name; } - public String getDescriptor() + public Type getType() { - return descriptor; + return type; } public Attributes getAttributes() diff --git a/src/main/java/info/sigterm/deob/Fields.java b/src/main/java/info/sigterm/deob/Fields.java index 360bae0602..aa46de1f63 100644 --- a/src/main/java/info/sigterm/deob/Fields.java +++ b/src/main/java/info/sigterm/deob/Fields.java @@ -46,7 +46,7 @@ public class Fields public Field findField(NameAndType nat) { for (Field f : fields) - if (f.getName().equals(nat.getName()) && f.getDescriptor().equals(nat.getDescriptor())) + if (f.getName().equals(nat.getName()) && f.getType().equals(nat.getDescriptorType())) return f; return null; } diff --git a/src/main/java/info/sigterm/deob/Method.java b/src/main/java/info/sigterm/deob/Method.java index 7676aeaac7..ba880b32a7 100644 --- a/src/main/java/info/sigterm/deob/Method.java +++ b/src/main/java/info/sigterm/deob/Method.java @@ -7,6 +7,7 @@ import info.sigterm.deob.attributes.code.Instruction; import info.sigterm.deob.attributes.code.instruction.types.LVTInstruction; import info.sigterm.deob.callgraph.Node; import info.sigterm.deob.pool.NameAndType; +import info.sigterm.deob.signature.Signature; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -22,7 +23,7 @@ public class Method private short accessFlags; private String name; - private String descriptor; + private Signature arguments; private Attributes attributes; private List callsTo = new ArrayList<>(), callsFrom = new ArrayList<>(); @@ -36,7 +37,7 @@ public class Method accessFlags = is.readShort(); name = pool.getUTF8(is.readUnsignedShort()); - descriptor = pool.getUTF8(is.readUnsignedShort()); + arguments = new Signature(pool.getUTF8(is.readUnsignedShort())); attributes = new Attributes(this); } @@ -46,7 +47,7 @@ public class Method out.writeShort(accessFlags); out.writeShort(pool.makeUTF8(name)); - out.writeShort(pool.makeUTF8(descriptor)); + out.writeShort(pool.makeUTF8(arguments.toString())); attributes.write(out); } @@ -65,14 +66,14 @@ public class Method return name; } - public String getDescriptor() + public Signature getDescriptor() { - return descriptor; + return arguments; } public NameAndType getNameAndType() { - return new NameAndType(name, descriptor); + return new NameAndType(name, arguments); } public boolean isStatic() diff --git a/src/main/java/info/sigterm/deob/Methods.java b/src/main/java/info/sigterm/deob/Methods.java index c3dabe4330..c2de700b95 100644 --- a/src/main/java/info/sigterm/deob/Methods.java +++ b/src/main/java/info/sigterm/deob/Methods.java @@ -1,6 +1,7 @@ package info.sigterm.deob; import info.sigterm.deob.pool.NameAndType; +import info.sigterm.deob.signature.Signature; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -57,7 +58,7 @@ public class Methods return null; } - public Method findMethod(String name, String type) + public Method findMethod(String name, Signature type) { for (Method m : methods) if (m.getName().equals(name) && m.getDescriptor().equals(type)) diff --git a/src/main/java/info/sigterm/deob/execution/ClassInstance.java b/src/main/java/info/sigterm/deob/execution/ClassInstance.java index dd724f080d..d5156b08f1 100644 --- a/src/main/java/info/sigterm/deob/execution/ClassInstance.java +++ b/src/main/java/info/sigterm/deob/execution/ClassInstance.java @@ -55,7 +55,7 @@ public class ClassInstance public StaticFieldInstance findStaticField(NameAndType nat) { for (StaticFieldInstance f : fields) - if (f.getField().getName().equals(nat.getName()) && f.getField().getDescriptor().equals(nat.getDescriptor())) + if (f.getField().getName().equals(nat.getName()) && f.getField().getType().equals(nat.getDescriptorType())) return f; return null; } diff --git a/src/main/java/info/sigterm/deob/execution/ObjectInstance.java b/src/main/java/info/sigterm/deob/execution/ObjectInstance.java index a396b192f6..bb9b224964 100644 --- a/src/main/java/info/sigterm/deob/execution/ObjectInstance.java +++ b/src/main/java/info/sigterm/deob/execution/ObjectInstance.java @@ -44,7 +44,7 @@ public class ObjectInstance extends ObjectInstanceBase public FieldInstance getField(NameAndType nat) { for (FieldInstance f : fields) - if (f.getField().getName().equals(nat.getName()) && f.getField().getDescriptor().equals(nat.getDescriptor())) + if (f.getField().getName().equals(nat.getName()) && f.getField().getType().equals(nat.getDescriptorType())) return f; return null; } diff --git a/src/main/java/info/sigterm/deob/pool/NameAndType.java b/src/main/java/info/sigterm/deob/pool/NameAndType.java index 5a5122071d..6821906301 100644 --- a/src/main/java/info/sigterm/deob/pool/NameAndType.java +++ b/src/main/java/info/sigterm/deob/pool/NameAndType.java @@ -1,17 +1,24 @@ package info.sigterm.deob.pool; import info.sigterm.deob.ConstantPool; +import info.sigterm.deob.signature.Signature; +import info.sigterm.deob.signature.Type; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; public class NameAndType extends PoolEntry { private int nameIndex, descriptorIndex; - private java.lang.String name, descriptor; + private java.lang.String name; + /* method signature */ + private Signature signature; + /* type */ + private Type type; public NameAndType(ConstantPool pool) throws IOException { @@ -23,26 +30,34 @@ public class NameAndType extends PoolEntry descriptorIndex = is.readUnsignedShort(); } - public NameAndType(java.lang.String name, java.lang.String type) + public NameAndType(java.lang.String name, Signature type) { super(null, ConstantType.NAME_AND_TYPE); this.name = name; - descriptor = type; + signature = type; } @Override public void resolve() { name = this.getPool().getUTF8(nameIndex); - descriptor = this.getPool().getUTF8(descriptorIndex); + + java.lang.String sig = this.getPool().getUTF8(descriptorIndex); + if (sig.startsWith("(")) + signature = new Signature(sig); + else + type = new Type(sig); } @Override public void prime() { nameIndex = this.getPool().makeUTF8(name); - descriptorIndex = this.getPool().makeUTF8(descriptor); + if (signature != null) + descriptorIndex = this.getPool().makeUTF8(signature.toString()); + else + descriptorIndex = this.getPool().makeUTF8(type.toString()); } @Override @@ -52,7 +67,7 @@ public class NameAndType extends PoolEntry return false; NameAndType nat = (NameAndType) other; - return name.equals(nat.name) && descriptor.equals(nat.descriptor); + return name.equals(nat.name) && Objects.equals(signature, nat.signature) && Objects.equals(type, nat.type); } public java.lang.String getName() @@ -60,15 +75,19 @@ public class NameAndType extends PoolEntry return name; } - public java.lang.String getDescriptor() + public Signature getDescriptor() { - return descriptor; + return signature; + } + + public Type getDescriptorType() + { + return type; } public Object getStackObject() { - java.lang.String desc = getDescriptor(); - switch (desc) + switch (type.toString()) { case "B": return (byte) 0; @@ -90,33 +109,17 @@ public class NameAndType extends PoolEntry return null; } } - - private static Pattern allParamsPattern = Pattern.compile("(\\(.*?\\))"); - private static Pattern paramsPattern = Pattern.compile("(\\[?)(B|C|Z|S|I|J|F|D|(:?L[^;]+;))"); - + public int getNumberOfArgs() { - java.lang.String methodRefType = this.getDescriptor(); - Matcher m = allParamsPattern.matcher(methodRefType); - if (!m.find()) - throw new IllegalArgumentException("Method signature does not contain parameters"); - - java.lang.String paramsDescriptor = m.group(1); - Matcher mParam = paramsPattern.matcher(paramsDescriptor); - - int count = 0; - while (mParam.find()) - count++; - - return count; + return signature.size(); } public boolean isNonVoid() { - java.lang.String methodRefType = this.getDescriptor(); - if (this.getName().equals("")) + if (this.getName().equals("") || this.getName().equals("")) return true; - return !methodRefType.endsWith(")V"); + return !signature.getReturnValue().equals("V"); } @Override diff --git a/src/main/java/info/sigterm/deob/signature/Signature.java b/src/main/java/info/sigterm/deob/signature/Signature.java new file mode 100644 index 0000000000..bda64af7f0 --- /dev/null +++ b/src/main/java/info/sigterm/deob/signature/Signature.java @@ -0,0 +1,66 @@ +package info.sigterm.deob.signature; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Signature +{ + private static Pattern paramRetPattern = Pattern.compile("\\((.*)\\)(.*)"), + paramsPattern = Pattern.compile("(\\[*(?:B|C|Z|S|I|J|F|D|(?:L[^;]*;)))"); + + private List arguments = new ArrayList<>(); + private Type rv; + + public Signature(String str) + { + Matcher m = paramRetPattern.matcher(str); + if (!m.find()) + throw new IllegalArgumentException("Signature has no arguments"); + + String args = m.group(1), ret = m.group(2); + + m = paramsPattern.matcher(args); + while (m.find()) + { + String arg = m.group(1); + arguments.add(new Type(arg)); + } + + rv = new Type(ret); + } + + @Override + public boolean equals(Object other) + { + if (!(other instanceof Signature)) + return false; + + Signature a = (Signature) other; + return arguments.equals(a.arguments) && rv.equals(a.rv); + } + + @Override + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append('('); + for (Type a : arguments) + sb.append(a.toString()); + sb.append(')'); + sb.append(rv.toString()); + return sb.toString(); + } + + public int size() + { + return arguments.size(); + } + + public Type getReturnValue() + { + return rv; + } +} diff --git a/src/main/java/info/sigterm/deob/signature/Type.java b/src/main/java/info/sigterm/deob/signature/Type.java new file mode 100644 index 0000000000..0dd118aa66 --- /dev/null +++ b/src/main/java/info/sigterm/deob/signature/Type.java @@ -0,0 +1,38 @@ +package info.sigterm.deob.signature; + +public class Type +{ + private String type; + private int arrayDimms; + + public Type(String str) + { + while (str.startsWith("[")) + { + ++arrayDimms; + str = str.substring(1); + } + + type = str; + } + + @Override + public boolean equals(Object other) + { + if (!(other instanceof Type)) + return false; + + Type a = (Type) other; + return type.equals(a.type) && arrayDimms == a.arrayDimms; + } + + @Override + public String toString() + { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < arrayDimms; ++i) + sb.append('['); + sb.append(type); + return sb.toString(); + } +}