From 713db7777fdca7062d3cf705b97ad605c0b062c4 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 20 Jun 2015 17:56:46 -0400 Subject: [PATCH] remove stack of ifs in illegal state ex deob, get rid of using pcs in frame to execute, need to remove more of this later, make jumps jump to instructions, doesn't yet work --- src/main/java/info/sigterm/deob/Deob.java | 9 +++ .../deob/attributes/code/Instructions.java | 9 ++- .../attributes/code/instructions/AThrow.java | 2 +- .../code/instructions/CheckCast.java | 2 +- .../attributes/code/instructions/Goto.java | 2 +- .../attributes/code/instructions/GotoW.java | 2 +- .../deob/attributes/code/instructions/If.java | 4 +- .../attributes/code/instructions/If0.java | 2 +- .../code/instructions/InvokeInterface.java | 2 +- .../code/instructions/InvokeSpecial.java | 2 +- .../code/instructions/InvokeStatic.java | 2 +- .../code/instructions/InvokeVirtual.java | 2 +- .../code/instructions/LookupSwitch.java | 4 +- .../code/instructions/TableSwitch.java | 4 +- .../deobfuscators/IllegalStateExceptions.java | 65 +++++++++++++++++-- .../sigterm/deob/execution/Execution.java | 2 + .../info/sigterm/deob/execution/Frame.java | 46 ++++++------- 17 files changed, 116 insertions(+), 45 deletions(-) diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index 629dd26b34..95c8e75bbe 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -1,5 +1,6 @@ package info.sigterm.deob; +import info.sigterm.deob.deobfuscators.IllegalStateExceptions; import info.sigterm.deob.deobfuscators.Jumps; import info.sigterm.deob.deobfuscators.RuntimeExceptions; import info.sigterm.deob.deobfuscators.UnusedBlocks; @@ -35,11 +36,16 @@ public class Deob { public static void main(String[] args) throws IOException { + long start = System.currentTimeMillis(); + ClassGroup group = loadJar(args[0]); // remove except RuntimeException new RuntimeExceptions().run(group); + // remove illegal state exceptions, frees up some parameters + new IllegalStateExceptions().run(group); + // remove code blocks that used to be the runtime exception handlers new UnusedBlocks().run(group); @@ -53,6 +59,9 @@ public class Deob new Jumps().run(group); saveJar(group, args[1]); + + long end = System.currentTimeMillis(); + System.out.println("Done in " + ((end - start) / 1000L) + "s"); } private static ClassGroup loadJar(String jarfile) throws IOException diff --git a/src/main/java/info/sigterm/deob/attributes/code/Instructions.java b/src/main/java/info/sigterm/deob/attributes/code/Instructions.java index ddfe5836c5..ba7ad5f849 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/Instructions.java +++ b/src/main/java/info/sigterm/deob/attributes/code/Instructions.java @@ -99,12 +99,19 @@ public class Instructions public void buildBlocks() { clearBlockGraph(); + buildJumpGraph(); Block current = null; for (Instruction i : instructions) { - if (current == null) + if (current == null || !i.from.isEmpty()) { + // this caused exception errors? + if (current != null) + { + current.end = current.instructions.get(current.instructions.size() - 1); + blocks.add(current); + } current = new Block(); current.begin = i; findExceptionInfo(current, i); diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/AThrow.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/AThrow.java index 96fb451720..f88ecb7789 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/AThrow.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/AThrow.java @@ -50,7 +50,7 @@ public class AThrow extends Instruction if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) { Frame f = frame.dup(); - f.jumpAbsolute(e.getHandler().getPc()); + f.jump(e.getHandler()); } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/CheckCast.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/CheckCast.java index fed814ee04..452be308e0 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/CheckCast.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/CheckCast.java @@ -63,7 +63,7 @@ public class CheckCast extends Instruction f.addInstructionContext(ins); - f.jumpAbsolute(e.getHandler().getPc()); + f.jump(e.getHandler()); } } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/Goto.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/Goto.java index dd26304999..325b07dbb5 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/Goto.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/Goto.java @@ -56,7 +56,7 @@ public class Goto extends Instruction implements JumpingInstruction @Override public void execute(Frame e) { - e.jump(offset); + e.jump(to); } @Override diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/GotoW.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/GotoW.java index 25db691fa0..f01c31f3ee 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/GotoW.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/GotoW.java @@ -46,7 +46,7 @@ public class GotoW extends Instruction implements JumpingInstruction @Override public void execute(Frame e) { - e.jump(offset); + e.jump(to); } @Override 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 3fbc8e645b..03866d7422 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 @@ -57,8 +57,10 @@ public class If extends Instruction implements JumpingInstruction ins.pop(one, two); + frame.addInstructionContext(ins); + Frame other = frame.dup(); - other.jump(offset); + other.jump(to); } @Override 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 e4ae2add3e..a81342f5b1 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 @@ -59,7 +59,7 @@ public class If0 extends Instruction implements JumpingInstruction frame.addInstructionContext(ins); Frame other = frame.dup(); - other.jump(offset); + other.jump(to); } @Override diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeInterface.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeInterface.java index ea947bf0d4..cbec79016a 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeInterface.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeInterface.java @@ -110,7 +110,7 @@ public class InvokeInterface extends Instruction implements InvokeInstruction StackContext ctx = new StackContext(ins, new Type("java/lang/Exception")); stack.push(ctx); - f.jumpAbsolute(e.getHandler().getPc()); + f.jump(e.getHandler()); } } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeSpecial.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeSpecial.java index 06b6a20e53..640aaa2b21 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeSpecial.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeSpecial.java @@ -105,7 +105,7 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction StackContext ctx = new StackContext(ins, new Type("java/lang/Exception")); stack.push(ctx); - f.jumpAbsolute(e.getHandler().getPc()); + f.jump(e.getHandler()); } } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeStatic.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeStatic.java index c35c6faecf..f310a1742e 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeStatic.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeStatic.java @@ -102,7 +102,7 @@ public class InvokeStatic extends Instruction implements InvokeInstruction StackContext ctx = new StackContext(ins, new Type("java/lang/Exception")); stack.push(ctx); - f.jumpAbsolute(e.getHandler().getPc()); + f.jump(e.getHandler()); } } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeVirtual.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeVirtual.java index 65322f424d..1b904f74e5 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeVirtual.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/InvokeVirtual.java @@ -106,7 +106,7 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction StackContext ctx = new StackContext(ins, new Type("java/lang/Exception")); stack.push(ctx); - f.jumpAbsolute(e.getHandler().getPc()); + f.jump(e.getHandler()); } } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/LookupSwitch.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/LookupSwitch.java index b1accd1171..ad63129169 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/LookupSwitch.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/LookupSwitch.java @@ -107,13 +107,13 @@ public class LookupSwitch extends Instruction implements JumpingInstruction frame.addInstructionContext(ins); - for (int i : branch) + for (Instruction i : branchi) { Frame other = frame.dup(); other.jump(i); } - frame.jump(def); + frame.jump(defi); } @Override diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/TableSwitch.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/TableSwitch.java index 051e92d84e..890e131c48 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/TableSwitch.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/TableSwitch.java @@ -104,13 +104,13 @@ public class TableSwitch extends Instruction implements JumpingInstruction frame.addInstructionContext(ins); - for (int i : jumps) + for (Instruction i : branchi) { Frame other = frame.dup(); other.jump(i); } - frame.jump(def); + frame.jump(defi); } @Override diff --git a/src/main/java/info/sigterm/deob/deobfuscators/IllegalStateExceptions.java b/src/main/java/info/sigterm/deob/deobfuscators/IllegalStateExceptions.java index a0ed64f88c..bf3b74cb33 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/IllegalStateExceptions.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/IllegalStateExceptions.java @@ -11,16 +11,22 @@ import info.sigterm.deob.attributes.code.instructions.Goto; import info.sigterm.deob.attributes.code.instructions.If; import info.sigterm.deob.attributes.code.instructions.If0; import info.sigterm.deob.attributes.code.instructions.New; +import info.sigterm.deob.execution.Execution; +import info.sigterm.deob.execution.Frame; +import info.sigterm.deob.execution.InstructionContext; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class IllegalStateExceptions { /* find if, new, ..., athrow, replace with goto */ - public void run(ClassGroup group) + private int checkOnce(Execution execution, ClassGroup group) { int count = 0; + for (ClassFile cf : group.getClasses()) { for (Method m : new ArrayList<>(cf.getMethods().getMethods())) @@ -55,13 +61,43 @@ public class IllegalStateExceptions else if (ins instanceof If0) to = ((If0) ins).getTo(); + // remove stack of if. + boolean found = false; + for (Frame f : execution.processedFrames) + if (f.getMethod() == m) + for (InstructionContext ic : f.getInstructions()) + if (ic.getInstruction() == ins) // this is the if + { + found = true; + + if (ins instanceof If) + ic.removeStack(1); + ic.removeStack(0); + } + assert found; + + // instruction is no longer at 'i' because we've just removed stuff... + i = ilist.indexOf(ins); + // remove up to athrow - do + while (!(ins instanceof AThrow)) { + // modify instructions which jump to here to instead jump to 'to' + + for (Instruction from : ins.from) + { + from.jump.remove(ins); + //ins.from.remove(from); + + from.replace(ins, to); + + from.jump.add(to); + } + ins.from.clear(); + instructions.remove(ins); ins = ilist.get(i); // don't need to ++i because } - while (!(ins instanceof AThrow)); // remove athrow instructions.remove(ins); @@ -70,9 +106,30 @@ public class IllegalStateExceptions ilist.add(i, new Goto(instructions, to)); ++count; + break; } } } - System.out.println("Removed " + count + " illegal state exceptions"); + return count; + } + + public void run(ClassGroup group) + { + Execution execution = new Execution(group); + execution.run(); + + int count = 0; + int passes = 0; + int i; + do + { + i = checkOnce(execution, group); + + count += i; + ++passes; + } + while (i > 0); + + System.out.println("Removed " + count + " illegal state exceptions in " + passes + " passes"); } } diff --git a/src/main/java/info/sigterm/deob/execution/Execution.java b/src/main/java/info/sigterm/deob/execution/Execution.java index 54e4efaf90..6afbcf1de0 100644 --- a/src/main/java/info/sigterm/deob/execution/Execution.java +++ b/src/main/java/info/sigterm/deob/execution/Execution.java @@ -21,6 +21,8 @@ public class Execution public void run() { + // XXX update pc? some instructiosn rely on it still. + int count = 0, fcount = 0; for (ClassFile cf : group.getClasses()) for (Method method : cf.getMethods().getMethods()) diff --git a/src/main/java/info/sigterm/deob/execution/Frame.java b/src/main/java/info/sigterm/deob/execution/Frame.java index 2fb477b319..5b64c80eef 100644 --- a/src/main/java/info/sigterm/deob/execution/Frame.java +++ b/src/main/java/info/sigterm/deob/execution/Frame.java @@ -20,6 +20,7 @@ public class Frame private Method method; private boolean executing = true; private int pc; + private Instruction cur; // current instruction private Stack stack; private Variables variables; private List instructions = new ArrayList<>(); // instructions executed in this frame @@ -48,6 +49,8 @@ public class Frame variables.set(pos, new VariableContext(null, new Type(nat.getDescriptor().getTypeOfArg(i)).toStackType())); pos += nat.getDescriptor().getTypeOfArg(i).getSlots(); } + + cur = code.getInstructions().getInstructions().get(0); } protected Frame(Frame other) @@ -56,6 +59,7 @@ public class Frame this.method = other.method; this.executing = other.executing; this.pc = other.pc; + this.cur = other.cur; this.stack = new Stack(other.stack); this.variables = new Variables(other.variables); this.visited = other.visited; @@ -106,25 +110,19 @@ public class Frame public void execute() { Instructions ins = method.getCode().getInstructions(); + List instructions = ins.getInstructions(); + while (executing) { - int oldPc = pc; - - Instruction i = ins.findInstruction(pc); - - if (i == null) - { - System.err.println("Cant find ins at pc " + pc + " in method " + method.getName() + " in " + method.getCode().getAttributes().getClassFile().getName()); - System.exit(-1); - } + Instruction oldCur = cur; try { - i.execute(this); + cur.execute(this); } catch (Throwable ex) { - System.err.println("Error executing instruction " + i.getDesc(this)); + System.err.println("Error executing instruction " + cur.getDesc(this)); System.err.println("Frame stack (grows downward):"); while (stack.getSize() > 0) { @@ -136,9 +134,14 @@ public class Frame throw ex; } - if (oldPc == pc) + if (!executing) + break; + + if (oldCur == cur) { - pc += i.getLength(); + int idx = instructions.indexOf(cur); + assert idx != -1; + cur = instructions.get(idx + 1); } else { @@ -178,26 +181,17 @@ public class Frame return false; } - public void jump(int offset) + public void jump(Instruction to) { - jumpAbsolute(pc + offset); - } - - public void jumpAbsolute(int pc) - { - Instruction from = method.getCode().getInstructions().findInstruction(this.pc); - Instruction to = method.getCode().getInstructions().findInstruction(pc); - - assert from != null; assert to != null; - if (hasJumped(from, to)) + if (hasJumped(cur, to)) { executing = false; return; } - doJump(from, to); - this.pc = pc; + doJump(cur, to); + cur = to; } }