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; } }