From ec5030396261b1b716c70cda2f8a47efcdb6f3d2 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 12 Jul 2015 00:15:45 -0400 Subject: [PATCH] Fix up jump inlining, this causes linear scans of the instructions for a lot of exceptions and is slow. Need to allow inlining in try blocks? --- src/main/java/info/sigterm/deob/Deob.java | 17 ++++--- .../deob/attributes/code/Instructions.java | 50 ++++++++++++++----- .../attributes/code/instructions/AThrow.java | 11 ++-- .../code/instructions/CheckCast.java | 11 ++-- .../code/instructions/InvokeInterface.java | 11 ++-- .../code/instructions/InvokeSpecial.java | 11 ++-- .../code/instructions/InvokeStatic.java | 11 ++-- .../code/instructions/InvokeVirtual.java | 12 +++-- .../sigterm/deob/deobfuscators/Jumps.java | 23 +++++---- .../deob/deobfuscators/UnusedFields.java | 6 --- 10 files changed, 109 insertions(+), 54 deletions(-) diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index f265e49dbb..5ad4347f3c 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -45,28 +45,31 @@ public class Deob // remove except RuntimeException new RuntimeExceptions().run(group); + // the blocks of runtime exceptions may contain interesting things like other obfuscations we identify later, but now that + // it can't be reached by the execution phase, those things become confused. so remove blocks here. + //new UnusedBlocks().run(group); // remove unused methods - new UnusedMethods().run(group); + //new UnusedMethods().run(group); // remove illegal state exceptions, frees up some parameters - new IllegalStateExceptions().run(group); + //new IllegalStateExceptions().run(group); - // remove code blocks that used to be the runtime exception handlers - new UnusedBlocks().run(group); + // remove unhit blocks + //new UnusedBlocks().run(group); // remove unused parameters - new UnusedParameters().run(group); + //new UnusedParameters().run(group); // remove jump obfuscation new Jumps().run(group); // remove unused fields - new UnusedFields().run(group); + //new UnusedFields().run(group); //new ModularArithmeticDeobfuscation().run(group); - new RenameUnique().run(group); + //new RenameUnique().run(group); saveJar(group, args[1]); 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 d820bd67c3..27433159b3 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/Instructions.java +++ b/src/main/java/info/sigterm/deob/attributes/code/Instructions.java @@ -87,9 +87,20 @@ public class Instructions { for (Exception e : code.getExceptions().getExceptions()) { - if (i.getPc() >= e.getStart().getPc() && i.getPc() < e.getEnd().getPc()) + int startIdx = instructions.indexOf(e.getStart()), + endIdx = instructions.indexOf(e.getEnd()), + thisIdx = instructions.indexOf(i); + + assert startIdx != -1; + assert endIdx != -1; + assert thisIdx != -1; + + assert endIdx > startIdx; + + if (thisIdx >= startIdx && thisIdx < endIdx) { - block.exceptions.add(e); + if (!block.exceptions.contains(e)) + block.exceptions.add(e); } if (e.getHandler() == i) { @@ -98,28 +109,43 @@ public class Instructions } } + private boolean isException(Instruction i) + { + for (Exception e : code.getExceptions().getExceptions()) + if (e.getHandler() == i || e.getStart() == i) + return true; + return false; + } + + private boolean isExceptionEnd(Instruction i) + { + for (Exception e : code.getExceptions().getExceptions()) + if (e.getEnd() == i) + return true; + return false; + } + public void buildBlocks() { clearBlockGraph(); buildJumpGraph(); Block current = null; - for (Instruction i : instructions) + for (int j = 0; j < instructions.size(); ++j) { - if (current == null || !i.from.isEmpty()) + Instruction i = instructions.get(j), + next = j + 1 < instructions.size() ? instructions.get(j + 1) : null; + + if (current == null) { - if (current != null) - { - current.end = current.instructions.get(current.instructions.size() - 1); - blocks.add(current); - } current = new Block(); current.begin = i; - findExceptionInfo(current, i); } - i.block = current; + current.instructions.add(i); - if (i.isTerminal()) + findExceptionInfo(current, i); + + if (i.isTerminal() || next == null || isException(next) || isExceptionEnd(i) || !next.from.isEmpty()) { current.end = i; blocks.add(current); 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 f88ecb7789..5f861cfbf8 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 @@ -43,11 +43,16 @@ public class AThrow extends Instruction // jump to instruction handlers that can catch exceptions here for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) { - Instruction start = e.getStart(), - end = e.getEnd(); + int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()), + endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()), + thisIdx = this.getInstructions().getInstructions().indexOf(this); + + assert startIdx != -1; + assert endIdx != -1; + assert thisIdx != -1; // [start, end) - if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) + if (thisIdx >= startIdx && thisIdx < endIdx) { Frame f = frame.dup(); 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 e0361bcf99..0f9b279949 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 @@ -41,11 +41,16 @@ public class CheckCast extends Instruction // jump to instruction handlers that can catch exceptions here for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) { - Instruction start = e.getStart(), - end = e.getEnd(); + int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()), + endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()), + thisIdx = this.getInstructions().getInstructions().indexOf(this); + + assert startIdx != -1; + assert endIdx != -1; + assert thisIdx != -1; // [start, end) - if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) + if (thisIdx >= startIdx && thisIdx < endIdx) { Frame f = frame.dup(); Stack stack = f.getStack(); 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 233956e97a..f2c781c705 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 @@ -114,11 +114,16 @@ public class InvokeInterface extends Instruction implements InvokeInstruction // jump to instruction handlers that can catch exceptions here for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) { - Instruction start = e.getStart(), - end = e.getEnd(); + int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()), + endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()), + thisIdx = this.getInstructions().getInstructions().indexOf(this); + + assert startIdx != -1; + assert endIdx != -1; + assert thisIdx != -1; // [start, end) - if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) + if (thisIdx >= startIdx && thisIdx < endIdx) { Frame f = frame.dup(); Stack stack = f.getStack(); 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 28d8240f88..2d6963b4d7 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 @@ -101,11 +101,16 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction // jump to instruction handlers that can catch exceptions here for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) { - Instruction start = e.getStart(), - end = e.getEnd(); + int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()), + endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()), + thisIdx = this.getInstructions().getInstructions().indexOf(this); + + assert startIdx != -1; + assert endIdx != -1; + assert thisIdx != -1; // [start, end) - if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) + if (thisIdx >= startIdx && thisIdx < endIdx) { Frame f = frame.dup(); Stack stack = f.getStack(); 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 6115bd8439..e2f8bf402e 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 @@ -98,11 +98,16 @@ public class InvokeStatic extends Instruction implements InvokeInstruction // jump to instruction handlers that can catch exceptions here for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) { - Instruction start = e.getStart(), - end = e.getEnd(); + int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()), + endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()), + thisIdx = this.getInstructions().getInstructions().indexOf(this); + + assert startIdx != -1; + assert endIdx != -1; + assert thisIdx != -1; // [start, end) - if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) + if (thisIdx >= startIdx && thisIdx < endIdx) { Frame f = frame.dup(); Stack stack = f.getStack(); 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 03e7d11eaa..b84ad85bfe 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 @@ -112,12 +112,16 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction // jump to instruction handlers that can catch exceptions here for (info.sigterm.deob.attributes.code.Exception e : this.getInstructions().getCode().getExceptions().getExceptions()) { - Instruction start = e.getStart(), - end = e.getEnd(); + int startIdx = this.getInstructions().getInstructions().indexOf(e.getStart()), + endIdx = this.getInstructions().getInstructions().indexOf(e.getEnd()), + thisIdx = this.getInstructions().getInstructions().indexOf(this); + + assert startIdx != -1; + assert endIdx != -1; + assert thisIdx != -1; - // XXX this relies on pc? // [start, end) - if (this.getPc() >= start.getPc() && this.getPc() < end.getPc()) + if (thisIdx >= startIdx && thisIdx < endIdx) { Frame f = frame.dup(); Stack stack = f.getStack(); diff --git a/src/main/java/info/sigterm/deob/deobfuscators/Jumps.java b/src/main/java/info/sigterm/deob/deobfuscators/Jumps.java index a475f0fdcc..d2b25021c0 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/Jumps.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/Jumps.java @@ -56,10 +56,6 @@ public class Jumps implements Deobfuscator //ins.clearBlocks(); ins.clearJumpGraph(); - // 'from' goes away and is replaced with block.begin - for (Instruction in : ilist) - in.replace(from, block.begin); - // remove instructions for (Instruction in : block.instructions) { @@ -67,13 +63,19 @@ public class Jumps implements Deobfuscator assert b; } - // store pos of from - int index = ilist.indexOf(from); - ilist.remove(from); + int idx = ilist.indexOf(from); + boolean b = ilist.remove(from); + assert b; - // insert instructions where 'from' was - for (Instruction in : block.instructions) - ilist.add(index++, in); + b = ilist.addAll(idx, block.instructions); + assert b; + + // replace from with block.begin + for (Instruction ins2 : ilist) + ins2.replace(from, block.begin); + + for (info.sigterm.deob.attributes.code.Exception e : m.getCode().getExceptions().getExceptions()) + e.replace(from, block.begin); continue methods; } @@ -93,6 +95,7 @@ public class Jumps implements Deobfuscator do { i = checkBlockGraphOnce(g); + System.out.println("pass " + i); count += i; ++passes; } diff --git a/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java b/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java index 11a0c33571..6f84c316b1 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/UnusedFields.java @@ -53,12 +53,6 @@ public class UnusedFields implements Deobfuscator if (get == 0 && set == 0) return true; - if (get == 0) - { - System.out.println("Field " + field.getFields().getClassFile().getName() + "." + field.getName() + " is set but not get"); - return false; - } - return false; }