From 05439500134c4349982484454c63263ebcb79b20 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 25 Jun 2015 19:07:46 -0400 Subject: [PATCH] I think my invokevirtual execution is wrong because it doesn't actually look for virtual methods on the type, which is why my unused method deob does weird things. I am seeing methods that still exist after running it that appear to be using non-inversible constants. --- .../types/SetFieldInstruction.java | 8 ++++ .../code/instructions/PutField.java | 10 ++++- .../code/instructions/PutStatic.java | 9 ++++- .../ModularArithmeticDeobfuscation.java | 34 +++++++++++++--- .../deob/execution/InstructionContext.java | 8 ++++ .../info/sigterm/deob/execution/Stack.java | 6 +-- .../sigterm/deob/execution/StackContext.java | 39 ++++++++++++------- 7 files changed, 89 insertions(+), 25 deletions(-) create mode 100644 src/main/java/info/sigterm/deob/attributes/code/instruction/types/SetFieldInstruction.java diff --git a/src/main/java/info/sigterm/deob/attributes/code/instruction/types/SetFieldInstruction.java b/src/main/java/info/sigterm/deob/attributes/code/instruction/types/SetFieldInstruction.java new file mode 100644 index 0000000000..f2ed7742de --- /dev/null +++ b/src/main/java/info/sigterm/deob/attributes/code/instruction/types/SetFieldInstruction.java @@ -0,0 +1,8 @@ +package info.sigterm.deob.attributes.code.instruction.types; + +import info.sigterm.deob.pool.Field; + +public interface SetFieldInstruction +{ + public Field getField(); +} diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/PutField.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/PutField.java index 1be5b06eea..bd3934b99f 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/PutField.java @@ -3,16 +3,18 @@ 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 info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction; import info.sigterm.deob.execution.Frame; import info.sigterm.deob.execution.InstructionContext; import info.sigterm.deob.execution.Stack; import info.sigterm.deob.execution.StackContext; import info.sigterm.deob.pool.Field; + import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -public class PutField extends Instruction +public class PutField extends Instruction implements SetFieldInstruction { private Field field; @@ -45,4 +47,10 @@ public class PutField extends Instruction frame.addInstructionContext(ins); } + @Override + public Field getField() + { + return field; + } + } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/PutStatic.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/PutStatic.java index 1bf14b7a61..b93ba98bc6 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/PutStatic.java @@ -3,16 +3,18 @@ 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 info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction; import info.sigterm.deob.execution.Frame; import info.sigterm.deob.execution.InstructionContext; import info.sigterm.deob.execution.Stack; import info.sigterm.deob.execution.StackContext; import info.sigterm.deob.pool.Field; + import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -public class PutStatic extends Instruction +public class PutStatic extends Instruction implements SetFieldInstruction { private Field field; @@ -44,4 +46,9 @@ public class PutStatic extends Instruction frame.addInstructionContext(ins); } + @Override + public Field getField() + { + return field; + } } diff --git a/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java b/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java index af596c4e63..c7f857e709 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java @@ -12,7 +12,9 @@ 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.LVTInstruction; import info.sigterm.deob.attributes.code.instruction.types.PushConstantInstruction; +import info.sigterm.deob.attributes.code.instruction.types.SetFieldInstruction; import info.sigterm.deob.attributes.code.instructions.IMul; import info.sigterm.deob.execution.Execution; import info.sigterm.deob.execution.Frame; @@ -67,8 +69,8 @@ public class ModularArithmeticDeobfuscation continue; // check for push constant and for get field instruction - Instruction one = ctx.getPops().get(0).getIns().getInstruction(); - Instruction two = ctx.getPops().get(1).getIns().getInstruction(); + Instruction one = ctx.getPops().get(0).getPushed().getInstruction(); + Instruction two = ctx.getPops().get(1).getPushed().getInstruction(); PushConstantInstruction pc = null; GetFieldInstruction gf = null; @@ -86,14 +88,35 @@ public class ModularArithmeticDeobfuscation if (pc == null) continue; + 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 + + 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()); + } + + // XXX look only for setting to lvt. + if (!(popCtx.getInstruction() instanceof LVTInstruction)) + continue; + + LVTInstruction lvti = (LVTInstruction) popCtx.getInstruction(); + if (!lvti.store()) + continue; + try { - int constant = Integer.parseInt(pc.getConstant().toString()); modInverse(constant); } catch (ArithmeticException ex) { - continue; + System.err.println("Constant " + constant + " passed getter logic tests but is not inversable"); + continue; // if the constant isn't inversable then it can't be the right one } Integer old = constants.get(gf.getField()); @@ -103,10 +126,9 @@ public class ModularArithmeticDeobfuscation 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); - - // see what the result is used for? } } + System.out.println("Found " + constants.size() + " constants"); } private static BigInteger modInverse(BigInteger val, int bits) diff --git a/src/main/java/info/sigterm/deob/execution/InstructionContext.java b/src/main/java/info/sigterm/deob/execution/InstructionContext.java index 245951e462..093ba12703 100644 --- a/src/main/java/info/sigterm/deob/execution/InstructionContext.java +++ b/src/main/java/info/sigterm/deob/execution/InstructionContext.java @@ -22,7 +22,10 @@ public class InstructionContext public void pop(StackContext... ctx) { for (StackContext c : ctx) + { + c.setPopped(this); // now we know which instruction popped this, record it pops.add(c); + } } public void push(StackContext... ctx) @@ -47,6 +50,11 @@ public class InstructionContext return pops; } + public List getPushes() + { + return pushes; + } + public void removeStack(int idx) { // idx 0 is top of the stack, 1 is one under diff --git a/src/main/java/info/sigterm/deob/execution/Stack.java b/src/main/java/info/sigterm/deob/execution/Stack.java index bf4167d528..dbec46de6f 100644 --- a/src/main/java/info/sigterm/deob/execution/Stack.java +++ b/src/main/java/info/sigterm/deob/execution/Stack.java @@ -22,8 +22,8 @@ public class Stack { for (int i = 0; i < level; ++i) System.err.print(" "); - System.err.println(ctx.getType().type + " pushed by " + ctx.getIns().getInstruction().getType().getName() + " at " + ctx.getIns().getInstruction().getPc()); - for (StackContext c : ctx.getIns().getPops()) + System.err.println(ctx.getType().type + " pushed by " + ctx.getPushed().getInstruction().getType().getName() + " at " + ctx.getPushed().getInstruction().getPc()); + for (StackContext c : ctx.getPushed().getPops()) printStack(c, level + 2); } @@ -31,7 +31,7 @@ public class Stack { if (size == stack.length) { - info.sigterm.deob.Method m = i.getIns().getInstruction().getInstructions().getCode().getAttributes().getMethod(); + info.sigterm.deob.Method m = i.getPushed().getInstruction().getInstructions().getCode().getAttributes().getMethod(); System.err.println("in " + m.getMethods().getClassFile().getName() + " method " + m.getNameAndType().getName()); for (int c = 0; c < stack.length; ++c) printStack(stack[c], 0); diff --git a/src/main/java/info/sigterm/deob/execution/StackContext.java b/src/main/java/info/sigterm/deob/execution/StackContext.java index 62dbe18773..a35ebe6e78 100644 --- a/src/main/java/info/sigterm/deob/execution/StackContext.java +++ b/src/main/java/info/sigterm/deob/execution/StackContext.java @@ -2,32 +2,43 @@ package info.sigterm.deob.execution; public class StackContext { - private InstructionContext ic; // instruction which pushed this + private InstructionContext pushed; // instruction which pushed this + private InstructionContext popped; // instruction which popped this private Type type; // type of this - public StackContext(InstructionContext i, Type t) + public StackContext(InstructionContext pushed, Type type) { - ic = i; - type = t; + this.pushed = pushed; + this.type = type; } - public StackContext(InstructionContext i, Class c) + public StackContext(InstructionContext pushed, Class clazz) { - ic = i; - type = new Type(c.getCanonicalName()); + this.pushed = pushed; + type = new Type(clazz.getCanonicalName()); } - public StackContext(InstructionContext i, info.sigterm.deob.pool.Class c) + public StackContext(InstructionContext pushed, info.sigterm.deob.pool.Class c) { - ic = i; + this.pushed = pushed; type = new Type(c.getName()); } - public InstructionContext getIns() + public InstructionContext getPushed() { - return ic; + return pushed; } - + + public InstructionContext getPopped() + { + return popped; + } + + public void setPopped(InstructionContext popped) + { + this.popped = popped; + } + public Type getType() { return type; @@ -37,13 +48,13 @@ public class StackContext public void removeStack() { // remove the instruction which pushed this - if (!ic.getInstruction().removeStack()) + if (!pushed.getInstruction().removeStack()) // dup will return false as the other objects on the stack below this are necessary // for the other branch. return; // remove from the stack things this instruction read - for (StackContext ctx : ic.getPops()) + for (StackContext ctx : pushed.getPops()) ctx.removeStack(); } }