From 7b0776d1ec0e4cd97b47c37847c630fd76b166d7 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 2 Jul 2015 17:07:57 -0400 Subject: [PATCH] more arith deob --- src/main/java/info/sigterm/deob/Deob.java | 3 + .../types/ComparisonInstruction.java | 6 ++ .../instruction/types/FieldInstruction.java | 8 +++ .../types/GetFieldInstruction.java | 5 +- .../types/SetFieldInstruction.java | 5 +- .../deob/attributes/code/instructions/If.java | 3 +- .../attributes/code/instructions/If0.java | 3 +- .../ModularArithmeticDeobfuscation.java | 27 ++++++++- .../deob/deobfuscators/UnusedFields.java | 59 +++++++++++++++++++ 9 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 src/main/java/info/sigterm/deob/attributes/code/instruction/types/ComparisonInstruction.java create mode 100644 src/main/java/info/sigterm/deob/attributes/code/instruction/types/FieldInstruction.java create mode 100644 src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index 7d5187dd10..6882258ee5 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -5,6 +5,7 @@ import info.sigterm.deob.deobfuscators.Jumps; import info.sigterm.deob.deobfuscators.ModularArithmeticDeobfuscation; 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; @@ -59,6 +60,8 @@ public class Deob // remove jump obfuscation new Jumps().run(group); + new UnusedFields().run(group); + new ModularArithmeticDeobfuscation().run(group); saveJar(group, args[1]); diff --git a/src/main/java/info/sigterm/deob/attributes/code/instruction/types/ComparisonInstruction.java b/src/main/java/info/sigterm/deob/attributes/code/instruction/types/ComparisonInstruction.java new file mode 100644 index 0000000000..9c2c2fa128 --- /dev/null +++ b/src/main/java/info/sigterm/deob/attributes/code/instruction/types/ComparisonInstruction.java @@ -0,0 +1,6 @@ +package info.sigterm.deob.attributes.code.instruction.types; + +public interface ComparisonInstruction +{ + +} diff --git a/src/main/java/info/sigterm/deob/attributes/code/instruction/types/FieldInstruction.java b/src/main/java/info/sigterm/deob/attributes/code/instruction/types/FieldInstruction.java new file mode 100644 index 0000000000..f3ed7bfa3f --- /dev/null +++ b/src/main/java/info/sigterm/deob/attributes/code/instruction/types/FieldInstruction.java @@ -0,0 +1,8 @@ +package info.sigterm.deob.attributes.code.instruction.types; + +import info.sigterm.deob.pool.Field; + +public interface FieldInstruction +{ + public Field getField(); +} diff --git a/src/main/java/info/sigterm/deob/attributes/code/instruction/types/GetFieldInstruction.java b/src/main/java/info/sigterm/deob/attributes/code/instruction/types/GetFieldInstruction.java index e0bdf7da21..d1a02b8723 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instruction/types/GetFieldInstruction.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instruction/types/GetFieldInstruction.java @@ -1,8 +1,5 @@ package info.sigterm.deob.attributes.code.instruction.types; -import info.sigterm.deob.pool.Field; - -public interface GetFieldInstruction +public interface GetFieldInstruction extends FieldInstruction { - public Field getField(); } 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 index f2ed7742de..2b3f264ba7 100644 --- 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 @@ -1,8 +1,5 @@ package info.sigterm.deob.attributes.code.instruction.types; -import info.sigterm.deob.pool.Field; - -public interface SetFieldInstruction +public interface SetFieldInstruction extends FieldInstruction { - public Field getField(); } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/If.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/If.java index 03866d7422..b689fb309f 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/If.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/If.java @@ -3,6 +3,7 @@ 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.ComparisonInstruction; import info.sigterm.deob.attributes.code.instruction.types.JumpingInstruction; import info.sigterm.deob.execution.Frame; import info.sigterm.deob.execution.InstructionContext; @@ -13,7 +14,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -public class If extends Instruction implements JumpingInstruction +public class If extends Instruction implements JumpingInstruction, ComparisonInstruction { private Instruction to; private short offset; diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/If0.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/If0.java index a81342f5b1..5a10f75ee9 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/If0.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/If0.java @@ -3,6 +3,7 @@ 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.ComparisonInstruction; import info.sigterm.deob.attributes.code.instruction.types.JumpingInstruction; import info.sigterm.deob.execution.Frame; import info.sigterm.deob.execution.InstructionContext; @@ -13,7 +14,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -public class If0 extends Instruction implements JumpingInstruction +public class If0 extends Instruction implements JumpingInstruction, ComparisonInstruction { private Instruction to; private short offset; diff --git a/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java b/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java index 37dc6091db..cde3115718 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/ModularArithmeticDeobfuscation.java @@ -13,6 +13,7 @@ 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.ComparisonInstruction; 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; @@ -48,7 +49,7 @@ public class ModularArithmeticDeobfuscation } } - // check for popping instruction to be a LVT get + // lvt = field * constant private static boolean checkLVTGet(InstructionContext popCtx) { if (!(popCtx.getInstruction() instanceof LVTInstruction)) @@ -70,10 +71,32 @@ public class ModularArithmeticDeobfuscation return true; } + // lvt comparison field * constant + private static boolean checkCompare(InstructionContext popCtx) + { + if (!(popCtx.getInstruction() instanceof ComparisonInstruction)) + return false; + + // make sure comparison is against lvt + List pops = popCtx.getPops(); // things popCtx popped + for (StackContext ctx : pops) // one of these is the imul + { + InstructionContext pushCtx = ctx.getPushed(); // instruction which pushed this here + if (pushCtx.getInstruction() instanceof LVTInstruction) + { + LVTInstruction lvt = (LVTInstruction) pushCtx.getInstruction(); + return !lvt.store(); // check its a get + } + } + + return false; + } + private static boolean checkRules(InstructionContext popCtx) { return checkLVTGet(popCtx) - || checkInvoke(popCtx); + || checkInvoke(popCtx) + || checkCompare(popCtx); } /* try to identify: diff --git a/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java b/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java new file mode 100644 index 0000000000..bfb411d603 --- /dev/null +++ b/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java @@ -0,0 +1,59 @@ +package info.sigterm.deob.deobfuscators; + +import java.util.ArrayList; + +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.instruction.types.FieldInstruction; + +public class UnusedFields +{ + private static boolean isUnused(ClassGroup group, Field field) + { + for (ClassFile cf : group.getClasses()) + for (Method m : cf.getMethods().getMethods()) + { + Code code = m.getCode(); + if (code == null) + continue; + + for (Instruction ins : code.getInstructions().getInstructions()) + { + if (ins instanceof FieldInstruction) + { + FieldInstruction fi = (FieldInstruction) ins; + + info.sigterm.deob.pool.Field ff = fi.getField(); + + if (ff.getClassEntry().getName().equals(field.getFields().getClassFile().getName())) + { + if (ff.getNameAndType().getName().equals(field.getName())) + { + return false; + } + } + } + } + } + return true; + } + + public void run(ClassGroup group) + { + int count = 0; + for (ClassFile cf : group.getClasses()) + for (Field f : new ArrayList<>(cf.getFields().getFields())) + { + if (isUnused(group, f)) + { + cf.getFields().getFields().remove(f); + ++count; + } + } + System.out.println("Removed " + count + " unused fields"); + } +}