From e5a8ff8268d5b441c6876e4fe7c4a6ce46b61681 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 2 Jul 2015 13:48:26 -0400 Subject: [PATCH] cleanup, detect func(field * constant). Sometimes non storing lvt instructions don't give us the correct getter value eg if (lvt > field * constant) -> actually if (lvt > field * x) --- src/main/java/info/sigterm/deob/Deob.java | 2 +- .../ModularArithmeticDeobfuscation.java | 88 ++++++++++++++++--- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index c5fd262efb..7d5187dd10 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -59,7 +59,7 @@ public class Deob // remove jump obfuscation new Jumps().run(group); - //new ModularArithmeticDeobfuscation().run(group); + new ModularArithmeticDeobfuscation().run(group); saveJar(group, args[1]); diff --git a/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java b/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java index f6428187a4..37dc6091db 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java @@ -8,11 +8,13 @@ import java.util.Map.Entry; import info.sigterm.deob.ClassFile; import info.sigterm.deob.ClassGroup; +import info.sigterm.deob.Field; import info.sigterm.deob.Method; 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.instruction.types.GetFieldInstruction; +import info.sigterm.deob.attributes.code.instruction.types.InvokeInstruction; import info.sigterm.deob.attributes.code.instruction.types.LVTInstruction; import info.sigterm.deob.attributes.code.instruction.types.PushConstantInstruction; import info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction; @@ -21,10 +23,59 @@ import info.sigterm.deob.execution.Execution; import info.sigterm.deob.execution.Frame; import info.sigterm.deob.execution.InstructionContext; import info.sigterm.deob.execution.StackContext; -import info.sigterm.deob.pool.Field; public class ModularArithmeticDeobfuscation { + private static String getMethodDesc(Method m) + { + return m.getMethods().getClassFile().getName() + "." + m.getName() + m.getNameAndType().getDescriptor().toString(); + } + + private static void printWhatCalls(Execution execution, Method method, int level) + { + for (Frame frame : execution.processedFrames) + { + for (InstructionContext ctx : frame.getInstructions()) + { + if (ctx.getInvokes().contains(method)) + { + for (int i = 0; i < level; ++i) + System.out.print(" "); + System.out.println(getMethodDesc(method) + " called by " + getMethodDesc(frame.getMethod()) + ", " + ctx.getInvokes().size() + " methods total"); + printWhatCalls(execution, frame.getMethod(), level + 1); + } + } + } + } + + // check for popping instruction to be a LVT get + private static boolean checkLVTGet(InstructionContext popCtx) + { + if (!(popCtx.getInstruction() instanceof LVTInstruction)) + return false; + + LVTInstruction lvti = (LVTInstruction) popCtx.getInstruction(); + if (!lvti.store()) + return false; + + return true; + } + + // func(field * constant) + private static boolean checkInvoke(InstructionContext popCtx) + { + if (!(popCtx.getInstruction() instanceof InvokeInstruction)) + return false; + + return true; + } + + private static boolean checkRules(InstructionContext popCtx) + { + return checkLVTGet(popCtx) + || checkInvoke(popCtx); + } + /* try to identify: * lvt = field * constant @@ -102,14 +153,9 @@ public class ModularArithmeticDeobfuscation //System.err.println("next ins is " + frame.getInstructions().get(i + 1).getInstruction()); } - // XXX look only for setting to lvt. - if (!(popCtx.getInstruction() instanceof LVTInstruction)) + if (!checkRules(popCtx)) continue; - - LVTInstruction lvti = (LVTInstruction) popCtx.getInstruction(); - if (!lvti.store()) - continue; - + try { modInverse(constant); @@ -117,16 +163,21 @@ public class ModularArithmeticDeobfuscation 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 } - Integer old = constants.get(gf.getField()); + // 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(gf.getField(), newi); + constants.put(f, newi); } } System.out.println("Found " + constants.size() + " constants"); @@ -134,8 +185,23 @@ public class ModularArithmeticDeobfuscation { Field f = entry.getKey(); Integer v = entry.getValue(); - System.out.println(f.getClassEntry().getName() + "." + f.getNameAndType().getName() + " -> " + v); + System.out.println(f.getFields().getClassFile().getName() + "." + f.getName() + " -> " + v); } + System.out.println("Did not find for:"); + int count = 0; + for (ClassFile cf : group.getClasses()) + for (Field f : cf.getFields().getFields()) + { + if (f.getType().toString().equals("I")) + { + if (!constants.containsKey(f)) + { + System.out.println(f.getFields().getClassFile().getName() + "." + f.getName()); + ++count; + } + } + } + System.out.println("Did not find for " + count); } private static BigInteger modInverse(BigInteger val, int bits)