From fc3c0a258f0b9f93bb4fc5dd18e27e44913917da Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 15 Aug 2015 12:49:00 -0400 Subject: [PATCH] Finish methodmover --- src/main/java/info/sigterm/deob/Deob.java | 18 ++++-- src/main/java/info/sigterm/deob/Method.java | 7 +++ .../deob/attributes/code/Instruction.java | 2 +- .../deob/attributes/code/Instructions.java | 4 +- .../code/instructions/InvokeInterface.java | 5 +- .../code/instructions/InvokeSpecial.java | 4 +- .../code/instructions/InvokeStatic.java | 4 +- .../code/instructions/InvokeVirtual.java | 4 +- .../deob/deobfuscators/MethodMover.java | 59 +++++++++++++++++-- .../deob/deobfuscators/RenameUnique.java | 8 ++- 10 files changed, 93 insertions(+), 22 deletions(-) diff --git a/src/main/java/info/sigterm/deob/Deob.java b/src/main/java/info/sigterm/deob/Deob.java index 69d06e4320..774c6f4d6e 100644 --- a/src/main/java/info/sigterm/deob/Deob.java +++ b/src/main/java/info/sigterm/deob/Deob.java @@ -3,6 +3,9 @@ package info.sigterm.deob; import info.sigterm.deob.deobfuscators.ConstantParameter; import info.sigterm.deob.deobfuscators.IllegalStateExceptions; import info.sigterm.deob.deobfuscators.MethodInliner; +import info.sigterm.deob.deobfuscators.MethodMover; +import info.sigterm.deob.deobfuscators.ModularArithmeticDeobfuscation; +import info.sigterm.deob.deobfuscators.RenameUnique; import info.sigterm.deob.deobfuscators.RuntimeExceptions; import info.sigterm.deob.deobfuscators.UnreachedCode; import info.sigterm.deob.deobfuscators.UnusedFields; @@ -21,6 +24,13 @@ import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; +//move static methods +//move static fields +//math deob +//remove dead classes +//inline constant fields +//compare old and new + public class Deob { public static void main(String[] args) throws IOException @@ -38,9 +48,6 @@ public class Deob // remove except RuntimeException bstart = System.currentTimeMillis(); 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); bdur = System.currentTimeMillis() - bstart; System.out.println("runtime exception took " + bdur/1000L + " seconds"); @@ -92,9 +99,12 @@ public class Deob bdur = System.currentTimeMillis() - bstart; System.out.println("unused methods took " + bdur/1000L + " seconds"); - //new ModularArithmeticDeobfuscation().run(group); new MethodInliner().run(group); + +// new ModularArithmeticDeobfuscation().run(group); + + new MethodMover().run(group); saveJar(group, args[1]); diff --git a/src/main/java/info/sigterm/deob/Method.java b/src/main/java/info/sigterm/deob/Method.java index 9ec3c93b53..25ed1f469b 100644 --- a/src/main/java/info/sigterm/deob/Method.java +++ b/src/main/java/info/sigterm/deob/Method.java @@ -42,6 +42,8 @@ public class Method public void write(DataOutputStream out) throws IOException { + assert methods.getMethods().contains(this); + ConstantPool pool = methods.getClassFile().getPool(); out.writeShort(accessFlags); @@ -55,6 +57,11 @@ public class Method return methods; } + public void setMethods(Methods methods) + { + this.methods = methods; + } + public String getName() { return name; diff --git a/src/main/java/info/sigterm/deob/attributes/code/Instruction.java b/src/main/java/info/sigterm/deob/attributes/code/Instruction.java index 15ebcdd8d6..b503c4cd07 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/Instruction.java +++ b/src/main/java/info/sigterm/deob/attributes/code/Instruction.java @@ -226,7 +226,7 @@ public abstract class Instruction { } - public void renameMethod(Method m, String name) + public void renameMethod(Method oldMethod, info.sigterm.deob.pool.Method newMethod) { } } 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 7a91a79bec..1eb0d27216 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/Instructions.java +++ b/src/main/java/info/sigterm/deob/attributes/code/Instructions.java @@ -238,9 +238,9 @@ public class Instructions i.renameField(f, name); } - public void renameMethod(Method m, String name) + public void renameMethod(Method oldMethod, info.sigterm.deob.pool.Method newMethod) { for (Instruction i : instructions) - i.renameMethod(m, name); + i.renameMethod(oldMethod, newMethod); } } 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 f5cfbc6743..218dd755e4 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 @@ -13,6 +13,7 @@ import info.sigterm.deob.execution.StackContext; import info.sigterm.deob.execution.Type; import info.sigterm.deob.pool.Class; import info.sigterm.deob.pool.InterfaceMethod; +import info.sigterm.deob.pool.Method; import info.sigterm.deob.pool.NameAndType; import info.sigterm.deob.pool.PoolEntry; import info.sigterm.deob.signature.Signature; @@ -149,10 +150,10 @@ public class InvokeInterface extends Instruction implements InvokeInstruction } @Override - public void renameMethod(info.sigterm.deob.Method m, String name) + public void renameMethod(info.sigterm.deob.Method m, Method newMethod) { for (info.sigterm.deob.Method m2 : getMethods()) if (m2.equals(m)) - method = new InterfaceMethod(method.getClassEntry(), new NameAndType(name, method.getNameAndType().getDescriptor())); + method = new InterfaceMethod(newMethod.getClassEntry(), newMethod.getNameAndType()); } } 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 b915a28ecc..25532cee1a 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 @@ -142,10 +142,10 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction } @Override - public void renameMethod(info.sigterm.deob.Method m, String name) + public void renameMethod(info.sigterm.deob.Method m, Method newMethod) { for (info.sigterm.deob.Method m2 : getMethods()) if (m2.equals(m)) - method = new Method(method.getClassEntry(), new NameAndType(name, method.getNameAndType().getDescriptor())); + method = newMethod; } } 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 314adb0da3..6ca5fa4bdc 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 @@ -139,7 +139,7 @@ public class InvokeStatic extends Instruction implements InvokeInstruction } @Override - public void renameMethod(info.sigterm.deob.Method m, String name) + public void renameMethod(info.sigterm.deob.Method m, Method newMethod) { ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup(); ClassFile otherClass = group.findClass(method.getClassEntry().getName()); @@ -150,6 +150,6 @@ public class InvokeStatic extends Instruction implements InvokeInstruction assert other.isStatic(); if (other.equals(m)) - method = new Method(method.getClassEntry(), new NameAndType(name, method.getNameAndType().getDescriptor())); + method = newMethod; } } 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 07665500e3..3401ed8c5f 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 @@ -147,10 +147,10 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction } @Override - public void renameMethod(info.sigterm.deob.Method m, String name) + public void renameMethod(info.sigterm.deob.Method m, Method newMethod) { for (info.sigterm.deob.Method m2 : getMethods()) if (m2.equals(m)) - method = new Method(method.getClassEntry(), new NameAndType(name, method.getNameAndType().getDescriptor())); + method = newMethod; } } diff --git a/src/main/java/info/sigterm/deob/deobfuscators/MethodMover.java b/src/main/java/info/sigterm/deob/deobfuscators/MethodMover.java index 4c93ec6722..de2e8491c5 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/MethodMover.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/MethodMover.java @@ -9,15 +9,18 @@ import info.sigterm.deob.attributes.code.Instruction; import info.sigterm.deob.attributes.code.Instructions; import info.sigterm.deob.attributes.code.instructions.InvokeStatic; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.collections4.map.MultiValueMap; -// find static methods that are only called from methods of one class +// find static methods that are only called from non-static methods of one class public class MethodMover implements Deobfuscator { + private ClassGroup group; private MultiValueMap calls = new MultiValueMap<>(); - private void buildCalls(ClassGroup group) + private void buildCalls() { calls.clear(); @@ -30,6 +33,9 @@ public class MethodMover implements Deobfuscator if (code == null) continue; + if (m.isStatic()) + continue; // only want member methods + Instructions ins = code.getInstructions(); for (Instruction i : ins.getInstructions()) { @@ -50,8 +56,10 @@ public class MethodMover implements Deobfuscator } } - private void look() + private int moveMethods() { + int moved = 0; + for (Method m : calls.keySet()) { Collection values = calls.getCollection(m); @@ -76,15 +84,54 @@ public class MethodMover implements Deobfuscator if (caller == null) continue; - System.out.println(caller.getName() + " always calls " + m.getName() + " sz " + values.size()); + if (m.getMethods().getClassFile() == caller) + continue; + + ++moved; + move(m, caller); } + + return moved; + } + + private void move(Method method, ClassFile to) + { + assert method.getMethods().getClassFile() != to; + + info.sigterm.deob.pool.Method newMethod = new info.sigterm.deob.pool.Method( + new info.sigterm.deob.pool.Class(to.getName()), + method.getNameAndType() + ); + + // move on instructions + for (ClassFile cf : group.getClasses()) + { + for (Method m : cf.getMethods().getMethods()) + { + Code code = m.getCode(); + + if (code == null) + continue; + + code.getInstructions().renameMethod(method, newMethod); + } + } + + // move the method + method.getMethods().removeMethod(method); + to.getMethods().getMethods().add(method); + method.setMethods(to.getMethods()); } @Override public void run(ClassGroup group) { + this.group = group; + group.buildClassGraph(); - buildCalls(group); - look(); + buildCalls(); + int count = moveMethods(); + + System.out.println("Moved " + count + " methods"); } } diff --git a/src/main/java/info/sigterm/deob/deobfuscators/RenameUnique.java b/src/main/java/info/sigterm/deob/deobfuscators/RenameUnique.java index 40e3e1cba2..13f0d0e40d 100644 --- a/src/main/java/info/sigterm/deob/deobfuscators/RenameUnique.java +++ b/src/main/java/info/sigterm/deob/deobfuscators/RenameUnique.java @@ -174,7 +174,13 @@ public class RenameUnique implements Deobfuscator { Instructions instructions = method.getCode().getInstructions(); for (Method m : methods) - instructions.renameMethod(m, name); + { + info.sigterm.deob.pool.Method newMethod = new info.sigterm.deob.pool.Method( + new info.sigterm.deob.pool.Class(m.getMethods().getClassFile().getName()), + new NameAndType(name, m.getNameAndType().getDescriptor()) + ); + instructions.renameMethod(m, newMethod); + } } } }