diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index e8caba48b6..dd0e388730 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -1,25 +1,12 @@ package info.sigterm.deob; import info.sigterm.deob.deobfuscators.IllegalStateExceptions; -import info.sigterm.deob.deobfuscators.Jumps; -import info.sigterm.deob.deobfuscators.ModularArithmeticDeobfuscation; import info.sigterm.deob.deobfuscators.RenameUnique; import info.sigterm.deob.deobfuscators.RuntimeExceptions; import info.sigterm.deob.deobfuscators.UnusedBlocks; import info.sigterm.deob.deobfuscators.UnusedFields; import info.sigterm.deob.deobfuscators.UnusedMethods; import info.sigterm.deob.deobfuscators.UnusedParameters; -import info.sigterm.deob.execution.Execution; -import info.sigterm.deob.execution.Frame; -import info.sigterm.deob.pool.NameAndType; -import info.sigterm.deob.signature.Signature; -import info.sigterm.deob.attributes.Code; -import info.sigterm.deob.attributes.code.Instruction; -import info.sigterm.deob.attributes.code.Instructions; -import info.sigterm.deob.attributes.code.instructions.Goto; -import info.sigterm.deob.attributes.code.instructions.GotoW; -import info.sigterm.deob.attributes.code.instructions.Return; -import info.sigterm.deob.block.Block; import info.sigterm.deob.deobfuscators.ConstantParameter; import java.io.ByteArrayOutputStream; @@ -28,9 +15,7 @@ import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.Enumeration; -import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; @@ -76,8 +61,8 @@ public class Deob new ConstantParameter().run(group); bdur = System.currentTimeMillis() - bstart; System.out.println("constant param took " + bdur/1000L + " seconds"); -// -// // remove unhit blocks + + // remove unhit blocks bstart = System.currentTimeMillis(); new UnusedBlocks().run(group); bdur = System.currentTimeMillis() - bstart; diff --git a/src/main/java/info/sigterm/deob/deobfuscators/ConstantParameter.java b/src/main/java/info/sigterm/deob/deobfuscators/ConstantParameter.java index 209625fb13..91bd69208f 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/ConstantParameter.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/ConstantParameter.java @@ -26,7 +26,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.MultiValueMap; class ConstantMethodParameter @@ -35,7 +34,6 @@ class ConstantMethodParameter public int paramIndex; public int lvtIndex; public Object value; - //public InstructionContext invoke; // invoking instruction @Override public int hashCode() @@ -50,20 +48,25 @@ class ConstantMethodParameter @Override public boolean equals(Object obj) { - if (obj == null) { + if (obj == null) + { return false; } - if (getClass() != obj.getClass()) { + if (getClass() != obj.getClass()) + { return false; } final ConstantMethodParameter other = (ConstantMethodParameter) obj; - if (!Objects.equals(this.methods, other.methods)) { + if (!Objects.equals(this.methods, other.methods)) + { return false; } - if (this.paramIndex != other.paramIndex) { + if (this.paramIndex != other.paramIndex) + { return false; } - if (!Objects.equals(this.value, other.value)) { + if (!Objects.equals(this.value, other.value)) + { return false; } return true; @@ -77,24 +80,12 @@ class MethodGroup public List methods; // methods that can be invoked public Collection constantParameters; // parameters which are always constant for all invocations public List cmps = new ArrayList<>(); // cmps for all methods in the group, which hold the values. - -// public List getConstantParametersFor(Method m, int parameter) -// { -// List out = new ArrayList<>(); -// for (ConstantMethodParameter c : cmps) -// if (c.method == m && c.paramNum == parameter) -// out.add(c); -// return out; -// } } public class ConstantParameter implements Deobfuscator { private List parameters = new ArrayList<>(); private MultiValueMap nonconst = new MultiValueMap<>(); // methods with non const parameters - //private MultiValueMap parameters = new MultiValueMap<>(); - // methods can be in more than one group because of multiple inheritance with interfaces - //private MultiValueMap methodGroups = new MultiValueMap<>(); private List methodGroups = new ArrayList<>(); private void checkMethodsAreConsistent(List methods) @@ -132,12 +123,7 @@ public class ConstantParameter implements Deobfuscator if (ctx.getPushed().getInstruction() instanceof PushConstantInstruction) { - PushConstantInstruction pc = (PushConstantInstruction) ctx.getPushed().getInstruction(); - - if (method.getMethods().getClassFile().getName().equals("client") && method.getName().equals("i")) - { - int i = 5; - } + PushConstantInstruction pc = (PushConstantInstruction) ctx.getPushed().getInstruction(); if (!(pc.getConstant().getObject() instanceof Integer) && (!(pc.getConstant().getObject() instanceof Byte))) continue; @@ -147,7 +133,6 @@ public class ConstantParameter implements Deobfuscator cmp.paramIndex = parameterIndex; cmp.lvtIndex = lvtOffset; cmp.value = pc.getConstant().getObject(); - //cmp.invoke = invokeCtx; // already exists? for (ConstantMethodParameter c : parameters) @@ -174,19 +159,6 @@ public class ConstantParameter implements Deobfuscator } } -// private Collection getParametersFor(Method method) -// { -// Collection params = parameters.getCollection(method); -// Collection out = new ArrayList<>(); -// -// if (params != null) -// for (ConstantMethodParameter p : params) -// if (!out.contains(p.paramNum)) -// out.add(p.paramNum); -// -// return out; -// } -// private void findParameters(Execution execution) { for (Frame frame : execution.processedFrames) @@ -200,39 +172,6 @@ public class ConstantParameter implements Deobfuscator continue; findConstantParameter(execution, methods, ins); - - /* - // get common constant indexes from all methods that can possibly be called - Collection parameterIndexes = null; - for (Method m : methods) - { - Collection idxs = getParametersFor(m); - - if (parameterIndexes == null) - parameterIndexes = idxs; - else - parameterIndexes = CollectionUtils.intersection(parameterIndexes, idxs); - } - - MethodGroup group = new MethodGroup(); - group.methods = methods; - group.constantParameters = parameterIndexes; - - // build constant method parameters - for (Method m : methods) - { - Collection params = parameters.getCollection(m); - if (params != null) - for (ConstantMethodParameter c : params) - if (parameterIndexes.contains(c.paramNum)) - group.cmps.add(c); - } - - // insert - methodGroups.add(group); - //for (Method m : methods) - // methodGroups.put(m, group); - */ } } @@ -282,34 +221,31 @@ public class ConstantParameter implements Deobfuscator @Override public boolean equals(Object obj) { - if (obj == null) { + if (obj == null) + { return false; } - if (getClass() != obj.getClass()) { + if (getClass() != obj.getClass()) + { return false; } final LogicallyDeadOp other = (LogicallyDeadOp) obj; - if (!Objects.equals(this.compCtx.getInstruction(), other.compCtx.getInstruction())) { + if (!Objects.equals(this.compCtx.getInstruction(), other.compCtx.getInstruction())) + { return false; } - if (this.branch != other.branch) { + if (this.branch != other.branch) + { return false; } return true; } - - } + // find all comparisons of lvtIndex in method and record branch taken private List isLogicallyDead(Execution execution, Method method, int lvtIndex, Object value) { - Boolean branch = null; List ops = new ArrayList<>(); - // find if instruction - // one side must be constant, other must be parameterIndex - - //int offset = method.isStatic() ? 0 : 1; - //int variableIndex = paramIndex + offset; for (Frame frame : execution.processedFrames) { @@ -318,15 +254,6 @@ public class ConstantParameter implements Deobfuscator for (InstructionContext ins : frame.getInstructions()) { - // XXX this should look for field accesses and see hwats done with it. -// if (ins.getInstruction() instanceof LVTInstruction) -// { -// LVTInstruction lvtins = (LVTInstruction) ins.getInstruction(); -// -// if (lvtins.getVariableIndex() != variableIndex) -// continue; -// } - if (!(ins.getInstruction() instanceof ComparisonInstruction)) continue; @@ -383,43 +310,26 @@ public class ConstantParameter implements Deobfuscator // the result of the comparison doesn't matter, only that it always goes the same direction for every invocation boolean result = doLogicalComparison(value, comp, otherValue); - /*if (branch == null) - branch = result; - else if (branch != result) - return null;*/ LogicallyDeadOp deadOp = new LogicallyDeadOp(); deadOp.compCtx = ins; deadOp.branch = result; ops.add(deadOp); - //if (!logicallyDead) - // return false; // if one frame finds it not logically dead, then stop } } return ops; - //return branch != null ? true /* always logically taking the same branch */ : false /* totally unused XXX */; - //return true; - } - - private void removeLogicallyDead(Execution execution, Method method, int lvtIndex) - { - } private Map > deadops = new HashMap<>(); private Set invalidDeadops = new HashSet<>(); + // check every method parameter that we've identified as being passed constants to see if it's logically dead private void findLogicallyDeadOperations(Execution execution) { outer: for (ConstantMethodParameter cmp : parameters) { -// Method method2 = cmp.methods.get(0); -// if (method2.getMethods().getClassFile().getName().equals("gy") && method2.getName().equals("y")) -// { -// int i = 5; -// } for (Method method : cmp.methods) { if (invalidDeadops.contains(method)) @@ -432,6 +342,7 @@ public class ConstantParameter implements Deobfuscator if (existing != null) if (!existing.equals(deadOps)) { + // one of the branches taken differs because of the value, skip it deadops.remove(method); invalidDeadops.add(method); continue; @@ -442,71 +353,14 @@ public class ConstantParameter implements Deobfuscator } deadops.put(method, deadOps); - //if (deadOps == null) - //continue; - //if (isDead == null || !isDead) - // continue outer; - } - - // param is logically dead for all possible methods - //Method method = cmp.methods.get(0); - //System.out.println(method.getMethods().getClassFile().getName() + "." + method.getName() + " has dead param " + cmp.paramIndex); - - for (Method method : cmp.methods) - { - // remove dead parameter. - - // I already have an unused parameter deob which detects them and removes them, so don't have to clean up those. - // Additionally there is an unused block deob which can remove unused blocks of code, so - - // remove conditional jump, insert goto? - //removeLogicallyDead(execution, method, cmp.lvtIndex); } } -// for (MethodGroup group : methodGroups) -// //for (Object ogroup : methodGroups.values()) -// { -// System.out.println("Iterating group " + group); -// // MethodGroup group = (MethodGroup) ogroup; -// for (Method m : group.methods) -// { -// System.out.println("Iterating method " + m); -// for (int parameterIndex : group.constantParameters) -// { -// // constants used in this parameter index when calling this method -// List cmps = group.getConstantParametersFor(m, parameterIndex); -// -// // iterate instructions of method and find comparisons to parameter -// // remove if all are logically dead. rely on unused parameter deob to remove -// // the parameter. -// System.out.println(cmps.size() + " calls to " + m.getMethods().getClassFile().getName() + "." + m.getName() + " with index " + parameterIndex); -// } -// } -// } -// for (MethodGroup group : methodGroups) -// //for (Object ogroup : methodGroups.values()) -// { -// System.out.println("Iterating group " + group); -// // MethodGroup group = (MethodGroup) ogroup; -// for (Method m : group.methods) -// { -// System.out.println("Iterating method " + m); -// for (int parameterIndex : group.constantParameters) -// { -// // constants used in this parameter index when calling this method -// List cmps = group.getConstantParametersFor(m, parameterIndex); -// -// // iterate instructions of method and find comparisons to parameter -// // remove if all are logically dead. rely on unused parameter deob to remove -// // the parameter. -// System.out.println(cmps.size() + " calls to " + m.getMethods().getClassFile().getName() + "." + m.getName() + " with index " + parameterIndex); -// } -// } -// } } - private void removeDeadOperations() + // remove logically dead comparisons + private int removeDeadOperations() { + int count = 0; for (Method method : deadops.keySet()) { List ops = deadops.get(method); @@ -515,7 +369,7 @@ public class ConstantParameter implements Deobfuscator { InstructionContext ctx = op.compCtx; // comparison Instruction ins = ctx.getInstruction(); - boolean branch = op.branch; + boolean branch = op.branch; // branch that is always taken Instructions instructions = ins.getInstructions(); @@ -528,6 +382,8 @@ public class ConstantParameter implements Deobfuscator if (idx == -1) continue; // already removed? + ++count; + Instruction to; if (branch) { @@ -560,6 +416,7 @@ public class ConstantParameter implements Deobfuscator } } } + return count; } @Override @@ -573,15 +430,9 @@ public class ConstantParameter implements Deobfuscator findParameters(execution); findLogicallyDeadOperations(execution); - removeDeadOperations(); + int count = removeDeadOperations(); - //System.out.println(deadops.size() + " deadops"); - -// System.out.println(parameters.size() + " params"); -// for (ConstantMethodParameter p : parameters) -// { -// //System.out.println -// } + System.out.println("Removed " + count + " logically dead conditional jumps"); } }