From 95368f61a877b215983b6ad2f3b8a859566d5321 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 6 Aug 2015 18:59:23 -0400 Subject: [PATCH] Fix constant parameter corrupting instructions. Make unused blocks faster. --- src/main/java/info/sigterm/deob/Deob.java | 24 ++++---- .../deob/deobfuscators/ConstantParameter.java | 12 +++- .../deob/deobfuscators/UnusedBlocks.java | 55 +++++++++++-------- .../info/sigterm/deob/execution/Frame.java | 2 + 4 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index 33ce50dc77..8380a9bb85 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -30,10 +30,10 @@ public class Deob ClassGroup group = loadJar(args[0]); long bstart, bdur; - bstart = System.currentTimeMillis(); - new RenameUnique().run(group); - bdur = System.currentTimeMillis() - bstart; - System.out.println("rename unique took " + bdur/1000L + " seconds"); +// bstart = System.currentTimeMillis(); +// new RenameUnique().run(group); +// bdur = System.currentTimeMillis() - bstart; +// System.out.println("rename unique took " + bdur/1000L + " seconds"); // remove except RuntimeException bstart = System.currentTimeMillis(); @@ -63,10 +63,10 @@ public class Deob System.out.println("constant param took " + bdur/1000L + " seconds"); // remove unhit blocks - bstart = System.currentTimeMillis(); - new UnusedBlocks().run(group); - bdur = System.currentTimeMillis() - bstart; - System.out.println("unused blocks took " + bdur/1000L + " seconds"); +// bstart = System.currentTimeMillis(); +// new UnusedBlocks().run(group); +// bdur = System.currentTimeMillis() - bstart; +// System.out.println("unused blocks took " + bdur/1000L + " seconds"); // remove unused parameters bstart = System.currentTimeMillis(); @@ -78,10 +78,10 @@ public class Deob //new Jumps().run(group); // remove unused fields - bstart = System.currentTimeMillis(); - new UnusedFields().run(group); - bdur = System.currentTimeMillis() - bstart; - System.out.println("unused fields took " + bdur/1000L + " seconds"); +// bstart = System.currentTimeMillis(); +// new UnusedFields().run(group); +// bdur = System.currentTimeMillis() - bstart; +// System.out.println("unused fields took " + bdur/1000L + " seconds"); //new ModularArithmeticDeobfuscation().run(group); diff --git a/src/main/java/info/sigterm/deob/deobfuscators/ConstantParameter.java b/src/main/java/info/sigterm/deob/deobfuscators/ConstantParameter.java index db2e85af89..fdb6818b20 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/ConstantParameter.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/ConstantParameter.java @@ -424,6 +424,7 @@ public class ConstantParameter implements Deobfuscator boolean branch = op.branch; // branch that is always taken Instructions instructions = ins.getInstructions(); + instructions.buildJumpGraph(); // remove the if if (ctx.getInstruction() instanceof If) @@ -450,6 +451,7 @@ public class ConstantParameter implements Deobfuscator } assert to.getInstructions() == instructions; assert ins != to; + assert instructions.getInstructions().contains(to); // move things that jump here to instead jump to 'to' for (Instruction fromI : ins.from) @@ -463,10 +465,16 @@ public class ConstantParameter implements Deobfuscator instructions.remove(ins); + assert instructions.getInstructions().contains(to); + if (branch) - { + { + Goto gotoins = new Goto(instructions, to); + to.from.add(gotoins); + gotoins.jump.add(to); + // insert goto - instructions.getInstructions().add(idx, new Goto(instructions, to)); + instructions.getInstructions().add(idx, gotoins); } } } diff --git a/src/main/java/info/sigterm/deob/deobfuscators/UnusedBlocks.java b/src/main/java/info/sigterm/deob/deobfuscators/UnusedBlocks.java index 6fec8dfce1..9357f5e068 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/UnusedBlocks.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/UnusedBlocks.java @@ -8,40 +8,43 @@ import info.sigterm.deob.attributes.code.Instructions; import info.sigterm.deob.block.Block; import java.util.ArrayList; +import java.util.List; public class UnusedBlocks implements Deobfuscator { + private List methods = new ArrayList<>(); + public int pass(ClassGroup group) { int removed = 0; - for (ClassFile cf : group.getClasses()) + methods: + for (Method m : new ArrayList<>(methods)) { - for (Method m : new ArrayList<>(cf.getMethods().getMethods())) + if (m.getCode() == null) + continue; + + Instructions ins = m.getCode().getInstructions(); + ins.buildBlocks(); + + for (int i = 0; i < ins.getBlocks().size(); ++i) { - if (m.getCode() == null) + Block block = ins.getBlocks().get(i); + + // first block is the entrypoint, so its always used + if (i == 0) continue; - - Instructions ins = m.getCode().getInstructions(); - ins.buildBlocks(); - - for (int i = 0; i < ins.getBlocks().size(); ++i) + + Block prev = ins.getBlocks().get(i - 1); + + if (prev.end.isTerminal() && block.begin.from.isEmpty() && block.handlers.isEmpty()) { - Block block = ins.getBlocks().get(i); - - // first block is the entrypoint, so its always used - if (i == 0) - continue; - - Block prev = ins.getBlocks().get(i - 1); - - if (prev.end.isTerminal() && block.begin.from.isEmpty() && block.handlers.isEmpty()) - { - ins.remove(block); - ++removed; - break; - } + ins.remove(block); + ++removed; + continue methods; } } + + methods.remove(m); } System.out.println("Removed " + removed + " unused blocks"); @@ -51,6 +54,14 @@ public class UnusedBlocks implements Deobfuscator @Override public void run(ClassGroup group) { + for (ClassFile cf : group.getClasses()) + { + for (Method m : cf.getMethods().getMethods()) + { + methods.add(m); + } + } + while (pass(group) > 0); } } diff --git a/src/main/java/info/sigterm/deob/execution/Frame.java b/src/main/java/info/sigterm/deob/execution/Frame.java index faeff4d7fc..5eedf6ad29 100644 --- a/src/main/java/info/sigterm/deob/execution/Frame.java +++ b/src/main/java/info/sigterm/deob/execution/Frame.java @@ -189,6 +189,8 @@ public class Frame public void jump(Instruction to) { assert to != null; + assert to.getInstructions() == method.getCode().getInstructions(); + assert method.getCode().getInstructions().getInstructions().contains(to); if (hasJumped(cur, to)) {