diff --git a/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java b/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java index 9e88cafde6..b28483c42d 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java @@ -170,83 +170,120 @@ public class ModularArithmeticDeobfuscation return fields; } + private static Set obfuscatedFields; + private static Map constants = new HashMap<>(); // getters + + private static void detectSetters(Execution execution, ClassGroup group, InstructionContext ctx) + { + if (!(ctx.getInstruction() instanceof SetFieldInstruction)) + return; + + SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction(); + + StackContext value = ctx.getPops().get(0); // what setfield pops as value + if (!(value.getPushed().getInstruction() instanceof IMul)) + return; + + Instruction one = value.getPushed().getPops().get(0).getPushed().getInstruction(); + Instruction two = value.getPushed().getPops().get(1).getPushed().getInstruction(); + + PushConstantInstruction pc = null; + Instruction other = null; + if (one instanceof PushConstantInstruction) + { + pc = (PushConstantInstruction) one; + other = two; + } + else if (two instanceof PushConstantInstruction) + { + pc = (PushConstantInstruction) two; + other = one; + } + + if (pc == null) + return; + + if (!checkFields(group, obfuscatedFields, sf.getField(), value.getPushed())) + return; + + System.out.println("Setter " + sf.getField().getClassEntry().getName() + "." + sf.getField().getNameAndType().getName() + " -> " + pc.getConstant().toString()); + } + + private static void detectGetters(Execution execution, ClassGroup group, InstructionContext ctx) + { + if (!(ctx.getInstruction() instanceof IMul)) + return; + + // check for push constant and for get field instruction + Instruction one = ctx.getPops().get(0).getPushed().getInstruction(); + Instruction two = ctx.getPops().get(1).getPushed().getInstruction(); + + PushConstantInstruction pc = null; + GetFieldInstruction gf = null; + if (one instanceof PushConstantInstruction && two instanceof GetFieldInstruction) + { + pc = (PushConstantInstruction) one; + gf = (GetFieldInstruction) two; + } + else if (two instanceof PushConstantInstruction && one instanceof GetFieldInstruction) + { + pc = (PushConstantInstruction) two; + gf = (GetFieldInstruction) one; + } + + if (pc == null) + return; + + int constant = Integer.parseInt(pc.getConstant().toString()); + + StackContext push = ctx.getPushes().get(0); // result of imul operation + InstructionContext popCtx = push.getPopped(); // instruction which popped the result of mul + + if (popCtx == null) + { + return; + //System.err.println("Stack ctx never popped! Pushed by " + push.getPushed().getInstruction()); + //int i = frame.getInstructions().indexOf(push.getPushed().getInstruction()); + //System.err.println("next ins is " + frame.getInstructions().get(i + 1).getInstruction()); + } + + if (!checkFields(group, obfuscatedFields, gf.getField(), ctx)) + return; + + try + { + modInverse(constant); + } + catch (ArithmeticException ex) + { + System.err.println("Constant " + constant + " passed getter logic tests but is not inversable"); + //printWhatCalls(execution, frame.getMethod(), 0); + return; // if the constant isn't inversable then it can't be the right one + } + + // get Field from pool Field + info.sigterm.deob.pool.Field field = gf.getField(); + Field f = group.findClass(field.getClassEntry().getName()).findField(field.getNameAndType()); + + Integer old = constants.get(f); + int newi = Integer.parseInt(pc.getConstant().toString()); + + if (old != null && (int) old != newi) + System.err.println("For " + gf.getField().getNameAndType().getName() + " in " + gf.getField().getClassEntry().getName() + " constant " + pc.getConstant().toString() + " mismatch on " + old); + + constants.put(f, newi); + } + private void run(Execution execution, ClassGroup group) { - Set obfuscatedFields = getObfuscatedFields(execution, group); + obfuscatedFields = getObfuscatedFields(execution, group); - Map constants = new HashMap<>(); for (Frame frame : execution.processedFrames) { for (InstructionContext ctx : frame.getInstructions()) { - // I think it is easier to detect the getters instead of the setters, - // and then calculate the setters. - if (!(ctx.getInstruction() instanceof IMul)) - continue; - - // check for push constant and for get field instruction - Instruction one = ctx.getPops().get(0).getPushed().getInstruction(); - Instruction two = ctx.getPops().get(1).getPushed().getInstruction(); - - PushConstantInstruction pc = null; - GetFieldInstruction gf = null; - if (one instanceof PushConstantInstruction && two instanceof GetFieldInstruction) - { - pc = (PushConstantInstruction) one; - gf = (GetFieldInstruction) two; - } - else if (two instanceof PushConstantInstruction && one instanceof GetFieldInstruction) - { - pc = (PushConstantInstruction) two; - gf = (GetFieldInstruction) one; - } - - if (pc == null) - continue; - - if (gf.getField().getClassEntry().getName().equals("ba") && gf.getField().getNameAndType().getName().equals("p")) - { - int i =5; - } - - int constant = Integer.parseInt(pc.getConstant().toString()); - - StackContext push = ctx.getPushes().get(0); // result of imul operation - InstructionContext popCtx = push.getPopped(); // instruction which popped the result of mul - - if (popCtx == null) - { - continue; - //System.err.println("Stack ctx never popped! Pushed by " + push.getPushed().getInstruction()); - //int i = frame.getInstructions().indexOf(push.getPushed().getInstruction()); - //System.err.println("next ins is " + frame.getInstructions().get(i + 1).getInstruction()); - } - - if (!checkFields(group, obfuscatedFields, gf.getField(), ctx)) - continue; - - try - { - modInverse(constant); - } - catch (ArithmeticException ex) - { - System.err.println("Constant " + constant + " passed getter logic tests but is not inversable"); - //printWhatCalls(execution, frame.getMethod(), 0); - continue; // if the constant isn't inversable then it can't be the right one - } - - // get Field from pool Field - info.sigterm.deob.pool.Field field = gf.getField(); - Field f = group.findClass(field.getClassEntry().getName()).findField(field.getNameAndType()); - - Integer old = constants.get(f); - int newi = Integer.parseInt(pc.getConstant().toString()); - - if (old != null && (int) old != newi) - System.out.println("For " + gf.getField().getNameAndType().getName() + " in " + gf.getField().getClassEntry().getName() + " constant " + pc.getConstant().toString() + " mismatch on " + old); - - constants.put(f, newi); + detectGetters(execution, group, ctx); + detectSetters(execution, group, ctx); } } System.out.println("Found " + constants.size() + " constants"); diff --git a/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java b/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java index afd54f6c49..3a8f7f3ebd 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java @@ -9,11 +9,14 @@ import info.sigterm.deob.Method; import info.sigterm.deob.attributes.Code; import info.sigterm.deob.attributes.code.Instruction; import info.sigterm.deob.attributes.code.instruction.types.FieldInstruction; +import info.sigterm.deob.attributes.code.instruction.types.GetFieldInstruction; +import info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction; public class UnusedFields { private static boolean isUnused(ClassGroup group, Field field) { + int get = 0, set = 0; for (ClassFile cf : group.getClasses()) for (Method m : cf.getMethods().getMethods()) { @@ -37,12 +40,25 @@ public class UnusedFields if (field == f) { - return false; + if (ins instanceof GetFieldInstruction) + ++get; + if (ins instanceof SetFieldInstruction) + ++set; } } } } - return true; + + if (get == 0 && set == 0) + return true; + + if (get == 0) + { + System.out.println("Field " + field.getFields().getClassFile().getName() + "." + field.getName() + " is set but not get"); + return false; + } + + return false; } public void run(ClassGroup group) diff --git a/src/main/java/info/sigterm/deob/deobfuscators/UnusedMethods.java b/src/main/java/info/sigterm/deob/deobfuscators/UnusedMethods.java index 53c9d7470f..c932b71b57 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/UnusedMethods.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/UnusedMethods.java @@ -27,7 +27,6 @@ public class UnusedMethods continue; if (!execution.methods.contains(m)) - //if (!m.isUsed()) { cf.getMethods().removeMethod(m); ++i;