From 0a8d233083bf7fd93b3926462eaa008c76d18a35 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 23 Aug 2015 12:40:12 -0400 Subject: [PATCH 01/58] arith v2 --- .../java/net/runelite/deob/ClassFile.java | 5 + src/main/java/net/runelite/deob/Deob.java | 5 +- src/main/java/net/runelite/deob/Fields.java | 8 + .../code/instructions/GetField.java | 14 ++ .../code/instructions/GetStatic.java | 28 ++- .../deob/deobfuscators/arithmetic/DMath.java | 35 ++++ .../deobfuscators/arithmetic/Encryption.java | 25 +++ .../deobfuscators/arithmetic/ModArith.java | 189 ++++++++++++++++++ .../deob/deobfuscators/arithmetic/Pair.java | 9 + .../runelite/deob/execution/Execution.java | 7 + .../runelite/deob/execution/StackContext.java | 1 + 11 files changed, 314 insertions(+), 12 deletions(-) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/Pair.java diff --git a/src/main/java/net/runelite/deob/ClassFile.java b/src/main/java/net/runelite/deob/ClassFile.java index 1ad261847d..0fe86823c7 100644 --- a/src/main/java/net/runelite/deob/ClassFile.java +++ b/src/main/java/net/runelite/deob/ClassFile.java @@ -148,6 +148,11 @@ public class ClassFile { return children; } + + public Field findField(String name) + { + return fields.findField(name); + } public Field findFieldDeep(NameAndType nat) { diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 3995fdcab4..cf23be88ad 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -25,6 +25,7 @@ import net.runelite.deob.deobfuscators.UnusedClass; import net.runelite.deob.deobfuscators.UnusedFields; import net.runelite.deob.deobfuscators.UnusedMethods; import net.runelite.deob.deobfuscators.UnusedParameters; +import net.runelite.deob.deobfuscators.arithmetic.ModArith; //move static methods //move static fields @@ -102,7 +103,7 @@ public class Deob // System.out.println("unused methods took " + bdur/1000L + " seconds"); - new MethodInliner().run(group); + //new MethodInliner().run(group); // // new MethodMover().run(group); // @@ -115,6 +116,8 @@ public class Deob //new UnusedClass().run(group); // new ModularArithmeticDeobfuscation().run(group); + + new ModArith().run(group); saveJar(group, args[1]); diff --git a/src/main/java/net/runelite/deob/Fields.java b/src/main/java/net/runelite/deob/Fields.java index 293bc7fa1b..49e2ffcefb 100644 --- a/src/main/java/net/runelite/deob/Fields.java +++ b/src/main/java/net/runelite/deob/Fields.java @@ -50,4 +50,12 @@ public class Fields return f; return null; } + + public Field findField(String name) + { + for (Field f : fields) + if (f.getName().equals(name)) + return f; + return null; + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java index 252f3aa2c4..9449bedc2c 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java @@ -17,6 +17,8 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import net.runelite.deob.deobfuscators.arithmetic.Encryption; +import net.runelite.deob.deobfuscators.arithmetic.Pair; public class GetField extends Instruction implements GetFieldInstruction { @@ -48,6 +50,18 @@ public class GetField extends Instruction implements GetFieldInstruction ins.pop(object); StackContext ctx = new StackContext(ins, new Type(field.getNameAndType().getDescriptorType()).toStackType()); + + Encryption encryption = frame.getExecution().getEncryption(); + net.runelite.deob.Field f = getMyField(); + if (f != null) + { + Pair pair = encryption.getField(f); + if (pair != null) + { + ctx.encryption = pair.getter; + } + } + stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java index f2b69e97c9..5c57774614 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java @@ -17,6 +17,8 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import net.runelite.deob.deobfuscators.arithmetic.Encryption; +import net.runelite.deob.deobfuscators.arithmetic.Pair; public class GetStatic extends Instruction implements GetFieldInstruction { @@ -45,6 +47,18 @@ public class GetStatic extends Instruction implements GetFieldInstruction Stack stack = frame.getStack(); StackContext ctx = new StackContext(ins, new Type(field.getNameAndType().getDescriptorType()).toStackType()); + + Encryption encryption = frame.getExecution().getEncryption(); + net.runelite.deob.Field f = getMyField(); + if (f != null) + { + Pair pair = encryption.getField(f); + if (pair != null) + { + ctx.encryption = pair.getter; + } + } + stack.push(ctx); ins.push(ctx); @@ -55,17 +69,9 @@ public class GetStatic extends Instruction implements GetFieldInstruction @Override public void buildInstructionGraph() { - Class clazz = field.getClassEntry(); - NameAndType nat = field.getNameAndType(); - - ClassFile cf = this.getInstructions().getCode().getAttributes().getClassFile().getGroup().findClass(clazz.getName()); - if (cf == null) - return; - - net.runelite.deob.Field f = cf.findFieldDeep(nat); - assert f != null; - - f.addReference(this); + net.runelite.deob.Field f = getMyField(); + if (f != null) + f.addReference(this); } @Override diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java new file mode 100644 index 0000000000..bb3aa9fbb5 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java @@ -0,0 +1,35 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import java.math.BigInteger; + +public class DMath +{ + public static BigInteger modInverse(BigInteger val, int bits) + { + BigInteger shift = BigInteger.ONE.shiftLeft(bits); + return val.modInverse(shift); + } + + public static int modInverse(int val) + { + return modInverse(BigInteger.valueOf(val), 32).intValue(); + } + + public static long modInverse(long val) + { + return modInverse(BigInteger.valueOf(val), 64).longValue(); + } + + public static boolean isInversable(int val) + { + try + { + modInverse(val); + return true; + } + catch (ArithmeticException ex) + { + return false; + } + } +} diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java new file mode 100644 index 0000000000..c6f7c8f435 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -0,0 +1,25 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import java.util.HashMap; +import java.util.Map; +import net.runelite.deob.Field; + +public class Encryption +{ + private Map fields = new HashMap<>(); + + public Pair getField(Field field) + { + if (field.getName().equals("field1170")) + { + Pair p = new Pair(); + p.field = field; + p.getter = -1570098313; + p.setter = DMath.modInverse(p.getter); + assert p.setter == 1237096007; + return p; + } + return null; + //return fields.get(field); + } +} diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java new file mode 100644 index 0000000000..254917cd09 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -0,0 +1,189 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Deobfuscator; +import net.runelite.deob.Field; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; +import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; +import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.execution.Execution; +import net.runelite.deob.execution.Frame; +import net.runelite.deob.execution.InstructionContext; +import net.runelite.deob.execution.StackContext; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.map.MultiValueMap; + +/* +store an encryption context on stack context that shows the value the ctx is encrypted with +*/ + +public class ModArith implements Deobfuscator +{ + private ClassGroup group; + private Execution execution; + private MultiValueMap fieldIns = new MultiValueMap<>(); + + private void findGetField(InstructionContext ctx) + { + + } + + private void findUses() + { + //List list = new ArrayList<>(); + + for (Frame f : execution.processedFrames) + for (InstructionContext ctx : f.getInstructions()) + { + Instruction i = ctx.getInstruction(); + + if (!(i instanceof FieldInstruction)) + continue; + + FieldInstruction fi = (FieldInstruction) i; + + Field fifield = fi.getMyField(); + + if (fifield == null) + continue; + + fieldIns.put(fifield, ctx); +// if (i instanceof GetFieldInstruction) +// { +// findGetField(ctx); +// } + } + + //return list; +// for (ClassFile cf : group.getClasses()) +// for (Field f : cf.getFields().getFields()) +// { +// +// } + } + + public void calculate(Field field) + { + Collection c = fieldIns.getCollection(field); + if (c == null) + return; + + List constants = new ArrayList<>(); + for (InstructionContext ctx : c) + { + if (ctx.getInstruction() instanceof GetFieldInstruction) + { + List fields = getFieldsInExpression(ctx, constants); + if (fields.size() == 1) + { + } + } + } + + Map map = CollectionUtils.getCardinalityMap(constants); + int max = Collections.max(map.values()); + + for (final Map.Entry entry : map.entrySet()) { + if (max == entry.getValue()) { + int constant = entry.getKey(); + + System.out.println(constant); + assert DMath.isInversable(constant); + break; + } + } + } + + private List getFieldsInExpression(InstructionContext ctx, List constants) + { + return check(ctx, new HashSet(), constants); + } + + private List check(InstructionContext context, Set visited, List constants) + { + List fields = new ArrayList<>(); + + if (visited.contains(context)) + return fields; + + visited.add(context); + + if (context.getInstruction() instanceof InvokeInstruction) + { + // field = func(field * constant), the output of the function isn't directly related to the result of field * constant + return fields; + } + + if (context.getInstruction() instanceof FieldInstruction) + { + FieldInstruction fi = (FieldInstruction) context.getInstruction(); + Field myf = fi.getMyField(); + if (myf != null) + fields.add(myf); + } + + if (context.getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) context.getInstruction(); + int i = (int) pci.getConstant().getObject(); + constants.add(i); + } + + for (StackContext ctx : context.getPops()) + { + InstructionContext i = ctx.getPushed(); + + fields.addAll(check(i, visited, constants)); + } + + for (StackContext ctx : context.getPushes()) + { + InstructionContext i = ctx.getPopped(); + + if (i == null) + continue; + + fields.addAll(check(i, visited, constants)); + } + + return fields; + } + +// private void replace(Pair pair) +// { +// // do replacements with pair +// +// for (Frame frame : execution.processedFrames) +// { +// for (InstructionContext ctx : frame.getInstructions()) +// { +// } +// } +// } + + @Override + public void run(ClassGroup group) + { + this.group = group; + group.buildClassGraph(); + + execution = new Execution(group); + execution.populateInitialMethods(); + execution.run(); + + findUses(); + + Field f = group.findClass("class41").findField("field1170"); + calculate(f); + } + +} diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Pair.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Pair.java new file mode 100644 index 0000000000..f68d9eea8d --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Pair.java @@ -0,0 +1,9 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import net.runelite.deob.Field; + +public class Pair +{ + public Field field; + public int getter, setter; +} diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index d216e6c9f6..5e3ba5bdd5 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -11,6 +11,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; +import net.runelite.deob.deobfuscators.arithmetic.Encryption; import org.apache.commons.collections4.map.MultiValueMap; public class Execution @@ -21,11 +22,17 @@ public class Execution public Set methods = new HashSet<>(); // all methods public Set executed = new HashSet<>(); // executed instructions private MultiValueMap invokes = new MultiValueMap<>(); + private Encryption encryption; public Execution(ClassGroup group) { this.group = group; } + + public Encryption getEncryption() + { + return encryption; + } public void populateInitialMethods() { diff --git a/src/main/java/net/runelite/deob/execution/StackContext.java b/src/main/java/net/runelite/deob/execution/StackContext.java index 92fc0f3f93..78d4a75f9d 100644 --- a/src/main/java/net/runelite/deob/execution/StackContext.java +++ b/src/main/java/net/runelite/deob/execution/StackContext.java @@ -9,6 +9,7 @@ public class StackContext public InstructionContext popped; // instruction which popped this public Type type; // type of this public boolean removed; + public int encryption; // if this value is encrypted, this is the key to get the real value public StackContext(InstructionContext pushed, Type type) { From 7ac2b0e977afe34b2cafe821f97b2db687fe902c Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 23 Aug 2015 18:22:51 -0400 Subject: [PATCH 02/58] Working on doing arith deob during exec --- .../code/instructions/GetField.java | 2 +- .../attributes/code/instructions/IMul.java | 39 ++++++++++++ .../code/instructions/PutStatic.java | 61 +++++++++++++++++++ .../deobfuscators/arithmetic/Encryption.java | 20 ++++++ .../deobfuscators/arithmetic/ModArith.java | 12 +++- .../runelite/deob/execution/Execution.java | 5 ++ 6 files changed, 135 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java index 9449bedc2c..67da2bdf62 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java @@ -53,7 +53,7 @@ public class GetField extends Instruction implements GetFieldInstruction Encryption encryption = frame.getExecution().getEncryption(); net.runelite.deob.Field f = getMyField(); - if (f != null) + if (encryption != null && f != null) { Pair pair = encryption.getField(f); if (pair != null) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index c1688b0c9c..8d95e1c4e9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -3,6 +3,10 @@ package net.runelite.deob.attributes.code.instructions; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.deobfuscators.arithmetic.DMath; +import net.runelite.deob.deobfuscators.arithmetic.Encryption; +import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; @@ -26,6 +30,41 @@ public class IMul extends Instruction ins.pop(one, two); + Encryption encryption = frame.getExecution().getEncryption(); + if (encryption != null) + { + if (one.encryption != 0) + { + assert two.encryption == 0; + PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); + int other = (int) pci.getConstant().getObject(); + + // 'one' is encrypted and we want to decrypt it by dividing by one.encryption + + int o = other * DMath.modInverse(one.encryption); + + System.out.println(other + " -> " + o); + + encryption.change(pci, o); + +// if (one.encryption == other) +// { +// System.out.println("decrr"); +// } + } + else if (two.encryption != 0) + { + PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); + int other = (int) pci.getConstant().getObject(); + + int o = other * DMath.modInverse(two.encryption); + + System.out.println(other + " -> " + o); + + encryption.change(pci, o); + } + } + StackContext ctx = new StackContext(ins, int.class); stack.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index b49c30e1f4..e95550f159 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -16,6 +16,10 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.List; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.deobfuscators.arithmetic.Encryption; +import net.runelite.deob.deobfuscators.arithmetic.Pair; public class PutStatic extends Instruction implements SetFieldInstruction { @@ -46,6 +50,63 @@ public class PutStatic extends Instruction implements SetFieldInstruction StackContext object = stack.pop(); ins.pop(object); + Encryption encryption = frame.getExecution().getEncryption(); + net.runelite.deob.Field myField = getMyField(); + if (encryption != null && myField != null) + { + Pair pair = encryption.getField(myField); + InstructionContext ctx = object.getPushed(); + if (ctx.getInstruction() instanceof ISub) + { + List stackCtx = ctx.getPops(); + + StackContext one = stackCtx.get(0), two = stackCtx.get(1); + + if (one.getPushed().getInstruction() instanceof IMul) + { + ctx = one.getPushed(); + } + else if (two.getPushed().getInstruction() instanceof IMul) + { + ctx = two.getPushed(); + } + } + if (ctx.getInstruction() instanceof IMul && pair != null) + { + List stackCtx = ctx.getPops(); + + StackContext one = stackCtx.get(0), two = stackCtx.get(1); + + if (one.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); + int value = (int) pci.getConstant().getObject(); + + // field is encrypted with pair + // divide value by setter + + value = value * pair.getter; + + encryption.change(pci, value); + + } + else if (two.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); + int value = (int) pci.getConstant().getObject(); + + // field is encrypted with pair + // divide value by setter + + value = value * pair.getter; + + encryption.change(pci, value); + } + else + assert false; + } + } + frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index c6f7c8f435..b05133f860 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -2,11 +2,14 @@ package net.runelite.deob.deobfuscators.arithmetic; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import net.runelite.deob.Field; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; public class Encryption { private Map fields = new HashMap<>(); + private Map changes = new HashMap<>(); public Pair getField(Field field) { @@ -22,4 +25,21 @@ public class Encryption return null; //return fields.get(field); } + + public void change(PushConstantInstruction pci, int value) + { + assert !changes.containsKey(pci) || changes.get(pci) == value; + changes.put(pci, value); + } + + public void doChange() + { + for (Entry e : changes.entrySet()) + { + PushConstantInstruction pci = e.getKey(); + int value = e.getValue(); + + pci.setConstant(new net.runelite.deob.pool.Integer(value)); + } + } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 254917cd09..43f3c5ed3f 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -178,12 +178,18 @@ public class ModArith implements Deobfuscator execution = new Execution(group); execution.populateInitialMethods(); + + Encryption encr = new Encryption(); + execution.setEncryption(encr); + execution.run(); - findUses(); + encr.doChange(); - Field f = group.findClass("class41").findField("field1170"); - calculate(f); +// findUses(); +// +// Field f = group.findClass("class41").findField("field1170"); +// calculate(f); } } diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index 5e3ba5bdd5..716649bf2d 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -34,6 +34,11 @@ public class Execution return encryption; } + public void setEncryption(Encryption encryption) + { + this.encryption = encryption; + } + public void populateInitialMethods() { for (ClassFile cf : group.getClasses()) From 5561478ec8ed06a26a2ac3440debb4328f927a8a Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 23 Aug 2015 18:35:45 -0400 Subject: [PATCH 03/58] Also direct assignment --- .../code/instructions/PutStatic.java | 12 ++++++++++++ .../deobfuscators/arithmetic/Encryption.java | 18 +++++++++++++++++- .../deobfuscators/arithmetic/ModArith.java | 13 ++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index e95550f159..050af727ce 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -56,6 +56,18 @@ public class PutStatic extends Instruction implements SetFieldInstruction { Pair pair = encryption.getField(myField); InstructionContext ctx = object.getPushed(); + if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) + { + // field = encryptedvalue + // decrypt value by * getter + + PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); + int value = (int) pci.getConstant().getObject(); + + value = value * pair.getter; + + encryption.change(pci, value); + } if (ctx.getInstruction() instanceof ISub) { List stackCtx = ctx.getPops(); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index b05133f860..b71b502a94 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -10,10 +10,17 @@ public class Encryption { private Map fields = new HashMap<>(); private Map changes = new HashMap<>(); + int i; + private Pair p; + + public Encryption(int i) + { + this.i = i; + } public Pair getField(Field field) { - if (field.getName().equals("field1170")) + if (i == 0 && field.getName().equals("field1170")) { Pair p = new Pair(); p.field = field; @@ -22,6 +29,15 @@ public class Encryption assert p.setter == 1237096007; return p; } + if (i == 1 && field.getName().equals("field700")) + { + Pair p = new Pair(); + p.field = field; + p.getter = -478315765; + p.setter = DMath.modInverse(p.getter); + //assert p.setter == + return p; + } return null; //return fields.get(field); } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 43f3c5ed3f..244c1ff39c 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -179,7 +179,18 @@ public class ModArith implements Deobfuscator execution = new Execution(group); execution.populateInitialMethods(); - Encryption encr = new Encryption(); + Encryption encr = new Encryption(0); + execution.setEncryption(encr); + + execution.run(); + + encr.doChange(); + + + execution = new Execution(group); + execution.populateInitialMethods(); + + encr = new Encryption(1); execution.setEncryption(encr); execution.run(); From 4143a59d9d006a0c6c08276d47f10d5978c18779 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 23 Aug 2015 20:29:23 -0400 Subject: [PATCH 04/58] cleanup --- .../deob/attributes/code/instructions/GetField.java | 10 +--------- .../deob/attributes/code/instructions/GetStatic.java | 10 +--------- .../deob/deobfuscators/arithmetic/ModArith.java | 12 ------------ 3 files changed, 2 insertions(+), 30 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java index 67da2bdf62..84bbe1d55c 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java @@ -102,15 +102,7 @@ public class GetField extends Instruction implements GetFieldInstruction @Override public void renameField(net.runelite.deob.Field f, Field newField) { - Class clazz = field.getClassEntry(); - NameAndType nat = field.getNameAndType(); - - ClassFile cf = this.getInstructions().getCode().getAttributes().getClassFile().getGroup().findClass(clazz.getName()); - if (cf == null) - return; - - net.runelite.deob.Field f2 = cf.findFieldDeep(nat); - assert f2 != null; + net.runelite.deob.Field f2 = getMyField(); if (f2 == f) field = newField; diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java index d4bb05104a..bcf957ebca 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java @@ -99,15 +99,7 @@ public class GetStatic extends Instruction implements GetFieldInstruction @Override public void renameField(net.runelite.deob.Field f, Field newField) { - Class clazz = field.getClassEntry(); - NameAndType nat = field.getNameAndType(); - - ClassFile cf = this.getInstructions().getCode().getAttributes().getClassFile().getGroup().findClass(clazz.getName()); - if (cf == null) - return; - - net.runelite.deob.Field f2 = cf.findFieldDeep(nat); - assert f2 != null; + net.runelite.deob.Field f2 = getMyField(); if (f2 == f) { diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 244c1ff39c..9f06cf2a40 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -157,18 +157,6 @@ public class ModArith implements Deobfuscator return fields; } - -// private void replace(Pair pair) -// { -// // do replacements with pair -// -// for (Frame frame : execution.processedFrames) -// { -// for (InstructionContext ctx : frame.getInstructions()) -// { -// } -// } -// } @Override public void run(ClassGroup group) From 1fd79174ea6075ec7d14fecc0a13cef55ec3d316 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 24 Aug 2015 18:27:13 -0400 Subject: [PATCH 05/58] Some detecting getters, not totally right. Cap at 5. --- .../code/instructions/GetStatic.java | 2 +- .../attributes/code/instructions/IMul.java | 26 +- .../code/instructions/PutStatic.java | 27 +- .../deobfuscators/arithmetic/Encryption.java | 46 ++-- .../deobfuscators/arithmetic/ModArith.java | 230 +++++++++++++----- 5 files changed, 221 insertions(+), 110 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java index bcf957ebca..68b2451a5d 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java @@ -50,7 +50,7 @@ public class GetStatic extends Instruction implements GetFieldInstruction Encryption encryption = frame.getExecution().getEncryption(); net.runelite.deob.Field f = getMyField(); - if (f != null) + if (f != null && encryption != null) { Pair pair = encryption.getField(f); if (pair != null) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index 8d95e1c4e9..a8911d329a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -41,11 +41,14 @@ public class IMul extends Instruction // 'one' is encrypted and we want to decrypt it by dividing by one.encryption - int o = other * DMath.modInverse(one.encryption); - - System.out.println(other + " -> " + o); - - encryption.change(pci, o); + if (other != 1 && other != 0) + { + int o = other * DMath.modInverse(one.encryption); + + System.out.println(other + " -> " + o); + + encryption.change(pci, o); + } // if (one.encryption == other) // { @@ -57,11 +60,14 @@ public class IMul extends Instruction PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); int other = (int) pci.getConstant().getObject(); - int o = other * DMath.modInverse(two.encryption); - - System.out.println(other + " -> " + o); - - encryption.change(pci, o); + if (other != 1 && other != 0) + { + int o = other * DMath.modInverse(two.encryption); + + System.out.println(other + " -> " + o); + + encryption.change(pci, o); + } } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index 050af727ce..0dd9038839 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -64,9 +64,12 @@ public class PutStatic extends Instruction implements SetFieldInstruction PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); int value = (int) pci.getConstant().getObject(); - value = value * pair.getter; - - encryption.change(pci, value); + if (value != 0 && value != 1) + { + value = value * pair.getter; + + encryption.change(pci, value); + } } if (ctx.getInstruction() instanceof ISub) { @@ -97,9 +100,12 @@ public class PutStatic extends Instruction implements SetFieldInstruction // field is encrypted with pair // divide value by setter - value = value * pair.getter; - - encryption.change(pci, value); + if (value != 0 && value != 1) + { + value = value * pair.getter; + + encryption.change(pci, value); + } } else if (two.getPushed().getInstruction() instanceof PushConstantInstruction) @@ -110,9 +116,12 @@ public class PutStatic extends Instruction implements SetFieldInstruction // field is encrypted with pair // divide value by setter - value = value * pair.getter; - - encryption.change(pci, value); + if (value != 0 && value != 1) + { + value = value * pair.getter; + + encryption.change(pci, value); + } } else assert false; diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index b71b502a94..a9abba21c5 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -10,36 +10,34 @@ public class Encryption { private Map fields = new HashMap<>(); private Map changes = new HashMap<>(); - int i; - private Pair p; - public Encryption(int i) + public void addPair(Pair pair) { - this.i = i; + fields.put(pair.field, pair); } public Pair getField(Field field) { - if (i == 0 && field.getName().equals("field1170")) - { - Pair p = new Pair(); - p.field = field; - p.getter = -1570098313; - p.setter = DMath.modInverse(p.getter); - assert p.setter == 1237096007; - return p; - } - if (i == 1 && field.getName().equals("field700")) - { - Pair p = new Pair(); - p.field = field; - p.getter = -478315765; - p.setter = DMath.modInverse(p.getter); - //assert p.setter == - return p; - } - return null; - //return fields.get(field); +// if (i == 0 && field.getName().equals("field1170")) +// { +// Pair p = new Pair(); +// p.field = field; +// p.getter = -1570098313; +// p.setter = DMath.modInverse(p.getter); +// assert p.setter == 1237096007; +// return p; +// } +// if (i == 1 && field.getName().equals("field700")) +// { +// Pair p = new Pair(); +// p.field = field; +// p.getter = -478315765; +// p.setter = DMath.modInverse(p.getter); +// //assert p.setter == +// return p; +// } +// return null; + return fields.get(field); } public void change(PushConstantInstruction pci, int value) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 9f06cf2a40..5b4671dadb 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -15,6 +15,8 @@ import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; +import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; @@ -30,12 +32,15 @@ public class ModArith implements Deobfuscator { private ClassGroup group; private Execution execution; - private MultiValueMap fieldIns = new MultiValueMap<>(); + private MultiValueMap constants = new MultiValueMap<>(); + //private MultiValueMap fieldIns = new MultiValueMap<>(); - private void findGetField(InstructionContext ctx) - { - - } + + +// private void findGetField(InstructionContext ctx) +// { +// +// } private void findUses() { @@ -44,65 +49,122 @@ public class ModArith implements Deobfuscator for (Frame f : execution.processedFrames) for (InstructionContext ctx : f.getInstructions()) { - Instruction i = ctx.getInstruction(); - - if (!(i instanceof FieldInstruction)) - continue; - - FieldInstruction fi = (FieldInstruction) i; - - Field fifield = fi.getMyField(); - - if (fifield == null) - continue; - - fieldIns.put(fifield, ctx); -// if (i instanceof GetFieldInstruction) -// { -// findGetField(ctx); -// } + if (ctx.getInstruction() instanceof IMul) + { + Instruction one = ctx.getPops().get(0).getPushed().getInstruction(); + Instruction two = ctx.getPops().get(1).getPushed().getInstruction(); + + PushConstantInstruction pc = null; + GetFieldInstruction gf = null; + if (one instanceof PushConstantInstruction && two instanceof GetFieldInstruction) + { + pc = (PushConstantInstruction) one; + gf = (GetFieldInstruction) two; + } + else if (two instanceof PushConstantInstruction && one instanceof GetFieldInstruction) + { + pc = (PushConstantInstruction) two; + gf = (GetFieldInstruction) one; + } + + if (pc == null) + continue; + + Field field = gf.getMyField(); + int value = (int) pc.getConstant().getObject(); + + constants.put(field, value); + } + else if (ctx.getInstruction() instanceof SetFieldInstruction) + { + SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction(); + + StackContext value = ctx.getPops().get(0); // what setfield pops as value + if (!(value.getPushed().getInstruction() instanceof IMul)) + continue; + + Instruction one = value.getPushed().getPops().get(0).getPushed().getInstruction(); + Instruction two = value.getPushed().getPops().get(1).getPushed().getInstruction(); + + PushConstantInstruction pc = null; + Instruction other = null; + if (one instanceof PushConstantInstruction) + { + pc = (PushConstantInstruction) one; + other = two; + } + else if (two instanceof PushConstantInstruction) + { + pc = (PushConstantInstruction) two; + other = one; + } + + if (pc == null) + continue; + + Field field = sf.getMyField(); + int value2 = (int) pc.getConstant().getObject(); + + constants.put(field, value2); + } } - - //return list; -// for (ClassFile cf : group.getClasses()) -// for (Field f : cf.getFields().getFields()) -// { -// -// } } - public void calculate(Field field) + private void reduce() { - Collection c = fieldIns.getCollection(field); - if (c == null) - return; + MultiValueMap values = constants; + constants = new MultiValueMap<>(); - List constants = new ArrayList<>(); - for (InstructionContext ctx : c) + for (Field field : values.keySet()) { - if (ctx.getInstruction() instanceof GetFieldInstruction) - { - List fields = getFieldsInExpression(ctx, constants); - if (fields.size() == 1) - { + Collection col = values.getCollection(field); + + Map map = CollectionUtils.getCardinalityMap(col); + int max = Collections.max(map.values()); + + for (final Map.Entry entry : map.entrySet()) { + if (max == entry.getValue()) { + int constant = entry.getKey(); + + constants.put(field, constant); + break; } } } - - Map map = CollectionUtils.getCardinalityMap(constants); - int max = Collections.max(map.values()); - - for (final Map.Entry entry : map.entrySet()) { - if (max == entry.getValue()) { - int constant = entry.getKey(); - - System.out.println(constant); - assert DMath.isInversable(constant); - break; - } - } } +// public void calculate(Field field) +// { +// Collection c = fieldIns.getCollection(field); +// if (c == null) +// return; +// +// List constants = new ArrayList<>(); +// for (InstructionContext ctx : c) +// { +// if (ctx.getInstruction() instanceof GetFieldInstruction) +// { +// List fields = getFieldsInExpression(ctx, constants); +// if (fields.size() == 1) +// { +// } +// } +// } +// +// Map map = CollectionUtils.getCardinalityMap(constants); +// int max = Collections.max(map.values()); +// +// for (final Map.Entry entry : map.entrySet()) { +// if (max == entry.getValue()) { +// int constant = entry.getKey(); +// +// System.out.println(constant); +// assert DMath.isInversable(constant); +// break; +// } +// } +// } + private List getFieldsInExpression(InstructionContext ctx, List constants) { return check(ctx, new HashSet(), constants); @@ -166,24 +228,60 @@ public class ModArith implements Deobfuscator execution = new Execution(group); execution.populateInitialMethods(); - - Encryption encr = new Encryption(0); - execution.setEncryption(encr); - execution.run(); - encr.doChange(); + findUses(); + reduce(); + int i = 0; + for (Field field : constants.keySet()) + { + System.out.println("Processing " + field.getName()); + int getter = constants.getCollection(field).iterator().next(); + + if (i > 5) + break; + + Pair pair = new Pair(); + pair.field = field; + pair.getter = getter; + pair.setter = DMath.modInverse(getter); + + Encryption encr = new Encryption(); + encr.addPair(pair); + + execution = new Execution(group); + execution.populateInitialMethods(); + execution.setEncryption(encr); + execution.run(); + + encr.doChange(); + System.out.println("Changed" + ++i); + } - execution = new Execution(group); - execution.populateInitialMethods(); + Encryption encr = new Encryption(); + System.out.println(constants); - encr = new Encryption(1); - execution.setEncryption(encr); - - execution.run(); - - encr.doChange(); +// execution = new Execution(group); +// execution.populateInitialMethods(); +// +// Encryption encr = new Encryption(0); +// execution.setEncryption(encr); +// +// execution.run(); +// +// encr.doChange(); +// +// +// execution = new Execution(group); +// execution.populateInitialMethods(); +// +// encr = new Encryption(1); +// execution.setEncryption(encr); +// +// execution.run(); +// +// encr.doChange(); // findUses(); // From 227606a065e1ab9b0b09e5d8667971e632a57165 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 26 Aug 2015 19:10:56 -0400 Subject: [PATCH 06/58] hm --- src/main/java/net/runelite/deob/Field.java | 7 ++ .../code/instructions/PutStatic.java | 86 ++++++++++++++----- .../deob/deobfuscators/arithmetic/DMath.java | 5 ++ .../deobfuscators/arithmetic/Encryption.java | 5 ++ .../deobfuscators/arithmetic/ModArith.java | 2 +- 5 files changed, 84 insertions(+), 21 deletions(-) diff --git a/src/main/java/net/runelite/deob/Field.java b/src/main/java/net/runelite/deob/Field.java index 07e883acd8..74d2916598 100644 --- a/src/main/java/net/runelite/deob/Field.java +++ b/src/main/java/net/runelite/deob/Field.java @@ -8,6 +8,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Objects; public class Field { @@ -95,4 +96,10 @@ public class Field { return attributes; } + + @Override + public int hashCode() + { + return name.hashCode(); + } } \ No newline at end of file diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index 0dd9038839..a51c1402d9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -18,6 +18,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.List; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.deobfuscators.arithmetic.DMath; import net.runelite.deob.deobfuscators.arithmetic.Encryption; import net.runelite.deob.deobfuscators.arithmetic.Pair; @@ -40,6 +41,33 @@ public class PutStatic extends Instruction implements SetFieldInstruction super.write(out); out.writeShort(this.getPool().make(field)); } + + private static StackContext findMagic(StackContext one, StackContext two) + { + if (one.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); + int value1 = (int) pci.getConstant().getObject(); + + if (DMath.isBig(value1)) + { + return one; + } + } + + if (two.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); + int value2 = (int) pci.getConstant().getObject(); + + if (DMath.isBig(value2)) + { + return two; + } + } + + return null; + } @Override public void execute(Frame frame) @@ -92,25 +120,11 @@ public class PutStatic extends Instruction implements SetFieldInstruction StackContext one = stackCtx.get(0), two = stackCtx.get(1); - if (one.getPushed().getInstruction() instanceof PushConstantInstruction) + StackContext magicStack = findMagic(one, two); + + if (magicStack != null) { - PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); - int value = (int) pci.getConstant().getObject(); - - // field is encrypted with pair - // divide value by setter - - if (value != 0 && value != 1) - { - value = value * pair.getter; - - encryption.change(pci, value); - } - - } - else if (two.getPushed().getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); + PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); int value = (int) pci.getConstant().getObject(); // field is encrypted with pair @@ -123,8 +137,40 @@ public class PutStatic extends Instruction implements SetFieldInstruction encryption.change(pci, value); } } - else - assert false; + +// if (one.getPushed().getInstruction() instanceof PushConstantInstruction) +// { +// PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); +// int value = (int) pci.getConstant().getObject(); +// +// // field is encrypted with pair +// // divide value by setter +// +// if (value != 0 && value != 1) +// { +// value = value * pair.getter; +// +// encryption.change(pci, value); +// } +// +// } +// else if (two.getPushed().getInstruction() instanceof PushConstantInstruction) +// { +// PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); +// int value = (int) pci.getConstant().getObject(); +// +// // field is encrypted with pair +// // divide value by setter +// +// if (value != 0 && value != 1) +// { +// value = value * pair.getter; +// +// encryption.change(pci, value); +// } +// } +// else +// assert false; } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java index bb3aa9fbb5..84496a5c93 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java @@ -32,4 +32,9 @@ public class DMath return false; } } + + public static boolean isBig(int val) + { + return (val & 0xFFF00000) != 0; + } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index a9abba21c5..ec055c10cc 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -5,6 +5,7 @@ import java.util.Map; import java.util.Map.Entry; import net.runelite.deob.Field; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.attributes.code.instructions.SiPush; public class Encryption { @@ -42,6 +43,10 @@ public class Encryption public void change(PushConstantInstruction pci, int value) { + if (pci instanceof SiPush) + { + int i =5; + } assert !changes.containsKey(pci) || changes.get(pci) == value; changes.put(pci, value); } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 5b4671dadb..9ac0613472 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -239,7 +239,7 @@ public class ModArith implements Deobfuscator System.out.println("Processing " + field.getName()); int getter = constants.getCollection(field).iterator().next(); - if (i > 5) + if (i > 50) break; Pair pair = new Pair(); From fae040a98faa4627e4e523fc608d676735d1c06b Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 5 Sep 2015 19:10:57 -0400 Subject: [PATCH 07/58] Fix methodinliner to move jumps to the function being inlined to the right place --- .../deob/deobfuscators/MethodInliner.java | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java b/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java index c86f15976e..37e946ce68 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java +++ b/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java @@ -111,6 +111,8 @@ public class MethodInliner implements Deobfuscator idx += descriptor.getTypeOfArg(j).getSlots(); } + Instruction firstParamStore = null; + for (int j = descriptor.size() - 1; j >= 0; --j) { Type type = descriptor.getTypeOfArg(j); @@ -151,12 +153,15 @@ public class MethodInliner implements Deobfuscator // insert storeIns before invoke instruction ins.getInstructions().add(invokeIdx++, storeIns); + + if (firstParamStore == null) + firstParamStore = storeIns; } int maxStack = code.getMaxStack() + invokedMethod.getCode().getMaxStack(); // not really right but ok code.setMaxStack(maxStack); - inline(m, i, invokedMethod, lvtIndex); + inline(m, i, invokedMethod, lvtIndex, firstParamStore); moveExceptions(m, invokedMethod); ++inlineCount; break; @@ -165,7 +170,7 @@ public class MethodInliner implements Deobfuscator return inlineCount; } - private void inline(Method method, Instruction invokeIns, Method invokeMethod, int lvtBase) + private void inline(Method method, Instruction invokeIns, Method invokeMethod, int lvtBase, Instruction firstParamStore) { Code methodCode = method.getCode(), invokeMethodCode = invokeMethod.getCode(); @@ -177,11 +182,17 @@ public class MethodInliner implements Deobfuscator Instruction nextInstruction = methodInstructions.getInstructions().get(idx + 1); - // move stuff which jumps to invokeIns to nop + // move stuff which jumps to invokeIns to firstParamStore. If there are no arguments that are stored, + // firstParamStore is null, and so create a nop instruction. - Instruction nop = new NOP(methodInstructions); - methodInstructions.getInstructions().add(idx + 1, nop); - ++idx; + if (firstParamStore == null) + { + Instruction nop = new NOP(methodInstructions); + methodInstructions.getInstructions().add(idx + 1, nop); + ++idx; + + firstParamStore = nop; + } methodInstructions.buildJumpGraph(); invokeMethodInstructions.buildJumpGraph(); @@ -191,15 +202,15 @@ public class MethodInliner implements Deobfuscator assert fromI.jump.contains(invokeIns); fromI.jump.remove(invokeIns); - fromI.replace(invokeIns, nop); + fromI.replace(invokeIns, firstParamStore); - fromI.jump.add(nop); - nop.from.add(fromI); + fromI.jump.add(firstParamStore); + firstParamStore.from.add(fromI); } invokeIns.from.clear(); for (net.runelite.deob.attributes.code.Exception e : invokeMethodCode.getExceptions().getExceptions()) - e.replace(invokeIns, nop); + e.replace(invokeIns, firstParamStore); methodInstructions.remove(invokeIns); From 88bd6490de1353367bca9bde37abb3628f07ad85 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 5 Sep 2015 23:19:38 -0400 Subject: [PATCH 08/58] Work. --- src/main/java/net/runelite/deob/Deob.java | 84 ++++---- .../attributes/code/instructions/IMul.java | 4 - .../code/instructions/PutField.java | 85 +++++++- .../code/instructions/PutStatic.java | 173 +++++++++-------- .../deobfuscators/arithmetic/Encryption.java | 29 +-- .../deobfuscators/arithmetic/ModArith.java | 182 +++++++++++------- 6 files changed, 332 insertions(+), 225 deletions(-) diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index cf23be88ad..f892934373 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -26,6 +26,7 @@ import net.runelite.deob.deobfuscators.UnusedFields; import net.runelite.deob.deobfuscators.UnusedMethods; import net.runelite.deob.deobfuscators.UnusedParameters; import net.runelite.deob.deobfuscators.arithmetic.ModArith; +import net.runelite.deob.execution.Execution; //move static methods //move static fields @@ -41,7 +42,6 @@ public class Deob long start = System.currentTimeMillis(); ClassGroup group = loadJar(args[0]); - long bstart, bdur; // bstart = System.currentTimeMillis(); // new RenameUnique().run(group); @@ -49,71 +49,45 @@ public class Deob // System.out.println("rename unique took " + bdur/1000L + " seconds"); // // remove except RuntimeException -// bstart = System.currentTimeMillis(); -// new RuntimeExceptions().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("runtime exception took " + bdur/1000L + " seconds"); +// run(group, new RuntimeExceptions()); // // // remove unused methods -// bstart = System.currentTimeMillis(); -// new UnusedMethods().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused methods took " + bdur/1000L + " seconds"); +// run(group, new UnusedMethods()); // -// new UnreachedCode().run(group); +// run(group, new UnreachedCode()); // // // remove illegal state exceptions, frees up some parameters -// bstart = System.currentTimeMillis(); -// new IllegalStateExceptions().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("illegal state exception took " + bdur/1000L + " seconds"); +// run(group, new IllegalStateExceptions()); // // // remove constant logically dead parameters -// bstart = System.currentTimeMillis(); -// new ConstantParameter().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("constant param took " + bdur/1000L + " seconds"); +// run(group, new ConstantParameter()); // // // remove unhit blocks -// bstart = System.currentTimeMillis(); -// new UnreachedCode().run(group); -// //new UnusedBlocks().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused blocks took " + bdur/1000L + " seconds"); +// run(group, new UnreachedCode()); // // // remove unused parameters -// bstart = System.currentTimeMillis(); -// new UnusedParameters().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused params took " + bdur/1000L + " seconds"); +// run(group, new UnusedParameters()); // // // remove jump obfuscation // //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"); +// run(group, new UnusedFields()); // // // remove unused methods, again? -// bstart = System.currentTimeMillis(); -// new UnusedMethods().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("unused methods took " + bdur/1000L + " seconds"); - - - //new MethodInliner().run(group); -// -// new MethodMover().run(group); +// run(group, new UnusedMethods()); // -// new FieldInliner().run(group); - - // XXX this is broken because when moving clinit around, some fields can depend on other fields - // (like multianewarray) - //new FieldMover().run(group); - - //new UnusedClass().run(group); +// run(group, new MethodInliner()); +// +// run(group, new MethodMover()); +// +// run(group, new FieldInliner()); +// +// // XXX this is broken because when moving clinit around, some fields can depend on other fields +// // (like multianewarray) +// //new FieldMover().run(group); +// +// run(group, new UnusedClass()); // new ModularArithmeticDeobfuscation().run(group); @@ -168,4 +142,20 @@ public class Deob jout.close(); } + + private static void run(ClassGroup group, Deobfuscator deob) + { + long bstart, bdur; + + bstart = System.currentTimeMillis(); + deob.run(group); + bdur = System.currentTimeMillis() - bstart; + + System.out.println(deob.getClass().getName() + " took " + (bdur / 1000L) + " seconds"); + + // check code is still correct + Execution execution = new Execution(group); + execution.populateInitialMethods(); + execution.run(); + } } \ No newline at end of file diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index a8911d329a..61955fb267 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -45,8 +45,6 @@ public class IMul extends Instruction { int o = other * DMath.modInverse(one.encryption); - System.out.println(other + " -> " + o); - encryption.change(pci, o); } @@ -64,8 +62,6 @@ public class IMul extends Instruction { int o = other * DMath.modInverse(two.encryption); - System.out.println(other + " -> " + o); - encryption.change(pci, o); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java index 400cc99524..af6c42cd8c 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java @@ -16,6 +16,10 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.List; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.deobfuscators.arithmetic.Encryption; +import net.runelite.deob.deobfuscators.arithmetic.Pair; public class PutField extends Instruction implements SetFieldInstruction { @@ -43,10 +47,89 @@ public class PutField extends Instruction implements SetFieldInstruction InstructionContext ins = new InstructionContext(this, frame); Stack stack = frame.getStack(); - StackContext object = stack.pop(); StackContext value = stack.pop(); + StackContext object = stack.pop(); ins.pop(object, value); + Encryption encryption = frame.getExecution().getEncryption(); + net.runelite.deob.Field myField = getMyField(); + if (encryption != null && myField != null) + { + Pair pair = encryption.getField(myField); + InstructionContext ctx = value.getPushed(); + if (ctx.getInstruction() instanceof IAdd && pair != null) + { + // field += constant * crap; + // in bytecode is really + // field = field + constant * crap + + List pops = ctx.getPops(); + + if (pops.get(0).getPushed().getInstruction() instanceof IMul) + { + ctx = pops.get(0).getPushed(); + } + else if (pops.get(1).getPushed().getInstruction() instanceof IMul) + { + ctx = pops.get(1).getPushed(); + } + } + if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) + { + // field = encryptedvalue + // decrypt value by * getter + + PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); + int v = (int) pci.getConstant().getObject(); + + if (v != 0 && v != 1) + { + v = v * pair.getter; + + encryption.change(pci, v); + } + } + if (ctx.getInstruction() instanceof ISub) + { + List stackCtx = ctx.getPops(); + + StackContext one = stackCtx.get(0), two = stackCtx.get(1); + + if (one.getPushed().getInstruction() instanceof IMul) + { + ctx = one.getPushed(); + } + else if (two.getPushed().getInstruction() instanceof IMul) + { + ctx = two.getPushed(); + } + } + if (ctx.getInstruction() instanceof IMul && pair != null) + { + List stackCtx = ctx.getPops(); + + StackContext one = stackCtx.get(0), two = stackCtx.get(1); + + StackContext magicStack = PutStatic.findMagic(one, two); + + if (magicStack != null) + { + PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); + int v = (int) pci.getConstant().getObject(); + + // field is encrypted with pair + // divide value by setter + + if (v != 0 && v != 1) + { + v = v * pair.getter; + + encryption.change(pci, v); + } + } + } + } + frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index a51c1402d9..34e6a346bf 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -42,7 +42,7 @@ public class PutStatic extends Instruction implements SetFieldInstruction out.writeShort(this.getPool().make(field)); } - private static StackContext findMagic(StackContext one, StackContext two) + protected static StackContext findMagic(StackContext one, StackContext two) { if (one.getPushed().getInstruction() instanceof PushConstantInstruction) { @@ -68,6 +68,44 @@ public class PutStatic extends Instruction implements SetFieldInstruction return null; } + + private static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx) + { + if (ctx.getInstruction() instanceof LDC_W) + { + LDC_W pci = (LDC_W) ctx.getInstruction(); + int value = (int) pci.getConstant().getObject(); + + if (encryption.hasChange(pci)) + return true; + + if (value != 0 && value != 1) + { + value = value * pair.getter; + + encryption.change(pci, value); + } + + return true; + } + + boolean multipleBranches = ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub; + boolean retVal = false; + + for (StackContext sctx : ctx.getPops()) + { + InstructionContext i = sctx.getPushed(); + + if (translate(encryption, pair, i)) + { + retVal = true; + if (!multipleBranches) + break; + } + } + + return retVal; + } @Override public void execute(Frame frame) @@ -83,80 +121,67 @@ public class PutStatic extends Instruction implements SetFieldInstruction if (encryption != null && myField != null) { Pair pair = encryption.getField(myField); - InstructionContext ctx = object.getPushed(); - if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) - { - // field = encryptedvalue - // decrypt value by * getter - - PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); - int value = (int) pci.getConstant().getObject(); - - if (value != 0 && value != 1) - { - value = value * pair.getter; - - encryption.change(pci, value); - } - } - if (ctx.getInstruction() instanceof ISub) - { - List stackCtx = ctx.getPops(); - - StackContext one = stackCtx.get(0), two = stackCtx.get(1); - - if (one.getPushed().getInstruction() instanceof IMul) - { - ctx = one.getPushed(); - } - else if (two.getPushed().getInstruction() instanceof IMul) - { - ctx = two.getPushed(); - } - } - if (ctx.getInstruction() instanceof IMul && pair != null) - { - List stackCtx = ctx.getPops(); - - StackContext one = stackCtx.get(0), two = stackCtx.get(1); - - StackContext magicStack = findMagic(one, two); - - if (magicStack != null) - { - PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); - int value = (int) pci.getConstant().getObject(); - - // field is encrypted with pair - // divide value by setter - - if (value != 0 && value != 1) - { - value = value * pair.getter; - - encryption.change(pci, value); - } - } - -// if (one.getPushed().getInstruction() instanceof PushConstantInstruction) + if (pair != null) + translate(encryption, pair, ins); +// InstructionContext ctx = object.getPushed(); +// if (ctx.getInstruction() instanceof IAdd && pair != null) +// { +// // field += constant * crap; +// // in bytecode is really +// // field = field + constant * crap +// +// List pops = ctx.getPops(); +// +// if (pops.get(0).getPushed().getInstruction() instanceof IMul) // { -// PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); -// int value = (int) pci.getConstant().getObject(); -// -// // field is encrypted with pair -// // divide value by setter -// -// if (value != 0 && value != 1) -// { -// value = value * pair.getter; -// -// encryption.change(pci, value); -// } -// +// ctx = pops.get(0).getPushed(); // } -// else if (two.getPushed().getInstruction() instanceof PushConstantInstruction) +// else if (pops.get(1).getPushed().getInstruction() instanceof IMul) // { -// PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); +// ctx = pops.get(1).getPushed(); +// } +// } +// if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) +// { +// // field = encryptedvalue +// // decrypt value by * getter +// +// PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); +// int value = (int) pci.getConstant().getObject(); +// +// if (value != 0 && value != 1) +// { +// value = value * pair.getter; +// +// encryption.change(pci, value); +// } +// } +// if (ctx.getInstruction() instanceof ISub) +// { +// List stackCtx = ctx.getPops(); +// +// StackContext one = stackCtx.get(0), two = stackCtx.get(1); +// +// if (one.getPushed().getInstruction() instanceof IMul) +// { +// ctx = one.getPushed(); +// } +// else if (two.getPushed().getInstruction() instanceof IMul) +// { +// ctx = two.getPushed(); +// } +// } +// if (ctx.getInstruction() instanceof IMul && pair != null) +// { +// List stackCtx = ctx.getPops(); +// +// StackContext one = stackCtx.get(0), two = stackCtx.get(1); +// +// StackContext magicStack = findMagic(one, two); +// +// if (magicStack != null) +// { +// PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); // int value = (int) pci.getConstant().getObject(); // // // field is encrypted with pair @@ -169,9 +194,7 @@ public class PutStatic extends Instruction implements SetFieldInstruction // encryption.change(pci, value); // } // } -// else -// assert false; - } +// } } frame.addInstructionContext(ins); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index ec055c10cc..cf66fa7653 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -5,7 +5,6 @@ import java.util.Map; import java.util.Map.Entry; import net.runelite.deob.Field; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; -import net.runelite.deob.attributes.code.instructions.SiPush; public class Encryption { @@ -19,34 +18,16 @@ public class Encryption public Pair getField(Field field) { -// if (i == 0 && field.getName().equals("field1170")) -// { -// Pair p = new Pair(); -// p.field = field; -// p.getter = -1570098313; -// p.setter = DMath.modInverse(p.getter); -// assert p.setter == 1237096007; -// return p; -// } -// if (i == 1 && field.getName().equals("field700")) -// { -// Pair p = new Pair(); -// p.field = field; -// p.getter = -478315765; -// p.setter = DMath.modInverse(p.getter); -// //assert p.setter == -// return p; -// } -// return null; return fields.get(field); } + public boolean hasChange(PushConstantInstruction pci) + { + return changes.containsKey(pci); + } + public void change(PushConstantInstruction pci, int value) { - if (pci instanceof SiPush) - { - int i =5; - } assert !changes.containsKey(pci) || changes.get(pci) == value; changes.put(pci, value); } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 9ac0613472..6310cc50e6 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -2,11 +2,10 @@ package net.runelite.deob.deobfuscators.arithmetic; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; +import net.runelite.deob.ClassFile; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; import net.runelite.deob.Field; @@ -21,7 +20,6 @@ import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.StackContext; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.MultiValueMap; /* @@ -32,20 +30,12 @@ public class ModArith implements Deobfuscator { private ClassGroup group; private Execution execution; - private MultiValueMap constants = new MultiValueMap<>(); - //private MultiValueMap fieldIns = new MultiValueMap<>(); - + private MultiValueMap constantGetters = new MultiValueMap<>(), + constantSetters = new MultiValueMap<>(); + private List pairs = new ArrayList<>(); - -// private void findGetField(InstructionContext ctx) -// { -// -// } - private void findUses() - { - //List list = new ArrayList<>(); - + { for (Frame f : execution.processedFrames) for (InstructionContext ctx : f.getInstructions()) { @@ -71,9 +61,12 @@ public class ModArith implements Deobfuscator continue; Field field = gf.getMyField(); + if (field == null) + continue; + int value = (int) pc.getConstant().getObject(); - constants.put(field, value); + constantGetters.put(field, value); } else if (ctx.getInstruction() instanceof SetFieldInstruction) { @@ -103,67 +96,113 @@ public class ModArith implements Deobfuscator continue; Field field = sf.getMyField(); + if (field == null) + continue; + int value2 = (int) pc.getConstant().getObject(); - constants.put(field, value2); + constantSetters.put(field, value2); } } } + private Pair reduce(Collection getters, Collection setters) + { + Pair p = null; + + for (Integer i : getters) + { + Integer inverse; + try + { + inverse = DMath.modInverse(i); + } + catch (ArithmeticException ex) + { + continue; + } + + if (setters.contains(inverse)) + { + if (p != null && p.getter != i) + return null; + + if (p == null) + { + p = new Pair(); + p.getter = i; + p.setter = inverse; + } + } + } + + for (Integer i : setters) + { + Integer inverse; + try + { + inverse = DMath.modInverse(i); + } + catch (ArithmeticException ex) + { + continue; + } + + if (getters.contains(inverse)) + { + if (p != null && p.setter != i) + return null; + + if (p == null) + { + p = new Pair(); + p.setter = i; + p.getter = inverse; + } + } + } + + return p; + } + private void reduce() { - MultiValueMap values = constants; - constants = new MultiValueMap<>(); - - for (Field field : values.keySet()) - { - Collection col = values.getCollection(field); - - Map map = CollectionUtils.getCardinalityMap(col); - int max = Collections.max(map.values()); - - for (final Map.Entry entry : map.entrySet()) { - if (max == entry.getValue()) { - int constant = entry.getKey(); - - constants.put(field, constant); - break; - } + for (ClassFile cf : group.getClasses()) + for (Field f : cf.getFields().getFields()) + { + Collection getters = constantGetters.getCollection(f), + setters = constantSetters.getCollection(f); + + if (getters == null || setters == null) + continue; + + Pair answer = reduce(getters, setters); + if (answer == null) + continue; + + answer.field = f; + pairs.add(answer); } - } - } - -// public void calculate(Field field) -// { -// Collection c = fieldIns.getCollection(field); -// if (c == null) -// return; +// MultiValueMap values = constants; +// constants = new MultiValueMap<>(); // -// List constants = new ArrayList<>(); -// for (InstructionContext ctx : c) +// for (Field field : values.keySet()) // { -// if (ctx.getInstruction() instanceof GetFieldInstruction) -// { -// List fields = getFieldsInExpression(ctx, constants); -// if (fields.size() == 1) -// { +// Collection col = values.getCollection(field); +// +// Map map = CollectionUtils.getCardinalityMap(col); +// int max = Collections.max(map.values()); +// +// for (final Map.Entry entry : map.entrySet()) { +// if (max == entry.getValue()) { +// int constant = entry.getKey(); +// +// constants.put(field, constant); +// break; // } // } // } -// -// Map map = CollectionUtils.getCardinalityMap(constants); -// int max = Collections.max(map.values()); -// -// for (final Map.Entry entry : map.entrySet()) { -// if (max == entry.getValue()) { -// int constant = entry.getKey(); -// -// System.out.println(constant); -// assert DMath.isInversable(constant); -// break; -// } -// } -// } + } private List getFieldsInExpression(InstructionContext ctx, List constants) { @@ -234,19 +273,14 @@ public class ModArith implements Deobfuscator reduce(); int i = 0; - for (Field field : constants.keySet()) + for (Pair pair : pairs) { - System.out.println("Processing " + field.getName()); - int getter = constants.getCollection(field).iterator().next(); + Field field = pair.field; + System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter); - if (i > 50) + if (i > 10) // 25 break; - Pair pair = new Pair(); - pair.field = field; - pair.getter = getter; - pair.setter = DMath.modInverse(getter); - Encryption encr = new Encryption(); encr.addPair(pair); @@ -256,11 +290,11 @@ public class ModArith implements Deobfuscator execution.run(); encr.doChange(); - System.out.println("Changed" + ++i); + System.out.println("Changed " + ++i); } Encryption encr = new Encryption(); - System.out.println(constants); + System.out.println(pairs); // execution = new Execution(group); // execution.populateInitialMethods(); From f46e4dfdceaa43f3d02e53c0266c22c082ed7d7d Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 6 Sep 2015 23:39:47 -0400 Subject: [PATCH 09/58] translating one field works --- .../code/instructions/PutField.java | 148 +++++++++--------- .../code/instructions/PutStatic.java | 24 ++- .../deobfuscators/arithmetic/Encryption.java | 30 ++++ .../deobfuscators/arithmetic/ModArith.java | 2 +- 4 files changed, 129 insertions(+), 75 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java index af6c42cd8c..3df0c55b03 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java @@ -18,6 +18,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.List; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import static net.runelite.deob.attributes.code.instructions.PutStatic.translate; import net.runelite.deob.deobfuscators.arithmetic.Encryption; import net.runelite.deob.deobfuscators.arithmetic.Pair; @@ -56,78 +57,81 @@ public class PutField extends Instruction implements SetFieldInstruction if (encryption != null && myField != null) { Pair pair = encryption.getField(myField); - InstructionContext ctx = value.getPushed(); - if (ctx.getInstruction() instanceof IAdd && pair != null) - { - // field += constant * crap; - // in bytecode is really - // field = field + constant * crap - - List pops = ctx.getPops(); - - if (pops.get(0).getPushed().getInstruction() instanceof IMul) - { - ctx = pops.get(0).getPushed(); - } - else if (pops.get(1).getPushed().getInstruction() instanceof IMul) - { - ctx = pops.get(1).getPushed(); - } - } - if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) - { - // field = encryptedvalue - // decrypt value by * getter - - PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); - int v = (int) pci.getConstant().getObject(); - - if (v != 0 && v != 1) - { - v = v * pair.getter; - - encryption.change(pci, v); - } - } - if (ctx.getInstruction() instanceof ISub) - { - List stackCtx = ctx.getPops(); - - StackContext one = stackCtx.get(0), two = stackCtx.get(1); - - if (one.getPushed().getInstruction() instanceof IMul) - { - ctx = one.getPushed(); - } - else if (two.getPushed().getInstruction() instanceof IMul) - { - ctx = two.getPushed(); - } - } - if (ctx.getInstruction() instanceof IMul && pair != null) - { - List stackCtx = ctx.getPops(); - - StackContext one = stackCtx.get(0), two = stackCtx.get(1); - - StackContext magicStack = PutStatic.findMagic(one, two); - - if (magicStack != null) - { - PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); - int v = (int) pci.getConstant().getObject(); - - // field is encrypted with pair - // divide value by setter - - if (v != 0 && v != 1) - { - v = v * pair.getter; - - encryption.change(pci, v); - } - } - } + if (pair != null) + translate(encryption, pair, ins); +// XXX move translate() here +// InstructionContext ctx = value.getPushed(); +// if (ctx.getInstruction() instanceof IAdd && pair != null) +// { +// // field += constant * crap; +// // in bytecode is really +// // field = field + constant * crap +// +// List pops = ctx.getPops(); +// +// if (pops.get(0).getPushed().getInstruction() instanceof IMul) +// { +// ctx = pops.get(0).getPushed(); +// } +// else if (pops.get(1).getPushed().getInstruction() instanceof IMul) +// { +// ctx = pops.get(1).getPushed(); +// } +// } +// if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) +// { +// // field = encryptedvalue +// // decrypt value by * getter +// +// PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); +// int v = (int) pci.getConstant().getObject(); +// +// if (v != 0 && v != 1) +// { +// v = v * pair.getter; +// +// encryption.change(pci, v); +// } +// } +// if (ctx.getInstruction() instanceof ISub) +// { +// List stackCtx = ctx.getPops(); +// +// StackContext one = stackCtx.get(0), two = stackCtx.get(1); +// +// if (one.getPushed().getInstruction() instanceof IMul) +// { +// ctx = one.getPushed(); +// } +// else if (two.getPushed().getInstruction() instanceof IMul) +// { +// ctx = two.getPushed(); +// } +// } +// if (ctx.getInstruction() instanceof IMul && pair != null) +// { +// List stackCtx = ctx.getPops(); +// +// StackContext one = stackCtx.get(0), two = stackCtx.get(1); +// +// StackContext magicStack = PutStatic.findMagic(one, two); +// +// if (magicStack != null) +// { +// PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); +// int v = (int) pci.getConstant().getObject(); +// +// // field is encrypted with pair +// // divide value by setter +// +// if (v != 0 && v != 1) +// { +// v = v * pair.getter; +// +// encryption.change(pci, v); +// } +// } +// } } frame.addInstructionContext(ins); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index 34e6a346bf..c00eb9c3e7 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -17,6 +17,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.List; +import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.deobfuscators.arithmetic.DMath; import net.runelite.deob.deobfuscators.arithmetic.Encryption; @@ -69,7 +70,7 @@ public class PutStatic extends Instruction implements SetFieldInstruction return null; } - private static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx) + protected static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx) { if (ctx.getInstruction() instanceof LDC_W) { @@ -89,9 +90,14 @@ public class PutStatic extends Instruction implements SetFieldInstruction return true; } + if (ctx.getInstruction() instanceof InvokeInstruction) + return false; + boolean multipleBranches = ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub; boolean retVal = false; + encryption.begin(); + for (StackContext sctx : ctx.getPops()) { InstructionContext i = sctx.getPushed(); @@ -99,11 +105,25 @@ public class PutStatic extends Instruction implements SetFieldInstruction if (translate(encryption, pair, i)) { retVal = true; - if (!multipleBranches) + + if (!multipleBranches) // only need to translate the one branch, which we have, return. break; } + else + { + if (multipleBranches) + { + // we can't translate both branches so rollback + encryption.rollback(); + retVal = false; + break; + } + // else this is okay, we can try another + } } + encryption.end(); + return retVal; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index cf66fa7653..461b6e36f3 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -1,15 +1,24 @@ package net.runelite.deob.deobfuscators.arithmetic; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; +import java.util.Stack; import net.runelite.deob.Field; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; public class Encryption { + private static class PendingStack + { + private Set pending = new HashSet<>(); + } + private Map fields = new HashMap<>(); private Map changes = new HashMap<>(); + private Stack stack = new Stack<>(); public void addPair(Pair pair) { @@ -30,6 +39,10 @@ public class Encryption { assert !changes.containsKey(pci) || changes.get(pci) == value; changes.put(pci, value); + if (stack.isEmpty()) + return; + PendingStack ps = stack.peek(); + ps.pending.add(pci); } public void doChange() @@ -42,4 +55,21 @@ public class Encryption pci.setConstant(new net.runelite.deob.pool.Integer(value)); } } + + public void begin() + { + stack.push(new PendingStack()); + } + + public void end() + { + stack.pop(); + } + + public void rollback() + { + PendingStack ps = stack.peek(); + for (PushConstantInstruction pci : ps.pending) + changes.remove(pci); + } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 6310cc50e6..f8471cc11c 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -278,7 +278,7 @@ public class ModArith implements Deobfuscator Field field = pair.field; System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter); - if (i > 10) // 25 + if (i > 0) // 2 break; Encryption encr = new Encryption(); From 2ea00d654f7bcfe607c947c5f4d605a36a47cd0e Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 7 Sep 2015 17:07:02 -0400 Subject: [PATCH 10/58] 32 vars! --- .../attributes/code/instructions/PutStatic.java | 13 ++++++++++++- .../deob/deobfuscators/arithmetic/ModArith.java | 9 +++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index c00eb9c3e7..c600f80fbb 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -90,7 +90,18 @@ public class PutStatic extends Instruction implements SetFieldInstruction return true; } - if (ctx.getInstruction() instanceof InvokeInstruction) +// if (ctx.getInstruction() instanceof InvokeInstruction) +// return false; +// +// if (ctx.getInstruction() instanceof IDiv) +// return false; + + boolean ok = ctx.getInstruction() instanceof IAdd || + ctx.getInstruction() instanceof ISub || + ctx.getInstruction() instanceof IMul || + ctx.getInstruction() instanceof SetFieldInstruction; + + if (!ok) return false; boolean multipleBranches = ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub; diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index f8471cc11c..526ccd31fd 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -273,13 +273,14 @@ public class ModArith implements Deobfuscator reduce(); int i = 0; - for (Pair pair : pairs) + int start = 0, end = 32; // 24 32 ok + for (int j = start; j < end; ++j) + //for (Pair pair : pairs) { + Pair pair = pairs.get(j); Field field = pair.field; - System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter); - if (i > 0) // 2 - break; + System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter); Encryption encr = new Encryption(); encr.addPair(pair); From 7e9233a5d52af224d016d5f5cb93f00897fe081a Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 8 Sep 2015 15:46:29 -0400 Subject: [PATCH 11/58] Fix putfield pop order, runs on all fields it detects now. Don't know if it works. --- .../code/instructions/PutField.java | 2 +- .../deobfuscators/arithmetic/ModArith.java | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java index 3df0c55b03..13e2552d19 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java @@ -50,7 +50,7 @@ public class PutField extends Instruction implements SetFieldInstruction StackContext value = stack.pop(); StackContext object = stack.pop(); - ins.pop(object, value); + ins.pop(value, object); Encryption encryption = frame.getExecution().getEncryption(); net.runelite.deob.Field myField = getMyField(); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 526ccd31fd..d4826a987a 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -66,13 +66,16 @@ public class ModArith implements Deobfuscator int value = (int) pc.getConstant().getObject(); + if (value == 1 || value == 0) + continue; + constantGetters.put(field, value); } else if (ctx.getInstruction() instanceof SetFieldInstruction) { SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction(); - StackContext value = ctx.getPops().get(0); // what setfield pops as value + StackContext value = ctx.getPops().get(0); // the first thing poppe from both putfield and putstatic is the value if (!(value.getPushed().getInstruction() instanceof IMul)) continue; @@ -101,6 +104,9 @@ public class ModArith implements Deobfuscator int value2 = (int) pc.getConstant().getObject(); + if (value2 == 1 || value2 == 0) + continue; + constantSetters.put(field, value2); } } @@ -263,8 +269,17 @@ public class ModArith implements Deobfuscator public void run(ClassGroup group) { this.group = group; + while (runOnce() > 0); + } + + private int runOnce() + { group.buildClassGraph(); + pairs.clear(); + constantGetters.clear();; + constantSetters.clear(); + execution = new Execution(group); execution.populateInitialMethods(); execution.run(); @@ -273,7 +288,7 @@ public class ModArith implements Deobfuscator reduce(); int i = 0; - int start = 0, end = 32; // 24 32 ok + int start = 0, end = pairs.size(); // 0-64 ok for (int j = start; j < end; ++j) //for (Pair pair : pairs) { @@ -322,6 +337,7 @@ public class ModArith implements Deobfuscator // // Field f = group.findClass("class41").findField("field1170"); // calculate(f); + return i; } } From 9404e1d9afe7758e02f181ffd194bac3af82977f Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 8 Sep 2015 20:45:57 -0400 Subject: [PATCH 12/58] Carry encryption over in iadd and dup x1, this needs to be handled a better way. --- .../attributes/code/instructions/Dup_X1.java | 3 ++ .../attributes/code/instructions/IAdd.java | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java index 173f138e5b..defb3440de 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java @@ -29,16 +29,19 @@ public class Dup_X1 extends Instruction ins.pop(one, two); StackContext ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, two.getType()); + ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java index 286ff4e5c3..960d709e74 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java @@ -3,6 +3,9 @@ package net.runelite.deob.attributes.code.instructions; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.deobfuscators.arithmetic.DMath; +import net.runelite.deob.deobfuscators.arithmetic.Encryption; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; @@ -26,7 +29,52 @@ public class IAdd extends Instruction ins.pop(two, one); + Encryption encryption = frame.getExecution().getEncryption(); + int encKey = 0; + if (encryption != null) + { + if (one.encryption != 0) + { + assert two.encryption == 0; + + if (two.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); + int value = (int) pci.getConstant().getObject(); + + if (value != 0 && value != 1) + { + int o = value * one.encryption; + + encryption.change(pci, o); + } + } + + encKey = one.encryption; + } + else if (two.encryption != 0) + { + assert one.encryption == 0; + + if (one.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); + int value = (int) pci.getConstant().getObject(); + + if (value != 0 && value != 1) + { + int o = value * two.encryption; + + encryption.change(pci, o); + } + } + + encKey = two.encryption; + } + } + StackContext ctx = new StackContext(ins, int.class); + ctx.encryption = encKey; stack.push(ctx); ins.push(ctx); From 2cfba32e287dadd43675350e14552bf616bbde8a Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 9 Sep 2015 21:24:37 -0400 Subject: [PATCH 13/58] class172.java: this.field2982 = ((1 * this.field2963 & -65536) + this.field2982 * 1) * -402105799; not working. --- .../attributes/code/instructions/IMul.java | 6 + .../attributes/code/instructions/ISub.java | 47 ++++++++ .../deobfuscators/arithmetic/ModArith.java | 108 +++++++++--------- 3 files changed, 107 insertions(+), 54 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index 61955fb267..4e3028d8c9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -31,6 +31,7 @@ public class IMul extends Instruction ins.pop(one, two); Encryption encryption = frame.getExecution().getEncryption(); + int encKey = 0; if (encryption != null) { if (one.encryption != 0) @@ -52,9 +53,12 @@ public class IMul extends Instruction // { // System.out.println("decrr"); // } + encKey = one.encryption; } else if (two.encryption != 0) { + assert one.encryption == 0; + PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); int other = (int) pci.getConstant().getObject(); @@ -64,10 +68,12 @@ public class IMul extends Instruction encryption.change(pci, o); } + encKey = two.encryption; } } StackContext ctx = new StackContext(ins, int.class); + ctx.encryption = encKey; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java b/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java index 2b8519d509..1ad181a86c 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java @@ -3,6 +3,8 @@ package net.runelite.deob.attributes.code.instructions; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.deobfuscators.arithmetic.Encryption; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; @@ -26,7 +28,52 @@ public class ISub extends Instruction ins.pop(two, one); + Encryption encryption = frame.getExecution().getEncryption(); + int encKey = 0; + if (encryption != null) + { + if (one.encryption != 0) + { + assert two.encryption == 0; + + if (two.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); + int value = (int) pci.getConstant().getObject(); + + if (value != 0 && value != 1) + { + int o = value * one.encryption; + + encryption.change(pci, o); + } + } + + encKey = one.encryption; + } + else if (two.encryption != 0) + { + assert one.encryption == 0; + + if (one.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); + int value = (int) pci.getConstant().getObject(); + + if (value != 0 && value != 1) + { + int o = value * two.encryption; + + encryption.change(pci, o); + } + } + + encKey = two.encryption; + } + } + StackContext ctx = new StackContext(ins, int.class); + ctx.encryption = encKey; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index d4826a987a..1c777c0911 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -210,60 +210,60 @@ public class ModArith implements Deobfuscator // } } - private List getFieldsInExpression(InstructionContext ctx, List constants) - { - return check(ctx, new HashSet(), constants); - } - - private List check(InstructionContext context, Set visited, List constants) - { - List fields = new ArrayList<>(); - - if (visited.contains(context)) - return fields; - - visited.add(context); - - if (context.getInstruction() instanceof InvokeInstruction) - { - // field = func(field * constant), the output of the function isn't directly related to the result of field * constant - return fields; - } - - if (context.getInstruction() instanceof FieldInstruction) - { - FieldInstruction fi = (FieldInstruction) context.getInstruction(); - Field myf = fi.getMyField(); - if (myf != null) - fields.add(myf); - } - - if (context.getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) context.getInstruction(); - int i = (int) pci.getConstant().getObject(); - constants.add(i); - } - - for (StackContext ctx : context.getPops()) - { - InstructionContext i = ctx.getPushed(); - - fields.addAll(check(i, visited, constants)); - } - - for (StackContext ctx : context.getPushes()) - { - InstructionContext i = ctx.getPopped(); - - if (i == null) - continue; - - fields.addAll(check(i, visited, constants)); - } - - return fields; - } +// private List getFieldsInExpression(InstructionContext ctx, List constants) +// { +// return check(ctx, new HashSet(), constants); +// } +// +// private List check(InstructionContext context, Set visited, List constants) +// { +// List fields = new ArrayList<>(); +// +// if (visited.contains(context)) +// return fields; +// +// visited.add(context); +// +// if (context.getInstruction() instanceof InvokeInstruction) +// { +// // field = func(field * constant), the output of the function isn't directly related to the result of field * constant +// return fields; +// } +// +// if (context.getInstruction() instanceof FieldInstruction) +// { +// FieldInstruction fi = (FieldInstruction) context.getInstruction(); +// Field myf = fi.getMyField(); +// if (myf != null) +// fields.add(myf); +// } +// +// if (context.getInstruction() instanceof PushConstantInstruction) +// { +// PushConstantInstruction pci = (PushConstantInstruction) context.getInstruction(); +// int i = (int) pci.getConstant().getObject(); +// constants.add(i); +// } +// +// for (StackContext ctx : context.getPops()) +// { +// InstructionContext i = ctx.getPushed(); +// +// fields.addAll(check(i, visited, constants)); +// } +// +// for (StackContext ctx : context.getPushes()) +// { +// InstructionContext i = ctx.getPopped(); +// +// if (i == null) +// continue; +// +// fields.addAll(check(i, visited, constants)); +// } +// +// return fields; +// } @Override public void run(ClassGroup group) From c8d1ec9e259bdb425a4459630a64c4b143cd04c4 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 10 Sep 2015 14:17:47 -0400 Subject: [PATCH 14/58] After imul runs the value is no longer encrypted --- .../runelite/deob/attributes/code/instructions/IMul.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index 4e3028d8c9..a77292e9c8 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -48,12 +48,7 @@ public class IMul extends Instruction encryption.change(pci, o); } - -// if (one.encryption == other) -// { -// System.out.println("decrr"); -// } - encKey = one.encryption; + else encKey = one.encryption; } else if (two.encryption != 0) { @@ -68,7 +63,7 @@ public class IMul extends Instruction encryption.change(pci, o); } - encKey = two.encryption; + else encKey = two.encryption; } } From c5af568867449e5c161faf6ec47e4067100ed9da Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 10 Sep 2015 21:11:36 -0400 Subject: [PATCH 15/58] rename unique run --- src/main/java/net/runelite/deob/Deob.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index f892934373..80e82e0a9e 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -43,10 +43,7 @@ public class Deob ClassGroup group = loadJar(args[0]); -// bstart = System.currentTimeMillis(); -// new RenameUnique().run(group); -// bdur = System.currentTimeMillis() - bstart; -// System.out.println("rename unique took " + bdur/1000L + " seconds"); +// run(group, new RenameUnique()); // // remove except RuntimeException // run(group, new RuntimeExceptions()); @@ -89,8 +86,6 @@ public class Deob // // run(group, new UnusedClass()); -// new ModularArithmeticDeobfuscation().run(group); - new ModArith().run(group); saveJar(group, args[1]); From 5116d09fa0d74c5a80ba3d1e5e3dafc7abe4fbd2 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 11 Sep 2015 20:47:41 -0400 Subject: [PATCH 16/58] begin work on guessing --- .../deobfuscators/arithmetic/ModArith.java | 141 ++++++++++++------ .../arithmetic/OtherFieldException.java | 6 + 2 files changed, 98 insertions(+), 49 deletions(-) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/OtherFieldException.java diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 1c777c0911..f95a28441f 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -2,8 +2,10 @@ package net.runelite.deob.deobfuscators.arithmetic; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import net.runelite.deob.ClassFile; import net.runelite.deob.ClassGroup; @@ -16,10 +18,12 @@ import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.LDC_W; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.StackContext; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.MultiValueMap; /* @@ -33,6 +37,35 @@ public class ModArith implements Deobfuscator private MultiValueMap constantGetters = new MultiValueMap<>(), constantSetters = new MultiValueMap<>(); private List pairs = new ArrayList<>(); + + private List findAssocConstants(Field field, InstructionContext ctx) throws OtherFieldException + { + // starts with ctx = setfield + + List list = new ArrayList<>(); + + if (ctx.getInstruction() instanceof LDC_W) + { + LDC_W pci = (LDC_W) ctx.getInstruction(); + if (pci.getConstant().getObject() instanceof Integer) + list.add((int) pci.getConstant().getObject()); + } + + if (ctx.getInstruction() instanceof FieldInstruction) + { + FieldInstruction fi = (FieldInstruction) ctx.getInstruction(); + + if (fi.getMyField() != field) + throw new OtherFieldException(); + } + + for (StackContext sctx : ctx.getPops()) + { + list.addAll(findAssocConstants(field, sctx.getPushed())); + } + + return list; + } private void findUses() { @@ -75,6 +108,21 @@ public class ModArith implements Deobfuscator { SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction(); + Field field = sf.getMyField(); + if (field == null) + continue; + + List constants = null; +// try +// { +// constants = findAssocConstants(field, ctx); +// System.out.println(field.getName() + " " + constants); +// for (int i : constants) +// if (i != 1 && i != 0) +// constantSetters.put(field, i); +// } +// catch (OtherFieldException ex) { } + StackContext value = ctx.getPops().get(0); // the first thing poppe from both putfield and putstatic is the value if (!(value.getPushed().getInstruction() instanceof IMul)) continue; @@ -98,10 +146,6 @@ public class ModArith implements Deobfuscator if (pc == null) continue; - Field field = sf.getMyField(); - if (field == null) - continue; - int value2 = (int) pc.getConstant().getObject(); if (value2 == 1 || value2 == 0) @@ -171,6 +215,33 @@ public class ModArith implements Deobfuscator return p; } + private Pair guess(Collection getters) + { + Map map = CollectionUtils.getCardinalityMap(getters); + int max = Collections.max(map.values()); + int size = getters.size(); + + if (size < 50) + return null; + + if (((float) max / (float) size) < 0.9) + return null; + + for (final Map.Entry entry : map.entrySet()) { + if (max == entry.getValue()) { + int constant = entry.getKey(); + + Pair pair = new Pair(); + pair.getter = constant; + pair.setter = DMath.modInverse(constant); + return pair; + } + } + + assert false; + return null; + } + private void reduce() { for (ClassFile cf : group.getClasses()) @@ -179,35 +250,27 @@ public class ModArith implements Deobfuscator Collection getters = constantGetters.getCollection(f), setters = constantSetters.getCollection(f); + if (f.getName().equals("field605")) + { + int i =4; + } + if (getters == null || setters == null) continue; Pair answer = reduce(getters, setters); if (answer == null) - continue; + { + // answer = guess(getters); + if (answer == null) + continue; + + System.out.println("Guessing getter for " + f.getName() + " is " + answer.getter + " setter " + answer.setter); + } answer.field = f; pairs.add(answer); } -// MultiValueMap values = constants; -// constants = new MultiValueMap<>(); -// -// for (Field field : values.keySet()) -// { -// Collection col = values.getCollection(field); -// -// Map map = CollectionUtils.getCardinalityMap(col); -// int max = Collections.max(map.values()); -// -// for (final Map.Entry entry : map.entrySet()) { -// if (max == entry.getValue()) { -// int constant = entry.getKey(); -// -// constants.put(field, constant); -// break; -// } -// } -// } } // private List getFieldsInExpression(InstructionContext ctx, List constants) @@ -295,6 +358,11 @@ public class ModArith implements Deobfuscator Pair pair = pairs.get(j); Field field = pair.field; + if (!field.getName().equals("field2982") && !field.getName().equals("field2963")) + { + // continue; + } + System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter); Encryption encr = new Encryption(); @@ -312,31 +380,6 @@ public class ModArith implements Deobfuscator Encryption encr = new Encryption(); System.out.println(pairs); -// execution = new Execution(group); -// execution.populateInitialMethods(); -// -// Encryption encr = new Encryption(0); -// execution.setEncryption(encr); -// -// execution.run(); -// -// encr.doChange(); -// -// -// execution = new Execution(group); -// execution.populateInitialMethods(); -// -// encr = new Encryption(1); -// execution.setEncryption(encr); -// -// execution.run(); -// -// encr.doChange(); - -// findUses(); -// -// Field f = group.findClass("class41").findField("field1170"); -// calculate(f); return i; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/OtherFieldException.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/OtherFieldException.java new file mode 100644 index 0000000000..5591eb3d8c --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/OtherFieldException.java @@ -0,0 +1,6 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +class OtherFieldException extends Exception +{ + +} From 53234351f9dcda30e96a26428c5fcc444e4e8388 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 12 Sep 2015 13:53:13 -0400 Subject: [PATCH 17/58] the value is still decrypted if it is 1 or 0 since x*1=x and x*0=0 so this was wrong --- .../net/runelite/deob/attributes/code/instructions/IMul.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index a77292e9c8..a00009d5b4 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -48,7 +48,6 @@ public class IMul extends Instruction encryption.change(pci, o); } - else encKey = one.encryption; } else if (two.encryption != 0) { @@ -63,7 +62,6 @@ public class IMul extends Instruction encryption.change(pci, o); } - else encKey = two.encryption; } } From c4636872023b4c71c5a8eeba55fa35889650540c Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 12 Sep 2015 13:59:31 -0400 Subject: [PATCH 18/58] dupinstruction, and enc --- .../code/instruction/types/DupInstruction.java | 6 ++++++ .../deob/attributes/code/instructions/Dup.java | 8 +++++--- .../deob/attributes/code/instructions/Dup2.java | 10 +++++++--- .../deob/attributes/code/instructions/Dup2_X1.java | 11 ++++++++--- .../deob/attributes/code/instructions/Dup2_X2.java | 12 +++++++++--- .../deob/attributes/code/instructions/Dup_X1.java | 6 +++--- .../deob/attributes/code/instructions/Dup_X2.java | 10 +++++++--- 7 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java diff --git a/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java b/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java new file mode 100644 index 0000000000..6df5249512 --- /dev/null +++ b/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java @@ -0,0 +1,6 @@ +package net.runelite.deob.attributes.code.instruction.types; + +public interface DupInstruction +{ + +} diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java index 5c1743fae3..853f7ba849 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java @@ -1,5 +1,6 @@ package net.runelite.deob.attributes.code.instructions; +import java.io.IOException; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; @@ -7,10 +8,9 @@ import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; +import net.runelite.deob.attributes.code.instruction.types.DupInstruction; -import java.io.IOException; - -public class Dup extends Instruction +public class Dup extends Instruction implements DupInstruction { public Dup(Instructions instructions, InstructionType type, int pc) throws IOException { @@ -27,11 +27,13 @@ public class Dup extends Instruction ins.pop(obj); StackContext ctx = new StackContext(ins, obj.getType()); + ctx.encryption = obj.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, obj.getType()); + ctx.encryption = obj.encryption; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java index 7a0698ed8a..3f4e7578de 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java @@ -1,5 +1,6 @@ package net.runelite.deob.attributes.code.instructions; +import java.io.IOException; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; @@ -8,10 +9,9 @@ import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; import net.runelite.deob.execution.Type; +import net.runelite.deob.attributes.code.instruction.types.DupInstruction; -import java.io.IOException; - -public class Dup2 extends Instruction +public class Dup2 extends Instruction implements DupInstruction { public Dup2(Instructions instructions, InstructionType type, int pc) throws IOException { @@ -36,12 +36,14 @@ public class Dup2 extends Instruction if (two != null) { StackContext ctx = new StackContext(ins, two.getType()); + ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } StackContext ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(one); ins.push(ctx); @@ -49,12 +51,14 @@ public class Dup2 extends Instruction if (two != null) { ctx = new StackContext(ins, two.getType()); + ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(one); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java index b7dbfaacf9..ea1da1d658 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java @@ -1,5 +1,6 @@ package net.runelite.deob.attributes.code.instructions; +import java.io.IOException; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; @@ -8,10 +9,9 @@ import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; import net.runelite.deob.execution.Type; +import net.runelite.deob.attributes.code.instruction.types.DupInstruction; -import java.io.IOException; - -public class Dup2_X1 extends Instruction +public class Dup2_X1 extends Instruction implements DupInstruction { public Dup2_X1(Instructions instructions, InstructionType type, int pc) throws IOException { @@ -38,17 +38,20 @@ public class Dup2_X1 extends Instruction if (two != null) { StackContext ctx = new StackContext(ins, two.getType()); + ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } StackContext ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, three.getType()); + ctx.encryption = three.encryption; stack.push(ctx); ins.push(ctx); @@ -56,12 +59,14 @@ public class Dup2_X1 extends Instruction if (two != null) { ctx = new StackContext(ins, two.getType()); + ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java index 367e86885f..60553bd5f9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java @@ -1,5 +1,6 @@ package net.runelite.deob.attributes.code.instructions; +import java.io.IOException; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; @@ -8,10 +9,9 @@ import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; import net.runelite.deob.execution.Type; +import net.runelite.deob.attributes.code.instruction.types.DupInstruction; -import java.io.IOException; - -public class Dup2_X2 extends Instruction +public class Dup2_X2 extends Instruction implements DupInstruction { public Dup2_X2(Instructions instructions, InstructionType type, int pc) throws IOException { @@ -43,12 +43,14 @@ public class Dup2_X2 extends Instruction if (two != null) { StackContext ctx = new StackContext(ins, two.getType()); + ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } StackContext ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(one); ins.push(ctx); @@ -56,12 +58,14 @@ public class Dup2_X2 extends Instruction if (four != null) { ctx = new StackContext(ins, four.getType()); + ctx.encryption = four.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, three.getType()); + ctx.encryption = three.encryption; stack.push(one); ins.push(ctx); @@ -69,12 +73,14 @@ public class Dup2_X2 extends Instruction if (two != null) { ctx = new StackContext(ins, two.getType()); + ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(one); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java index defb3440de..3ee57b8797 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java @@ -1,5 +1,6 @@ package net.runelite.deob.attributes.code.instructions; +import java.io.IOException; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; @@ -7,10 +8,9 @@ import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; +import net.runelite.deob.attributes.code.instruction.types.DupInstruction; -import java.io.IOException; - -public class Dup_X1 extends Instruction +public class Dup_X1 extends Instruction implements DupInstruction { public Dup_X1(Instructions instructions, InstructionType type, int pc) throws IOException { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java index 55412a94a2..5df005d458 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java @@ -1,5 +1,6 @@ package net.runelite.deob.attributes.code.instructions; +import java.io.IOException; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; @@ -8,10 +9,9 @@ import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; import net.runelite.deob.execution.Type; +import net.runelite.deob.attributes.code.instruction.types.DupInstruction; -import java.io.IOException; - -public class Dup_X2 extends Instruction +public class Dup_X2 extends Instruction implements DupInstruction { public Dup_X2(Instructions instructions, InstructionType type, int pc) throws IOException { @@ -35,6 +35,7 @@ public class Dup_X2 extends Instruction ins.pop(three); StackContext ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); @@ -42,17 +43,20 @@ public class Dup_X2 extends Instruction if (three != null) { ctx = new StackContext(ins, three.getType()); + ctx.encryption = three.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, two.getType()); + ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, one.getType()); + ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); From a826ac3c4725bd8425e2dc2895733e5666d9e6f3 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 12 Sep 2015 22:15:37 -0400 Subject: [PATCH 19/58] some guessing, fix dup stuff via magic --- .../code/instructions/PutField.java | 3 +- .../code/instructions/PutStatic.java | 40 ++++++--- .../deobfuscators/arithmetic/ModArith.java | 89 +++---------------- 3 files changed, 42 insertions(+), 90 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java index 13e2552d19..e6f07617cd 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java @@ -16,6 +16,7 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.HashSet; import java.util.List; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import static net.runelite.deob.attributes.code.instructions.PutStatic.translate; @@ -58,7 +59,7 @@ public class PutField extends Instruction implements SetFieldInstruction { Pair pair = encryption.getField(myField); if (pair != null) - translate(encryption, pair, ins); + translate(encryption, pair, ins, new HashSet()); // XXX move translate() here // InstructionContext ctx = value.getPushed(); // if (ctx.getInstruction() instanceof IAdd && pair != null) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index c600f80fbb..08c44a7cb5 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -16,8 +16,9 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.List; -import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; +import java.util.HashSet; +import java.util.Set; +import net.runelite.deob.attributes.code.instruction.types.DupInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.deobfuscators.arithmetic.DMath; import net.runelite.deob.deobfuscators.arithmetic.Encryption; @@ -70,8 +71,13 @@ public class PutStatic extends Instruction implements SetFieldInstruction return null; } - protected static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx) + protected static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx, Set visited) { + if (visited.contains(ctx.getInstruction())) + return true; + + visited.add(ctx.getInstruction()); + if (ctx.getInstruction() instanceof LDC_W) { LDC_W pci = (LDC_W) ctx.getInstruction(); @@ -90,21 +96,17 @@ public class PutStatic extends Instruction implements SetFieldInstruction return true; } -// if (ctx.getInstruction() instanceof InvokeInstruction) -// return false; -// -// if (ctx.getInstruction() instanceof IDiv) -// return false; - boolean ok = ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub || ctx.getInstruction() instanceof IMul || - ctx.getInstruction() instanceof SetFieldInstruction; + ctx.getInstruction() instanceof SetFieldInstruction || + ctx.getInstruction() instanceof DupInstruction; if (!ok) return false; - boolean multipleBranches = ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub; + boolean multipleBranches = ctx.getInstruction() instanceof IAdd || + ctx.getInstruction() instanceof ISub; boolean retVal = false; encryption.begin(); @@ -113,7 +115,7 @@ public class PutStatic extends Instruction implements SetFieldInstruction { InstructionContext i = sctx.getPushed(); - if (translate(encryption, pair, i)) + if (translate(encryption, pair, i, visited)) { retVal = true; @@ -135,6 +137,18 @@ public class PutStatic extends Instruction implements SetFieldInstruction encryption.end(); + for (StackContext sctx : ctx.getPushes()) + { + InstructionContext i = sctx.getPopped(); + + if (i != null) + translate(encryption, pair, i, visited); // XXX? + else + // this hasn't been popped yet, so it hasn't been executed yet, + // so mark it as encrypted so that when it is executed, we will decrypt it + sctx.encryption = pair.getter; + } + return retVal; } @@ -153,7 +167,7 @@ public class PutStatic extends Instruction implements SetFieldInstruction { Pair pair = encryption.getField(myField); if (pair != null) - translate(encryption, pair, ins); + translate(encryption, pair, ins, new HashSet()); // InstructionContext ctx = object.getPushed(); // if (ctx.getInstruction() instanceof IAdd && pair != null) // { diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index f95a28441f..fd5b017150 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -113,15 +113,14 @@ public class ModArith implements Deobfuscator continue; List constants = null; -// try -// { -// constants = findAssocConstants(field, ctx); -// System.out.println(field.getName() + " " + constants); -// for (int i : constants) -// if (i != 1 && i != 0) -// constantSetters.put(field, i); -// } -// catch (OtherFieldException ex) { } + try + { + constants = findAssocConstants(field, ctx); + for (int i : constants) + if (i != 1 && i != 0) + constantSetters.put(field, i); + } + catch (OtherFieldException ex) { } StackContext value = ctx.getPops().get(0); // the first thing poppe from both putfield and putstatic is the value if (!(value.getPushed().getInstruction() instanceof IMul)) @@ -250,83 +249,21 @@ public class ModArith implements Deobfuscator Collection getters = constantGetters.getCollection(f), setters = constantSetters.getCollection(f); - if (f.getName().equals("field605")) - { - int i =4; - } - if (getters == null || setters == null) continue; Pair answer = reduce(getters, setters); if (answer == null) { - // answer = guess(getters); + answer = guess(getters); if (answer == null) continue; - - System.out.println("Guessing getter for " + f.getName() + " is " + answer.getter + " setter " + answer.setter); } answer.field = f; pairs.add(answer); } } - -// private List getFieldsInExpression(InstructionContext ctx, List constants) -// { -// return check(ctx, new HashSet(), constants); -// } -// -// private List check(InstructionContext context, Set visited, List constants) -// { -// List fields = new ArrayList<>(); -// -// if (visited.contains(context)) -// return fields; -// -// visited.add(context); -// -// if (context.getInstruction() instanceof InvokeInstruction) -// { -// // field = func(field * constant), the output of the function isn't directly related to the result of field * constant -// return fields; -// } -// -// if (context.getInstruction() instanceof FieldInstruction) -// { -// FieldInstruction fi = (FieldInstruction) context.getInstruction(); -// Field myf = fi.getMyField(); -// if (myf != null) -// fields.add(myf); -// } -// -// if (context.getInstruction() instanceof PushConstantInstruction) -// { -// PushConstantInstruction pci = (PushConstantInstruction) context.getInstruction(); -// int i = (int) pci.getConstant().getObject(); -// constants.add(i); -// } -// -// for (StackContext ctx : context.getPops()) -// { -// InstructionContext i = ctx.getPushed(); -// -// fields.addAll(check(i, visited, constants)); -// } -// -// for (StackContext ctx : context.getPushes()) -// { -// InstructionContext i = ctx.getPopped(); -// -// if (i == null) -// continue; -// -// fields.addAll(check(i, visited, constants)); -// } -// -// return fields; -// } @Override public void run(ClassGroup group) @@ -351,16 +288,16 @@ public class ModArith implements Deobfuscator reduce(); int i = 0; - int start = 0, end = pairs.size(); // 0-64 ok + int start = 0, end = pairs.size(); for (int j = start; j < end; ++j) //for (Pair pair : pairs) { Pair pair = pairs.get(j); Field field = pair.field; - - if (!field.getName().equals("field2982") && !field.getName().equals("field2963")) + + if (!field.getName().equals("field1980") && !field.getName().equals("field1961")) { - // continue; +// continue; } System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter); From 309595a09bd744d86f78d2e016253dc2e5a8e851 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 13 Sep 2015 19:37:44 -0400 Subject: [PATCH 20/58] instructions replace --- .../deob/attributes/code/Instructions.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/net/runelite/deob/attributes/code/Instructions.java b/src/main/java/net/runelite/deob/attributes/code/Instructions.java index f0803d1b1c..096bd8d791 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instructions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instructions.java @@ -241,4 +241,33 @@ public class Instructions for (Instruction i : instructions) i.renameMethod(oldMethod, newMethod); } + + public void replace(Instruction oldi, Instruction newi) + { + assert oldi != newi; + + assert oldi.getInstructions() == this; + assert newi.getInstructions() == this; + + assert instructions.contains(oldi); + assert !instructions.contains(newi); + + int i = instructions.indexOf(oldi); + instructions.remove(oldi); + instructions.add(i, newi); + + for (Instruction ins : oldi.from) + { + assert ins.jump.contains(oldi); + + ins.jump.remove(oldi); + ins.jump.add(newi); + + ins.replace(oldi, newi); + } + oldi.from.clear(); + + for (net.runelite.deob.attributes.code.Exception e : code.getExceptions().getExceptions()) + e.replace(oldi, newi); + } } From 98e3b7ec9e9bb6c4bca9ae9eac1566254acd0603 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 13 Sep 2015 19:38:36 -0400 Subject: [PATCH 21/58] setConstant --- .../code/instruction/types/PushConstantInstruction.java | 3 ++- .../deob/attributes/code/instructions/BiPush.java | 2 +- .../deob/attributes/code/instructions/DConst_0.java | 2 +- .../deob/attributes/code/instructions/DConst_1.java | 2 +- .../deob/attributes/code/instructions/FConst_0.java | 2 +- .../deob/attributes/code/instructions/FConst_1.java | 2 +- .../deob/attributes/code/instructions/FConst_2.java | 2 +- .../deob/attributes/code/instructions/IConst_0.java | 2 +- .../deob/attributes/code/instructions/IConst_1.java | 4 ++-- .../deob/attributes/code/instructions/IConst_2.java | 2 +- .../deob/attributes/code/instructions/IConst_3.java | 2 +- .../deob/attributes/code/instructions/IConst_4.java | 2 +- .../deob/attributes/code/instructions/IConst_5.java | 2 +- .../deob/attributes/code/instructions/IConst_M1.java | 2 +- .../deob/attributes/code/instructions/LConst_0.java | 2 +- .../deob/attributes/code/instructions/LConst_1.java | 2 +- .../deob/attributes/code/instructions/LDC2_W.java | 3 ++- .../deob/attributes/code/instructions/LDC_W.java | 3 ++- .../deob/attributes/code/instructions/SiPush.java | 2 +- .../deobfuscators/ModularArithmeticDeobfuscation.java | 9 ++++++--- 20 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instruction/types/PushConstantInstruction.java b/src/main/java/net/runelite/deob/attributes/code/instruction/types/PushConstantInstruction.java index 7aeda1f371..de451ab1fe 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instruction/types/PushConstantInstruction.java +++ b/src/main/java/net/runelite/deob/attributes/code/instruction/types/PushConstantInstruction.java @@ -1,10 +1,11 @@ package net.runelite.deob.attributes.code.instruction.types; +import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.pool.PoolEntry; public interface PushConstantInstruction { public PoolEntry getConstant(); - public void setConstant(PoolEntry entry); + public Instruction setConstant(PoolEntry entry); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/BiPush.java b/src/main/java/net/runelite/deob/attributes/code/instructions/BiPush.java index cb341e2bff..7207072db9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/BiPush.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/BiPush.java @@ -55,7 +55,7 @@ public class BiPush extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DConst_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DConst_0.java index 124752f07b..8075194ae9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DConst_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DConst_0.java @@ -40,7 +40,7 @@ public class DConst_0 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DConst_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DConst_1.java index 6404d7df51..5957255930 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DConst_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DConst_1.java @@ -40,7 +40,7 @@ public class DConst_1 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_0.java index afe0edde87..4ce94c86d3 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_0.java @@ -40,7 +40,7 @@ public class FConst_0 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_1.java index 6045c2a192..4f8837cd38 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_1.java @@ -40,7 +40,7 @@ public class FConst_1 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_2.java index e342d96609..ff5f51ca4e 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FConst_2.java @@ -40,7 +40,7 @@ public class FConst_2 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java index 268701a82f..0db3ebe004 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java @@ -40,7 +40,7 @@ public class IConst_0 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_1.java index ffaa661d0d..4d8e47a43b 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_1.java @@ -40,8 +40,8 @@ public class IConst_1 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return new LDC_W(this.getInstructions(), entry); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java index 29b5bea5d2..8461db8f82 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java @@ -40,7 +40,7 @@ public class IConst_2 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java index fb4b1d6464..2f44c072bc 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java @@ -40,7 +40,7 @@ public class IConst_3 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java index f548584ac9..b5d011f815 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java @@ -40,7 +40,7 @@ public class IConst_4 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java index 75d62b9fe8..c991de2308 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java @@ -40,7 +40,7 @@ public class IConst_5 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java index 8045437289..bdbafebf5f 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java @@ -40,7 +40,7 @@ public class IConst_M1 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LConst_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LConst_0.java index 7d55b1b7a1..2838b7690c 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LConst_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LConst_0.java @@ -40,7 +40,7 @@ public class LConst_0 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LConst_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LConst_1.java index 978d77f736..96823a9350 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LConst_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LConst_1.java @@ -40,7 +40,7 @@ public class LConst_1 extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC2_W.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC2_W.java index 2a6425eba9..cbc026db64 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC2_W.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC2_W.java @@ -55,8 +55,9 @@ public class LDC2_W extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { value = entry; + return this; } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java index a80c87e2c7..2b2e0d993a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java @@ -105,8 +105,9 @@ public class LDC_W extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { value = entry; + return this; } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/SiPush.java b/src/main/java/net/runelite/deob/attributes/code/instructions/SiPush.java index daa4055694..e86ffe9159 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/SiPush.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/SiPush.java @@ -55,7 +55,7 @@ public class SiPush extends Instruction implements PushConstantInstruction } @Override - public void setConstant(PoolEntry entry) + public Instruction setConstant(PoolEntry entry) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/deobfuscators/ModularArithmeticDeobfuscation.java b/src/main/java/net/runelite/deob/deobfuscators/ModularArithmeticDeobfuscation.java index f644ae9f7e..927fb5c13f 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/ModularArithmeticDeobfuscation.java +++ b/src/main/java/net/runelite/deob/deobfuscators/ModularArithmeticDeobfuscation.java @@ -747,7 +747,8 @@ public class ModularArithmeticDeobfuscation implements Deobfuscator //assert m.setter == modInverse(m.getter); int newConstant = constant * m.setter; - pc.setConstant(new net.runelite.deob.pool.Integer(newConstant)); + Instruction i2 = pc.setConstant(new net.runelite.deob.pool.Integer(newConstant)); + assert i2 == (Instruction) pc; if (newConstant != 1) System.out.println("new constant: " + newConstant); else @@ -775,7 +776,8 @@ public class ModularArithmeticDeobfuscation implements Deobfuscator // field = setter * value, solve for value by * modInverse(setter) int newConstant = constant * m.getter; - pi.setConstant(new net.runelite.deob.pool.Integer(newConstant)); + Instruction i2 = pi.setConstant(new net.runelite.deob.pool.Integer(newConstant)); + assert i2 == (Instruction) pi; ++replaced; } else if (value.getPushed().getInstruction() instanceof IMul) @@ -810,7 +812,8 @@ public class ModularArithmeticDeobfuscation implements Deobfuscator // field = expression * constant int newConstant = constant * m.getter; - pc.setConstant(new net.runelite.deob.pool.Integer(newConstant)); + Instruction i2 = pc.setConstant(new net.runelite.deob.pool.Integer(newConstant)); + assert i2 == (Instruction) pc; ++replaced; } } From 0b1d2be4a1d41b2ec02ce269ffeb30393ae00618 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 13 Sep 2015 19:40:08 -0400 Subject: [PATCH 22/58] still change if *1 --- .../net/runelite/deob/attributes/code/instructions/IMul.java | 4 ++-- .../runelite/deob/attributes/code/instructions/PutStatic.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index a00009d5b4..3350195244 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -42,7 +42,7 @@ public class IMul extends Instruction // 'one' is encrypted and we want to decrypt it by dividing by one.encryption - if (other != 1 && other != 0) + //if (other != 1 && other != 0) { int o = other * DMath.modInverse(one.encryption); @@ -56,7 +56,7 @@ public class IMul extends Instruction PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); int other = (int) pci.getConstant().getObject(); - if (other != 1 && other != 0) + //if (other != 1 && other != 0) { int o = other * DMath.modInverse(two.encryption); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index 08c44a7cb5..a769b4edd8 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -86,7 +86,7 @@ public class PutStatic extends Instruction implements SetFieldInstruction if (encryption.hasChange(pci)) return true; - if (value != 0 && value != 1) + //if (value != 0 && value != 1) { value = value * pair.getter; From 95b87c005c39f83910f4dd3cc8c8d14fcbf27f1c Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 13 Sep 2015 19:40:40 -0400 Subject: [PATCH 23/58] handle setConstant changing ins --- .../runelite/deob/deobfuscators/arithmetic/Encryption.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index 461b6e36f3..cc9f7dc65a 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -7,6 +7,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.Stack; import net.runelite.deob.Field; +import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; public class Encryption @@ -52,7 +53,11 @@ public class Encryption PushConstantInstruction pci = e.getKey(); int value = e.getValue(); - pci.setConstant(new net.runelite.deob.pool.Integer(value)); + Instruction oldi = (Instruction) pci; + Instruction newi = pci.setConstant(new net.runelite.deob.pool.Integer(value)); + + if (oldi != newi) + oldi.getInstructions().replace(oldi, newi); } } From 200a82bc83c2c96819b381d7574c4b94f212bbe6 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 13 Sep 2015 19:41:10 -0400 Subject: [PATCH 24/58] this inf loops and keeps changing the same last few fields back and forth etc.? --- .../deobfuscators/arithmetic/ModArith.java | 94 ++++++++++++++----- 1 file changed, 69 insertions(+), 25 deletions(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index fd5b017150..f023e19b54 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -37,6 +37,7 @@ public class ModArith implements Deobfuscator private MultiValueMap constantGetters = new MultiValueMap<>(), constantSetters = new MultiValueMap<>(); private List pairs = new ArrayList<>(); + private Set deobfuscatedFields = new HashSet<>(); private List findAssocConstants(Field field, InstructionContext ctx) throws OtherFieldException { @@ -54,8 +55,9 @@ public class ModArith implements Deobfuscator if (ctx.getInstruction() instanceof FieldInstruction) { FieldInstruction fi = (FieldInstruction) ctx.getInstruction(); - - if (fi.getMyField() != field) + + // if the field is already deobbed, constants here don't include it + if (fi.getMyField() != field && !deobfuscatedFields.contains(fi.getMyField())) throw new OtherFieldException(); } @@ -214,30 +216,58 @@ public class ModArith implements Deobfuscator return p; } - private Pair guess(Collection getters) + private Pair guess(Field field, Collection values, boolean getter) { - Map map = CollectionUtils.getCardinalityMap(getters); - int max = Collections.max(map.values()); - int size = getters.size(); + Map map = CollectionUtils.getCardinalityMap(values); // value -> how many times it occurs + int max = Collections.max(map.values()); // largest occurance # + int size = values.size(); - if (size < 50) - return null; +// if (max == size) +// { +// // all getters are the same value +// int constant = getters.iterator().next(); +// Pair pair = new Pair(); +// pair.getter = constant; +// System.out.println("Guessing " + field.getName() + " getter " + constant + " setter "); +// pair.setter = DMath.modInverse(constant); +// return pair; +// } +// +// if (size < 50) +// return null; - if (((float) max / (float) size) < 0.9) - return null; +// if (((float) max / (float) size) < 0.9) +// return null; for (final Map.Entry entry : map.entrySet()) { if (max == entry.getValue()) { int constant = entry.getKey(); + int inverse; + try + { + inverse = DMath.modInverse(constant); + } + catch (ArithmeticException ex) + { + break; + } Pair pair = new Pair(); - pair.getter = constant; - pair.setter = DMath.modInverse(constant); + if (getter) + { + pair.getter = constant; + pair.setter = inverse; + } + else + { + pair.getter = inverse; + pair.setter = constant; + } + return pair; } } - assert false; return null; } @@ -249,16 +279,24 @@ public class ModArith implements Deobfuscator Collection getters = constantGetters.getCollection(f), setters = constantSetters.getCollection(f); + if (f.getName().equals("field542")) + { + int i =5; + } + if (getters == null || setters == null) continue; Pair answer = reduce(getters, setters); + if (answer == null) - { - answer = guess(getters); - if (answer == null) - continue; - } + answer = guess(f, getters, true); + + if (answer == null) + answer = guess(f, setters, false); + + if (answer == null) + continue; answer.field = f; pairs.add(answer); @@ -269,7 +307,13 @@ public class ModArith implements Deobfuscator public void run(ClassGroup group) { this.group = group; - while (runOnce() > 0); + int passes = 0, total = 0, i; + while ((i = runOnce()) > 0) + { + ++passes; + total += i; + } + System.out.println("Finished arith deob on " + total + " fields in " + passes + " passes"); } private int runOnce() @@ -288,16 +332,13 @@ public class ModArith implements Deobfuscator reduce(); int i = 0; - int start = 0, end = pairs.size(); - for (int j = start; j < end; ++j) - //for (Pair pair : pairs) + for (Pair pair : pairs) { - Pair pair = pairs.get(j); Field field = pair.field; - if (!field.getName().equals("field1980") && !field.getName().equals("field1961")) + if (!field.getName().equals("field933") && !field.getName().equals("field743")) { -// continue; + // continue; } System.out.println("Processing " + field.getName() + " getter " + pair.getter + " setter " + pair.setter); @@ -311,7 +352,10 @@ public class ModArith implements Deobfuscator execution.run(); encr.doChange(); + System.out.println("Changed " + ++i); + //assert !deobfuscatedFields.contains(field); + deobfuscatedFields.add(field); } Encryption encr = new Encryption(); From 4d21fe7daf690c9a267937ec4f689a439a822e3b Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 19 Sep 2015 18:58:00 -0400 Subject: [PATCH 25/58] XXX confused. trying something new, by inserting * setter and * getter before/after put/set field --- .../attributes/code/instructions/IAdd.java | 17 ++- .../code/instructions/IConst_2.java | 2 +- .../code/instructions/IConst_3.java | 2 +- .../code/instructions/IConst_4.java | 2 +- .../code/instructions/IConst_5.java | 2 +- .../code/instructions/IConst_M1.java | 2 +- .../attributes/code/instructions/IMul.java | 17 ++- .../attributes/code/instructions/ISub.java | 14 +- .../code/instructions/PutField.java | 4 +- .../code/instructions/PutStatic.java | 58 +++++---- .../deobfuscators/arithmetic/Encryption.java | 12 +- .../deobfuscators/arithmetic/ModArith.java | 120 ++++++++++++++++-- .../net/runelite/deob/execution/Stack.java | 2 +- 13 files changed, 190 insertions(+), 64 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java index 960d709e74..b6ec7a2d11 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java @@ -42,15 +42,17 @@ public class IAdd extends Instruction PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); int value = (int) pci.getConstant().getObject(); - if (value != 0 && value != 1) + //if (value != 0 && value != 1) { int o = value * one.encryption; - encryption.change(pci, o); + encryption.change(pci, o, false); } + // field is no longer encrypted + encKey = 1; } - - encKey = one.encryption; + //else + // encKey = one.encryption; } else if (two.encryption != 0) { @@ -61,15 +63,16 @@ public class IAdd extends Instruction PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); int value = (int) pci.getConstant().getObject(); - if (value != 0 && value != 1) + //if (value != 0 && value != 1) { int o = value * two.encryption; - encryption.change(pci, o); + encryption.change(pci, o, false); } + encKey = 1; } - encKey = two.encryption; + //encKey = two.encryption; } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java index 8461db8f82..35db6fa314 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java @@ -42,6 +42,6 @@ public class IConst_2 extends Instruction implements PushConstantInstruction @Override public Instruction setConstant(PoolEntry entry) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return new LDC_W(this.getInstructions(), entry); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java index 2f44c072bc..aefb49894a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java @@ -42,6 +42,6 @@ public class IConst_3 extends Instruction implements PushConstantInstruction @Override public Instruction setConstant(PoolEntry entry) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return new LDC_W(this.getInstructions(), entry); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java index b5d011f815..e672610cb9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java @@ -42,6 +42,6 @@ public class IConst_4 extends Instruction implements PushConstantInstruction @Override public Instruction setConstant(PoolEntry entry) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return new LDC_W(this.getInstructions(), entry); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java index c991de2308..f071b901cf 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java @@ -42,6 +42,6 @@ public class IConst_5 extends Instruction implements PushConstantInstruction @Override public Instruction setConstant(PoolEntry entry) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return new LDC_W(this.getInstructions(), entry); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java index bdbafebf5f..e0eda969ce 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java @@ -42,6 +42,6 @@ public class IConst_M1 extends Instruction implements PushConstantInstruction @Override public Instruction setConstant(PoolEntry entry) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return new LDC_W(this.getInstructions(), entry); } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index 3350195244..d9c347ca83 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -18,6 +18,11 @@ public class IMul extends Instruction { super(instructions, type, pc); } + + public IMul(Instructions instructions) + { + super(instructions, InstructionType.IMUL, 0); + } @Override public void execute(Frame frame) @@ -42,12 +47,14 @@ public class IMul extends Instruction // 'one' is encrypted and we want to decrypt it by dividing by one.encryption - //if (other != 1 && other != 0) + if (other != 0) { int o = other * DMath.modInverse(one.encryption); - encryption.change(pci, o); + encryption.change(pci, o, false); } + + encKey = 1; } else if (two.encryption != 0) { @@ -56,12 +63,14 @@ public class IMul extends Instruction PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); int other = (int) pci.getConstant().getObject(); - //if (other != 1 && other != 0) + if (other != 0) { int o = other * DMath.modInverse(two.encryption); - encryption.change(pci, o); + encryption.change(pci, o, false); } + + encKey = 1; } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java b/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java index 1ad181a86c..a1c1b448f9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java @@ -41,15 +41,16 @@ public class ISub extends Instruction PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); int value = (int) pci.getConstant().getObject(); - if (value != 0 && value != 1) + //if (value != 0 && value != 1) { int o = value * one.encryption; - encryption.change(pci, o); + encryption.change(pci, o, false); } + encKey = 1; } - encKey = one.encryption; + // encKey = one.encryption; } else if (two.encryption != 0) { @@ -60,15 +61,16 @@ public class ISub extends Instruction PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); int value = (int) pci.getConstant().getObject(); - if (value != 0 && value != 1) + //if (value != 0 && value != 1) { int o = value * two.encryption; - encryption.change(pci, o); + encryption.change(pci, o, false); } + encKey = 1; } - encKey = two.encryption; + //encKey = two.encryption; } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java index e6f07617cd..89cd1c12e6 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java @@ -58,8 +58,8 @@ public class PutField extends Instruction implements SetFieldInstruction if (encryption != null && myField != null) { Pair pair = encryption.getField(myField); - if (pair != null) - translate(encryption, pair, ins, new HashSet()); + //if (pair != null) + // translate(encryption, pair, ins, new HashSet()); // XXX move translate() here // InstructionContext ctx = value.getPushed(); // if (ctx.getInstruction() instanceof IAdd && pair != null) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index a769b4edd8..c71ec51a10 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -71,29 +71,33 @@ public class PutStatic extends Instruction implements SetFieldInstruction return null; } - protected static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx, Set visited) + public static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx, Set visited) { if (visited.contains(ctx.getInstruction())) return true; visited.add(ctx.getInstruction()); - if (ctx.getInstruction() instanceof LDC_W) + if (ctx.getInstruction() instanceof PushConstantInstruction) { - LDC_W pci = (LDC_W) ctx.getInstruction(); - int value = (int) pci.getConstant().getObject(); + PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); - if (encryption.hasChange(pci)) - return true; - - //if (value != 0 && value != 1) + if (pci.getConstant().getObject() instanceof Integer) { - value = value * pair.getter; + int value = (int) pci.getConstant().getObject(); - encryption.change(pci, value); + if (encryption.hasChange(pci)) + return true; + + if (value != 0) + { + value = value * pair.getter; + + encryption.change(pci, value, true); + } + + return true; } - - return true; } boolean ok = ctx.getInstruction() instanceof IAdd || @@ -137,17 +141,21 @@ public class PutStatic extends Instruction implements SetFieldInstruction encryption.end(); - for (StackContext sctx : ctx.getPushes()) - { - InstructionContext i = sctx.getPopped(); - - if (i != null) - translate(encryption, pair, i, visited); // XXX? - else - // this hasn't been popped yet, so it hasn't been executed yet, - // so mark it as encrypted so that when it is executed, we will decrypt it - sctx.encryption = pair.getter; - } +// for (StackContext sctx : ctx.getPushes()) +// { +// InstructionContext i = sctx.getPopped(); +// +// if (i != null) +// { +// boolean b = translate(encryption, pair, i, visited); // XXX? +// //System.out.println("up translate res " + b); +// } +// else +// assert false; +// // this hasn't been popped yet, so it hasn't been executed yet, +// // so mark it as encrypted so that when it is executed, we will decrypt it +// //sctx.encryption = pair.getter; +// } return retVal; } @@ -166,8 +174,8 @@ public class PutStatic extends Instruction implements SetFieldInstruction if (encryption != null && myField != null) { Pair pair = encryption.getField(myField); - if (pair != null) - translate(encryption, pair, ins, new HashSet()); + //if (pair != null) + // translate(encryption, pair, ins, new HashSet()); // InstructionContext ctx = object.getPushed(); // if (ctx.getInstruction() instanceof IAdd && pair != null) // { diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index cc9f7dc65a..db58756b34 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -36,10 +36,18 @@ public class Encryption return changes.containsKey(pci); } - public void change(PushConstantInstruction pci, int value) + public void change(PushConstantInstruction pci, int value, boolean mul) { + //Integer i = changes.get(pci); assert !changes.containsKey(pci) || changes.get(pci) == value; - changes.put(pci, value); +// if (i == null) +// changes.put(pci, value); +// else if (mul) +// changes.put(pci, value * i); +// else + changes.put(pci, value); + // assert i == value; + if (stack.isEmpty()) return; PendingStack ps = stack.peek(); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index f023e19b54..bc52be249a 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -11,14 +11,17 @@ import net.runelite.deob.ClassFile; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; import net.runelite.deob.Field; +import net.runelite.deob.Method; +import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; -import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.LDC_W; +import net.runelite.deob.attributes.code.instructions.PutStatic; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; @@ -289,11 +292,11 @@ public class ModArith implements Deobfuscator Pair answer = reduce(getters, setters); - if (answer == null) - answer = guess(f, getters, true); + //if (answer == null) + // answer = guess(f, getters, true); - if (answer == null) - answer = guess(f, setters, false); + //if (answer == null) + // answer = guess(f, setters, false); if (answer == null) continue; @@ -307,6 +310,9 @@ public class ModArith implements Deobfuscator public void run(ClassGroup group) { this.group = group; + runOnce(); + if (true) return; + int passes = 0, total = 0, i; while ((i = runOnce()) > 0) { @@ -316,6 +322,79 @@ public class ModArith implements Deobfuscator System.out.println("Finished arith deob on " + total + " fields in " + passes + " passes"); } + private void translateSetFields(Execution e) + { + //Set visited = new HashSet<>(); + for (Frame f : e.processedFrames) + for (InstructionContext ins : f.getInstructions()) + if (ins.getInstruction() instanceof SetFieldInstruction) + { + SetFieldInstruction sfi = (SetFieldInstruction) ins.getInstruction(); + Pair pair = e.getEncryption().getField(sfi.getMyField()); + + if (pair != null) + PutStatic.translate(e.getEncryption(), pair, ins, new HashSet()); + // + } + } + + private void insertGetterSetterMuls(Encryption encr) + { + // after getfield insert imul * setter + // before setfield insert inul * getter + for (ClassFile cf : group.getClasses()) + for (Method m : cf.getMethods().getMethods()) + { + Code code = m.getCode(); + if (code == null) + continue; + + Instructions ins = code.getInstructions(); + List ilist = ins.getInstructions(); + + for (int i = 0; i < ilist.size(); ++i) + { + Instruction in = ilist.get(i); + + if (in instanceof SetFieldInstruction) + { + SetFieldInstruction sfi = (SetFieldInstruction) in; + Field f = sfi.getMyField(); + + if (f == null) + continue; + + Pair p = encr.getField(f); + if (p == null) + continue; + + // insert push getter + // insert imul + + ilist.add(i++, new LDC_W(ins, new net.runelite.deob.pool.Integer(p.getter))); + ilist.add(i++, new IMul(ins)); + } + else if (in instanceof GetFieldInstruction) + { + GetFieldInstruction sfi = (GetFieldInstruction) in; + Field f = sfi.getMyField(); + + if (f == null) + continue; + + Pair p = encr.getField(f); + if (p == null) + continue; + + // add after: push setter + // imul + ilist.add(++i, new LDC_W(ins, new net.runelite.deob.pool.Integer(p.setter))); + ilist.add(++i, new IMul(ins)); + } + } + } + } + private int runOnce() { group.buildClassGraph(); @@ -336,7 +415,10 @@ public class ModArith implements Deobfuscator { Field field = pair.field; - if (!field.getName().equals("field933") && !field.getName().equals("field743")) + //field933 = -193434591 * field743; + // var143.field3014 = (var143.field2960 = 1 * var92.field2960) * 1496783801; + //if (!field.getName().equals("field3014") && !field.getName().equals("field2960")) + if (!field.getName().equals("field2201")) { // continue; } @@ -346,19 +428,33 @@ public class ModArith implements Deobfuscator Encryption encr = new Encryption(); encr.addPair(pair); - execution = new Execution(group); - execution.populateInitialMethods(); - execution.setEncryption(encr); - execution.run(); + insertGetterSetterMuls(encr); +// +// execution = new Execution(group); +// execution.populateInitialMethods(); +// execution.setEncryption(encr); +// execution.run(); +// +// encr.doChange(); +// +// insertSetterMuls(encr); - encr.doChange(); +// execution = new Execution(group); +// execution.populateInitialMethods(); +// execution.run(); +// +// encr = new Encryption(); +// encr.addPair(pair); +// execution.setEncryption(encr); +// translateSetFields(execution); +// +// encr.doChange(); System.out.println("Changed " + ++i); //assert !deobfuscatedFields.contains(field); deobfuscatedFields.add(field); } - Encryption encr = new Encryption(); System.out.println(pairs); return i; diff --git a/src/main/java/net/runelite/deob/execution/Stack.java b/src/main/java/net/runelite/deob/execution/Stack.java index 0cde672b51..961d4725eb 100644 --- a/src/main/java/net/runelite/deob/execution/Stack.java +++ b/src/main/java/net/runelite/deob/execution/Stack.java @@ -9,7 +9,7 @@ public class Stack public Stack(int sz) { - stack = new StackContext[sz]; + stack = new StackContext[sz*2]; // XXX } protected Stack(Stack other) From ec86f0bee6eb487e511fa1066b0c422d9014a3ed Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 20 Sep 2015 13:40:59 -0400 Subject: [PATCH 26/58] Basic multi arith, need to rewrite --- src/main/java/net/runelite/deob/Deob.java | 5 ++++- .../java/net/runelite/deob/attributes/code/Instruction.java | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 80e82e0a9e..226e008c05 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -26,6 +26,7 @@ import net.runelite.deob.deobfuscators.UnusedFields; import net.runelite.deob.deobfuscators.UnusedMethods; import net.runelite.deob.deobfuscators.UnusedParameters; import net.runelite.deob.deobfuscators.arithmetic.ModArith; +import net.runelite.deob.deobfuscators.arithmetic.MultiplicationDeobfuscator; import net.runelite.deob.execution.Execution; //move static methods @@ -86,7 +87,9 @@ public class Deob // // run(group, new UnusedClass()); - new ModArith().run(group); + //new ModArith().run(group); + + new MultiplicationDeobfuscator().run(group); saveJar(group, args[1]); diff --git a/src/main/java/net/runelite/deob/attributes/code/Instruction.java b/src/main/java/net/runelite/deob/attributes/code/Instruction.java index 2027330f47..88299f60f2 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instruction.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instruction.java @@ -128,6 +128,9 @@ public abstract class Instruction } from.clear(); + for (Exception e : instructions.getCode().getExceptions().getExceptions()) + e.replace(this, next); + this.getInstructions().remove(this); // calls remove() return true; From 762c6ba54316e2a5d1bec0fa3473a4adc7232c62 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 20 Sep 2015 13:41:15 -0400 Subject: [PATCH 27/58] ahhhhhhhhhhhhhhhhhhhhhh --- .../MultiplicationDeobfuscator.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java new file mode 100644 index 0000000000..fc5c6a4735 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -0,0 +1,75 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import java.util.List; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Deobfuscator; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.LDC_W; +import net.runelite.deob.execution.Execution; +import net.runelite.deob.execution.Frame; +import net.runelite.deob.execution.InstructionContext; +import net.runelite.deob.execution.StackContext; + +public class MultiplicationDeobfuscator implements Deobfuscator +{ + private ClassGroup group; + + @Override + public void run(ClassGroup group) + { + this.group = group; + + int i; + while ((i = runOnce()) > 0) + System.out.println("Simplified " + i + " multiplication"); + } + + private int runOnce() + { + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + int count = 0; + + for (Frame frame : e.processedFrames) + for (InstructionContext ictx : frame.getInstructions()) + { + if (!(ictx.getInstruction() instanceof IMul)) + continue; + + Instructions ins = ictx.getInstruction().getInstructions(); + List ilist = ins.getInstructions(); + + if (!ilist.contains(ictx.getInstruction())) + continue; // already done + + StackContext one = ictx.getPops().get(0); + StackContext two = ictx.getPops().get(1); + + if (one.getPushed().getInstruction() instanceof PushConstantInstruction + && two.getPushed().getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci1 = (PushConstantInstruction) one.getPushed().getInstruction(), + pci2 = (PushConstantInstruction) two.getPushed().getInstruction(); + + int i1 = (int) pci1.getConstant().getObject(), + i2 = (int) pci2.getConstant().getObject(); + + int result = i1 * i2; + + ictx.removeStack(1); + ictx.removeStack(0); + + ins.replace(ictx.getInstruction(), new LDC_W(ins, new net.runelite.deob.pool.Integer(result))); + ++count; + } + } + + return count; + } + +} From 1b063d9e1277c7e4290c443446d9c4e46b7e235d Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 20 Sep 2015 14:29:11 -0400 Subject: [PATCH 28/58] save --- .../MultiplicationDeobfuscator.java | 65 +++++++++++-------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index fc5c6a4735..42a0c802f1 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -1,5 +1,6 @@ package net.runelite.deob.deobfuscators.arithmetic; +import java.util.ArrayList; import java.util.List; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; @@ -17,6 +18,8 @@ public class MultiplicationDeobfuscator implements Deobfuscator { private ClassGroup group; + // find a chain of multiplication instructions, evaluate and set one to the constant and the others to 1 + @Override public void run(ClassGroup group) { @@ -27,6 +30,16 @@ public class MultiplicationDeobfuscator implements Deobfuscator System.out.println("Simplified " + i + " multiplication"); } + private List getConstants(InstructionContext ctx) + { + List l = new ArrayList<>(); + + for (StackContext sctx : ctx.getPops()) + { + InstructionContext i = sctx.getPushed(); + } + } + private int runOnce() { Execution e = new Execution(group); @@ -41,32 +54,32 @@ public class MultiplicationDeobfuscator implements Deobfuscator if (!(ictx.getInstruction() instanceof IMul)) continue; - Instructions ins = ictx.getInstruction().getInstructions(); - List ilist = ins.getInstructions(); - - if (!ilist.contains(ictx.getInstruction())) - continue; // already done - - StackContext one = ictx.getPops().get(0); - StackContext two = ictx.getPops().get(1); - - if (one.getPushed().getInstruction() instanceof PushConstantInstruction - && two.getPushed().getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci1 = (PushConstantInstruction) one.getPushed().getInstruction(), - pci2 = (PushConstantInstruction) two.getPushed().getInstruction(); - - int i1 = (int) pci1.getConstant().getObject(), - i2 = (int) pci2.getConstant().getObject(); - - int result = i1 * i2; - - ictx.removeStack(1); - ictx.removeStack(0); - - ins.replace(ictx.getInstruction(), new LDC_W(ins, new net.runelite.deob.pool.Integer(result))); - ++count; - } +// Instructions ins = ictx.getInstruction().getInstructions(); +// List ilist = ins.getInstructions(); +// +// if (!ilist.contains(ictx.getInstruction())) +// continue; // already done +// +// StackContext one = ictx.getPops().get(0); +// StackContext two = ictx.getPops().get(1); +// +// if (one.getPushed().getInstruction() instanceof PushConstantInstruction +// && two.getPushed().getInstruction() instanceof PushConstantInstruction) +// { +// PushConstantInstruction pci1 = (PushConstantInstruction) one.getPushed().getInstruction(), +// pci2 = (PushConstantInstruction) two.getPushed().getInstruction(); +// +// int i1 = (int) pci1.getConstant().getObject(), +// i2 = (int) pci2.getConstant().getObject(); +// +// int result = i1 * i2; +// +// ictx.removeStack(1); +// ictx.removeStack(0); +// +// ins.replace(ictx.getInstruction(), new LDC_W(ins, new net.runelite.deob.pool.Integer(result))); +// ++count; +// } } return count; From f7edf29ebc5ee3c265f40bca5af686a79de80269 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 24 Sep 2015 17:37:55 -0400 Subject: [PATCH 29/58] mul simplifying for simple expressions --- .../code/instructions/IConst_0.java | 2 +- .../MultiplicationDeobfuscator.java | 68 ++++++++++++++++++- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java index 0db3ebe004..94f5817898 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java @@ -42,6 +42,6 @@ public class IConst_0 extends Instruction implements PushConstantInstruction @Override public Instruction setConstant(PoolEntry entry) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return new LDC_W(this.getInstructions(), entry); } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 42a0c802f1..09823f35b8 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -1,14 +1,15 @@ package net.runelite.deob.deobfuscators.arithmetic; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instructions.IMul; -import net.runelite.deob.attributes.code.instructions.LDC_W; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; @@ -27,17 +28,33 @@ public class MultiplicationDeobfuscator implements Deobfuscator int i; while ((i = runOnce()) > 0) - System.out.println("Simplified " + i + " multiplication"); + System.out.println("Replaced " + i + " constants"); } private List getConstants(InstructionContext ctx) { List l = new ArrayList<>(); + assert ctx.getInstruction() instanceof IMul; + for (StackContext sctx : ctx.getPops()) { InstructionContext i = sctx.getPushed(); + + if (i.getInstruction() instanceof IMul) + { + l.addAll(getConstants(i)); + } + else if (i.getInstruction() instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); + int value = (int) pci.getConstant().getObject(); + if (value != 1) // already been touched, otherwise we keep multiplying the same ins over and over + l.add(i); + } } + + return l; } private int runOnce() @@ -46,13 +63,58 @@ public class MultiplicationDeobfuscator implements Deobfuscator e.populateInitialMethods(); e.run(); + Set done = new HashSet<>(); int count = 0; for (Frame frame : e.processedFrames) + outer: for (InstructionContext ictx : frame.getInstructions()) { - if (!(ictx.getInstruction() instanceof IMul)) + Instruction instruction = ictx.getInstruction(); + Instructions instructions = instruction.getInstructions(); + + if (!(instruction instanceof IMul)) continue; + + List ins = getConstants(ictx); + + if (ins.size() == 1) + continue; + + for (InstructionContext i : ins) + { + if (done.contains(i.getInstruction())) + { + continue outer; + } + } + + int result = 1; + + // calculate result + for (InstructionContext i : ins) + { + PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); + int value = (int) pci.getConstant().getObject(); + + result *= value; + } + + // set result on ins + for (InstructionContext i : ins) + { + PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); + Instruction newIns = pci.setConstant(new net.runelite.deob.pool.Integer(result)); + ++count; + if (newIns != pci) + { + instructions.replace((Instruction) pci, newIns); + } + result = 1; // rest of the results go to 1 + } + + for (InstructionContext i : ins) + done.add(i.getInstruction()); // Instructions ins = ictx.getInstruction().getInstructions(); // List ilist = ins.getInstructions(); From ae8544cea1608f2ba2c5a36340ef54f4ea7f3d90 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Sep 2015 11:23:20 -0400 Subject: [PATCH 30/58] beginning work on removing *1 --- src/main/java/net/runelite/deob/Deob.java | 12 ++-- .../MultiplicationDeobfuscator.java | 27 -------- .../arithmetic/MultiplyOneDeobfuscator.java | 67 +++++++++++++++++++ 3 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 226e008c05..ffb367d10e 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -27,15 +27,9 @@ import net.runelite.deob.deobfuscators.UnusedMethods; import net.runelite.deob.deobfuscators.UnusedParameters; import net.runelite.deob.deobfuscators.arithmetic.ModArith; import net.runelite.deob.deobfuscators.arithmetic.MultiplicationDeobfuscator; +import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator; import net.runelite.deob.execution.Execution; -//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 @@ -89,7 +83,9 @@ public class Deob //new ModArith().run(group); - new MultiplicationDeobfuscator().run(group); + //new MultiplicationDeobfuscator().run(group); + + new MultiplyOneDeobfuscator().run(group); saveJar(group, args[1]); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 09823f35b8..aed381fe40 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -115,33 +115,6 @@ public class MultiplicationDeobfuscator implements Deobfuscator for (InstructionContext i : ins) done.add(i.getInstruction()); - -// Instructions ins = ictx.getInstruction().getInstructions(); -// List ilist = ins.getInstructions(); -// -// if (!ilist.contains(ictx.getInstruction())) -// continue; // already done -// -// StackContext one = ictx.getPops().get(0); -// StackContext two = ictx.getPops().get(1); -// -// if (one.getPushed().getInstruction() instanceof PushConstantInstruction -// && two.getPushed().getInstruction() instanceof PushConstantInstruction) -// { -// PushConstantInstruction pci1 = (PushConstantInstruction) one.getPushed().getInstruction(), -// pci2 = (PushConstantInstruction) two.getPushed().getInstruction(); -// -// int i1 = (int) pci1.getConstant().getObject(), -// i2 = (int) pci2.getConstant().getObject(); -// -// int result = i1 * i2; -// -// ictx.removeStack(1); -// ictx.removeStack(0); -// -// ins.replace(ictx.getInstruction(), new LDC_W(ins, new net.runelite.deob.pool.Integer(result))); -// ++count; -// } } return count; diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java new file mode 100644 index 0000000000..03f7d45f5d --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java @@ -0,0 +1,67 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import java.util.List; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Deobfuscator; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.execution.Execution; +import net.runelite.deob.execution.Frame; +import net.runelite.deob.execution.InstructionContext; +import net.runelite.deob.execution.StackContext; + +public class MultiplyOneDeobfuscator implements Deobfuscator +{ + @Override + public void run(ClassGroup group) + { + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + int count = 0; + + for (Frame frame : e.processedFrames) + for (InstructionContext ictx : frame.getInstructions()) + { + Instruction instruction = ictx.getInstruction(); + + if (!(instruction instanceof IMul)) + continue; + + Instructions ins = ictx.getInstruction().getInstructions(); + List ilist = ins.getInstructions(); + + if (!ilist.contains(ictx.getInstruction())) + continue; // already done + + StackContext one = ictx.getPops().get(0); + StackContext two = ictx.getPops().get(1); + + int removeIdx = -1; + if (one.getPushed().getInstruction() instanceof PushConstantInstruction + && (int) ((PushConstantInstruction) one.getPushed().getInstruction()).getConstant().getObject() == 1) + { + removeIdx = 0; + } + else if (two.getPushed().getInstruction() instanceof PushConstantInstruction + && (int) ((PushConstantInstruction) two.getPushed().getInstruction()).getConstant().getObject() == 1) + { + removeIdx = 1; + } + + if (removeIdx == -1) + continue; + + ictx.removeStack(removeIdx); + ins.remove(ictx.getInstruction()); + + ++count; + } + + System.out.println("Removed " + count + " multiplications"); + } + +} From 5be7604ee95d2220786f6f74963249e1467cddd4 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Sep 2015 12:40:47 -0400 Subject: [PATCH 31/58] IT GETS ME EVERY TIME --- src/main/java/net/runelite/deob/Deob.java | 5 +- .../deob/deobfuscators/UnreachedCode.java | 1 - .../MultiplicationDeobfuscator.java | 2 + .../arithmetic/MultiplyOneDeobfuscator.java | 4 +- .../arithmetic/MultiplyZeroDeobfuscator.java | 98 +++++++++++++++++++ 5 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyZeroDeobfuscator.java diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index ffb367d10e..d784ebc8bb 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -28,6 +28,7 @@ import net.runelite.deob.deobfuscators.UnusedParameters; import net.runelite.deob.deobfuscators.arithmetic.ModArith; import net.runelite.deob.deobfuscators.arithmetic.MultiplicationDeobfuscator; import net.runelite.deob.deobfuscators.arithmetic.MultiplyOneDeobfuscator; +import net.runelite.deob.deobfuscators.arithmetic.MultiplyZeroDeobfuscator; import net.runelite.deob.execution.Execution; public class Deob @@ -85,7 +86,9 @@ public class Deob //new MultiplicationDeobfuscator().run(group); - new MultiplyOneDeobfuscator().run(group); + //new MultiplyOneDeobfuscator().run(group); + + new MultiplyZeroDeobfuscator().run(group); saveJar(group, args[1]); diff --git a/src/main/java/net/runelite/deob/deobfuscators/UnreachedCode.java b/src/main/java/net/runelite/deob/deobfuscators/UnreachedCode.java index 7a603a2653..e7eb79b840 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/UnreachedCode.java +++ b/src/main/java/net/runelite/deob/deobfuscators/UnreachedCode.java @@ -22,7 +22,6 @@ public class UnreachedCode implements Deobfuscator List insCopy = new ArrayList<>(ins.getInstructions()); for (int j = 0; j < insCopy.size(); ++j) - //for (Instruction i : new ArrayList<>(ins.getInstructions())) { Instruction i = insCopy.get(j); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index aed381fe40..f228de9490 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -59,6 +59,8 @@ public class MultiplicationDeobfuscator implements Deobfuscator private int runOnce() { + group.buildClassGraph(); + Execution e = new Execution(group); e.populateInitialMethods(); e.run(); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java index 03f7d45f5d..dadd29970e 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java @@ -17,6 +17,8 @@ public class MultiplyOneDeobfuscator implements Deobfuscator @Override public void run(ClassGroup group) { + group.buildClassGraph(); + Execution e = new Execution(group); e.populateInitialMethods(); e.run(); @@ -61,7 +63,7 @@ public class MultiplyOneDeobfuscator implements Deobfuscator ++count; } - System.out.println("Removed " + count + " multiplications"); + System.out.println("Removed " + count + " 1 multiplications"); } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyZeroDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyZeroDeobfuscator.java new file mode 100644 index 0000000000..1e7df51d45 --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyZeroDeobfuscator.java @@ -0,0 +1,98 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import java.util.List; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Deobfuscator; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.LDC_W; +import net.runelite.deob.execution.Execution; +import net.runelite.deob.execution.Frame; +import net.runelite.deob.execution.InstructionContext; +import net.runelite.deob.execution.StackContext; + +public class MultiplyZeroDeobfuscator implements Deobfuscator +{ + @Override + public void run(ClassGroup group) + { + group.buildClassGraph(); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + int count = 0; + + for (Frame frame : e.processedFrames) + for (InstructionContext ictx : frame.getInstructions()) + { + Instruction instruction = ictx.getInstruction(); + Instructions ins = instruction.getInstructions(); + + if (frame.getMethod().getName().equals("method3678")) + //if (ins.getCode().getAttributes().getMethod().getName().equals("method3678")) + { + int i = 5; + } + + if (!(instruction instanceof IMul)) + continue; + + List ilist = ins.getInstructions(); + + StackContext one = ictx.getPops().get(0); + StackContext two = ictx.getPops().get(1); + + Instruction ione = one.getPushed().getInstruction(), + itwo = two.getPushed().getInstruction(); + + boolean remove = false; + if (ione instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) ione; + int value = (int) pci.getConstant().getObject(); + + if (value == 0) + remove = true; + if (value == -1408052237) + { + int i = 5; + } + } + if (itwo instanceof PushConstantInstruction) + { + PushConstantInstruction pci = (PushConstantInstruction) itwo; + int value = (int) pci.getConstant().getObject(); + + if (value == 0) + remove = true; + if (value == -1408052237) + { + int i = 5; + } + } + + if (remove == false) + { + continue; + } + + if (!ilist.contains(instruction)) + continue; // already done + + // remove both, remove imul, push 0 + + ictx.removeStack(1); + ictx.removeStack(0); + + ins.replace(instruction, new LDC_W(ins, new net.runelite.deob.pool.Integer(0))); + + ++count; + } + + System.out.println("Removed " + count + " 0 multiplications"); + } +} From 5cc12d0228186abd4322e7f22179fe63705a6152 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Sep 2015 14:17:15 -0400 Subject: [PATCH 32/58] More multi fixes. Spinning is back with multiplication deobfuscator.. --- src/main/java/net/runelite/deob/Deob.java | 4 ++-- .../MultiplicationDeobfuscator.java | 22 ++++++++++++++++++- .../arithmetic/MultiplyOneDeobfuscator.java | 4 +++- .../arithmetic/MultiplyZeroDeobfuscator.java | 14 ------------ 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index d784ebc8bb..f39768c3d4 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -84,9 +84,9 @@ public class Deob //new ModArith().run(group); - //new MultiplicationDeobfuscator().run(group); + //new MultiplicationDeobfuscator().run(group); // this causes spinning? - //new MultiplyOneDeobfuscator().run(group); + new MultiplyOneDeobfuscator().run(group); new MultiplyZeroDeobfuscator().run(group); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index f228de9490..15a865fee6 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -10,6 +10,7 @@ import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.SiPush; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; @@ -57,6 +58,21 @@ public class MultiplicationDeobfuscator implements Deobfuscator return l; } + private boolean isOnlyPath(Execution execution, Frame frame, InstructionContext ctx) + { + for (Frame f : execution.processedFrames) + if (f.getMethod() == frame.getMethod()) + for (InstructionContext i : f.getInstructions()) + if (i.getInstruction() == ctx.getInstruction()) + { + if (!i.equals(ctx)) + { + return false; + } + } + return true; + } + private int runOnce() { group.buildClassGraph(); @@ -77,7 +93,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator if (!(instruction instanceof IMul)) continue; - + List ins = getConstants(ictx); if (ins.size() == 1) @@ -91,6 +107,10 @@ public class MultiplicationDeobfuscator implements Deobfuscator } } + // there can only be one path to here, or else combinging would change code logic + if (!isOnlyPath(e, frame, ictx)) + continue; + int result = 1; // calculate result diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java index dadd29970e..f4bd559d39 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyOneDeobfuscator.java @@ -7,6 +7,7 @@ import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.NOP; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; @@ -58,7 +59,8 @@ public class MultiplyOneDeobfuscator implements Deobfuscator continue; ictx.removeStack(removeIdx); - ins.remove(ictx.getInstruction()); + ins.replace(ictx.getInstruction(), new NOP(ins)); + //ins.remove(ictx.getInstruction()); ++count; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyZeroDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyZeroDeobfuscator.java index 1e7df51d45..916640c935 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyZeroDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplyZeroDeobfuscator.java @@ -32,12 +32,6 @@ public class MultiplyZeroDeobfuscator implements Deobfuscator Instruction instruction = ictx.getInstruction(); Instructions ins = instruction.getInstructions(); - if (frame.getMethod().getName().equals("method3678")) - //if (ins.getCode().getAttributes().getMethod().getName().equals("method3678")) - { - int i = 5; - } - if (!(instruction instanceof IMul)) continue; @@ -57,10 +51,6 @@ public class MultiplyZeroDeobfuscator implements Deobfuscator if (value == 0) remove = true; - if (value == -1408052237) - { - int i = 5; - } } if (itwo instanceof PushConstantInstruction) { @@ -69,10 +59,6 @@ public class MultiplyZeroDeobfuscator implements Deobfuscator if (value == 0) remove = true; - if (value == -1408052237) - { - int i = 5; - } } if (remove == false) From 9a5d2c801fca6729c302ff6391adc2a6c49e0d4b Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 26 Sep 2015 19:31:07 -0400 Subject: [PATCH 33/58] Rewrite multi deob, this looks rather nice --- src/main/java/net/runelite/deob/Deob.java | 8 +- .../MultiplicationDeobfuscator.java | 242 ++++++++++++++---- .../arithmetic/MultiplicationExpression.java | 56 ++++ .../runelite/deob/execution/Execution.java | 6 + .../net/runelite/deob/execution/Frame.java | 4 + 5 files changed, 260 insertions(+), 56 deletions(-) create mode 100644 src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index f39768c3d4..9008a1ae50 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -84,11 +84,11 @@ public class Deob //new ModArith().run(group); - //new MultiplicationDeobfuscator().run(group); // this causes spinning? + new MultiplicationDeobfuscator().run(group); // this causes spinning? - new MultiplyOneDeobfuscator().run(group); - - new MultiplyZeroDeobfuscator().run(group); +// new MultiplyOneDeobfuscator().run(group); +// +// new MultiplyZeroDeobfuscator().run(group); saveJar(group, args[1]); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 15a865fee6..adad743964 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -1,15 +1,18 @@ package net.runelite.deob.deobfuscators.arithmetic; -import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.Set; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.attributes.code.instructions.BiPush; +import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.ISub; import net.runelite.deob.attributes.code.instructions.SiPush; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; @@ -28,42 +31,141 @@ public class MultiplicationDeobfuscator implements Deobfuscator this.group = group; int i; + int count = 0; while ((i = runOnce()) > 0) + { System.out.println("Replaced " + i + " constants"); + count += i; + } + System.out.println("Total changed " + count); } - private List getConstants(InstructionContext ctx) + private MultiplicationExpression parseExpression(InstructionContext ctx) + //private List getConstants(InstructionContext ctx) { - List l = new ArrayList<>(); + MultiplicationExpression me = new MultiplicationExpression(); - assert ctx.getInstruction() instanceof IMul; + //assert ctx.getInstruction() instanceof IMul; + + // + if (ctx.getInstruction() instanceof PushConstantInstruction) + { + if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush) + { + throw new IllegalStateException(); + } + +// PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); +// int value = (int) pci.getConstant().getObject(); +// +// if (value == 1) +// return null + + me.instructions.add(ctx); + return me; + } for (StackContext sctx : ctx.getPops()) { InstructionContext i = sctx.getPushed(); - if (i.getInstruction() instanceof IMul) + // if this instruction is imul, look at pops + if (ctx.getInstruction() instanceof IMul) { - l.addAll(getConstants(i)); + if (i.getInstruction() instanceof PushConstantInstruction) + { + if (i.getInstruction() instanceof BiPush || i.getInstruction() instanceof SiPush) + throw new IllegalStateException(); + + // a constant of imul + me.instructions.add(i); + } + else if (i.getInstruction() instanceof IMul) + { + // chained imul, append to me + try + { + MultiplicationExpression other = parseExpression(i); + + me.instructions.addAll(other.instructions); + me.subexpressions.addAll(other.subexpressions); + } + catch (IllegalStateException ex) + { + // this is ok? just don't include it? + } + } + else if (i.getInstruction() instanceof IAdd || i.getInstruction() instanceof ISub) + { + // imul using result of iadd or isub. evaluate expression + try + { + MultiplicationExpression other = parseExpression(i); + + // subexpr + //if (other != null) + me.subexpressions.add(other); + } + catch (IllegalStateException ex) + { + assert me.subexpressions.isEmpty(); + // subexpression is too complex. we can still simplify the top level though + } + } + else if (i.getInstruction() instanceof GetFieldInstruction) + { + // non constant, ignore + } + else + { + //throw new IllegalStateException(); + //System.out.println("imul pops something I don't know " + i.getInstruction()); + } } - else if (i.getInstruction() instanceof PushConstantInstruction) + // this is an iadd/sub + else if (ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub) { - PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); - int value = (int) pci.getConstant().getObject(); - if (value != 1) // already been touched, otherwise we keep multiplying the same ins over and over - l.add(i); + MultiplicationExpression other = parseExpression(i); // parse this side of the add/sub + + //if (other != null) + me.subexpressions.add(other); } + else + { + //throw new IllegalStateException(); + //System.out.println(ctx.getInstruction() + " pops something I dont know " + i.getInstruction()); + } +// else if (i.getInstruction() instanceof PushConstantInstruction) +// { +// me.instructions.add(i); +// //PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); +// //int value = (int) pci.getConstant().getObject(); +// //if (value != 1) // already been touched, otherwise we keep multiplying the same ins over and over +// // l.add(i); +// } +// else if (i.getInstruction() instanceof IAdd || i.getInstruction() instanceof ISub) +// { +// MultiplicationExpression other = parseExpression(i); +// +// me.subexpressions.add(other); +// } } - return l; + if (me.instructions.isEmpty() && me.subexpressions.isEmpty()) + throw new IllegalStateException(); + //return null; + + return me; } - private boolean isOnlyPath(Execution execution, Frame frame, InstructionContext ctx) + private boolean isOnlyPath(Execution execution, InstructionContext ctx) { - for (Frame f : execution.processedFrames) - if (f.getMethod() == frame.getMethod()) - for (InstructionContext i : f.getInstructions()) - if (i.getInstruction() == ctx.getInstruction()) + Collection ins = execution.getInstructonContexts(ctx.getInstruction()); + for (InstructionContext i : ins) + //for (Frame f : execution.processedFrames) + // if (f.getMethod() == frame.getMethod()) + // for (InstructionContext i : f.getInstructions()) + //if (i.getInstruction() == ctx.getInstruction()) { if (!i.equals(ctx)) { @@ -73,6 +175,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator return true; } + Set done = new HashSet<>(); private int runOnce() { group.buildClassGraph(); @@ -81,7 +184,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator e.populateInitialMethods(); e.run(); - Set done = new HashSet<>(); + int count = 0; for (Frame frame : e.processedFrames) @@ -91,52 +194,87 @@ public class MultiplicationDeobfuscator implements Deobfuscator Instruction instruction = ictx.getInstruction(); Instructions instructions = instruction.getInstructions(); +// if (!frame.getMethod().getMethods().getClassFile().getName().equals("class114")) +// continue; + if (!(instruction instanceof IMul)) continue; - List ins = getConstants(ictx); + MultiplicationExpression expression; + try + { + expression = parseExpression(ictx); + } + catch (IllegalStateException ex) + { + continue; + } - if (ins.size() == 1) + if (expression == null) continue; - for (InstructionContext i : ins) - { - if (done.contains(i.getInstruction())) - { - continue outer; - } - } + //if (expression.subexpressions.isEmpty()) + // continue; // there can only be one path to here, or else combinging would change code logic - if (!isOnlyPath(e, frame, ictx)) + if (!isOnlyPath(e, ictx)) continue; - int result = 1; + + if (done.contains(instruction)) + continue; + done.add(instruction); - // calculate result - for (InstructionContext i : ins) + count += expression.simplify(1); + if (MultiplicationExpression.replace) { - PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); - int value = (int) pci.getConstant().getObject(); - - result *= value; + MultiplicationExpression.replace = false; + return count; } - - // set result on ins - for (InstructionContext i : ins) - { - PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); - Instruction newIns = pci.setConstant(new net.runelite.deob.pool.Integer(result)); - ++count; - if (newIns != pci) - { - instructions.replace((Instruction) pci, newIns); - } - result = 1; // rest of the results go to 1 - } - - for (InstructionContext i : ins) - done.add(i.getInstruction()); + //break; +// List ins = getConstants(ictx); +// +// if (ins.size() == 1) +// continue; +// +// for (InstructionContext i : ins) +// { +// if (done.contains(i.getInstruction())) +// { +// continue outer; +// } +// } +// +// // there can only be one path to here, or else combinging would change code logic +// if (!isOnlyPath(e, frame, ictx)) +// continue; +// +// int result = 1; +// +// // calculate result +// for (InstructionContext i : ins) +// { +// PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); +// int value = (int) pci.getConstant().getObject(); +// +// result *= value; +// } +// +// // set result on ins +// for (InstructionContext i : ins) +// { +// PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); +// Instruction newIns = pci.setConstant(new net.runelite.deob.pool.Integer(result)); +// ++count; +// if (newIns != pci) +// { +// instructions.replace((Instruction) pci, newIns); +// } +// result = 1; // rest of the results go to 1 +// } +// +// for (InstructionContext i : ins) +// done.add(i.getInstruction()); } return count; diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java new file mode 100644 index 0000000000..31587ea53e --- /dev/null +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java @@ -0,0 +1,56 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import java.util.ArrayList; +import java.util.List; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; +import net.runelite.deob.execution.InstructionContext; + +public class MultiplicationExpression +{ + List instructions = new ArrayList<>(); // push constant instructions that are being multiplied + List subexpressions = new ArrayList<>(); // for distributing, each subexpr is * by this + static boolean replace; + + int simplify(int start) + { + int count = 0; + int result = start; + + // calculate result + for (InstructionContext i : instructions) + { + PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); + int value = (int) pci.getConstant().getObject(); + + result *= value; + } + + // multiply subexpressions by result + if (!subexpressions.isEmpty()) + { + for (MultiplicationExpression me : subexpressions) + { + count += me.simplify(result); + } + + result = 1; // constant has been distributed, outer numbers all go to 1 + } + + // set result on ins + for (InstructionContext i : instructions) + { + PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); + Instruction newIns = pci.setConstant(new net.runelite.deob.pool.Integer(result)); + ++count; + if (newIns != pci) + { + newIns.getInstructions().replace((Instruction) pci, newIns); + replace = true; + } + result = 1; // rest of the results go to 1 + } + + return count; + } +} diff --git a/src/main/java/net/runelite/deob/execution/Execution.java b/src/main/java/net/runelite/deob/execution/Execution.java index 716649bf2d..c920535e83 100644 --- a/src/main/java/net/runelite/deob/execution/Execution.java +++ b/src/main/java/net/runelite/deob/execution/Execution.java @@ -23,6 +23,7 @@ public class Execution public Set executed = new HashSet<>(); // executed instructions private MultiValueMap invokes = new MultiValueMap<>(); private Encryption encryption; + public MultiValueMap contexts = new MultiValueMap<>(); public Execution(ClassGroup group) { @@ -102,4 +103,9 @@ public class Execution System.out.println("Processed " + fcount + " frames"); } + + public Collection getInstructonContexts(Instruction i) + { + return contexts.getCollection(i); + } } diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index 9761555f08..ade776f508 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -174,6 +174,10 @@ public class Frame throw ex; } + InstructionContext ictx = this.instructions.get(this.instructions.size() - 1); + assert ictx.getInstruction() == oldCur; + execution.contexts.put(oldCur, ictx); + execution.executed.add(oldCur); processExceptions(oldCur); From 9efef8aa5914ec4da7b12f4a0e56f4d719c2490e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 26 Sep 2015 23:59:05 -0400 Subject: [PATCH 34/58] Make specific/generic to try and allow changing constants without having to change instructions --- .../deob/attributes/code/Instruction.java | 10 ++++++ .../deob/attributes/code/Instructions.java | 18 ++++++++++- .../code/instructions/IConst_0.java | 11 +++++++ .../code/instructions/IConst_1.java | 11 +++++++ .../code/instructions/IConst_2.java | 11 +++++++ .../code/instructions/IConst_3.java | 11 +++++++ .../code/instructions/IConst_4.java | 11 +++++++ .../code/instructions/IConst_5.java | 11 +++++++ .../code/instructions/IConst_M1.java | 5 +++ .../attributes/code/instructions/LDC_W.java | 31 +++++++++++++++++++ 10 files changed, 129 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/Instruction.java b/src/main/java/net/runelite/deob/attributes/code/Instruction.java index 88299f60f2..9db98de703 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instruction.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instruction.java @@ -228,4 +228,14 @@ public abstract class Instruction public void renameMethod(Method oldMethod, net.runelite.deob.pool.Method newMethod) { } + + public Instruction makeGeneric() + { + return this; + } + + public Instruction makeSpecific() + { + return this; + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/Instructions.java b/src/main/java/net/runelite/deob/attributes/code/Instructions.java index 096bd8d791..54df6cf832 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instructions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instructions.java @@ -43,8 +43,14 @@ public class Instructions { Constructor con = type.getInstructionClass().getConstructor(Instructions.class, InstructionType.class, int.class); Instruction ins = con.newInstance(this, type, pc); + Instruction genericIns = ins.makeGeneric(); + + if (genericIns != ins) + { + genericIns.setPc(ins.getPc()); + } - instructions.add(ins); + instructions.add(genericIns); int len = ins.getLength(); pc += len; @@ -168,6 +174,16 @@ public class Instructions public void write(DataOutputStream out) throws IOException { + // trnaslate instructions to specific + for (Instruction i : new ArrayList<>(instructions)) + { + Instruction specific = i.makeSpecific(); + if (i != specific) + { + replace(i, specific); + } + } + // generate pool indexes for (Instruction i : new ArrayList<>(instructions)) i.prime(); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java index 94f5817898..5a2e50663b 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_0.java @@ -18,6 +18,11 @@ public class IConst_0 extends Instruction implements PushConstantInstruction { super(instructions, type, pc); } + + public IConst_0(Instructions instructions) + { + super(instructions, InstructionType.ICONST_0, 0); + } @Override public void execute(Frame frame) @@ -44,4 +49,10 @@ public class IConst_0 extends Instruction implements PushConstantInstruction { return new LDC_W(this.getInstructions(), entry); } + + @Override + public Instruction makeGeneric() + { + return new LDC_W(this.getInstructions(), getConstant()); + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_1.java index 4d8e47a43b..57ee54e0ec 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_1.java @@ -18,6 +18,11 @@ public class IConst_1 extends Instruction implements PushConstantInstruction { super(instructions, type, pc); } + + public IConst_1(Instructions instructions) + { + super(instructions, InstructionType.ICONST_1, 0); + } @Override public void execute(Frame frame) @@ -44,4 +49,10 @@ public class IConst_1 extends Instruction implements PushConstantInstruction { return new LDC_W(this.getInstructions(), entry); } + + @Override + public Instruction makeGeneric() + { + return new LDC_W(this.getInstructions(), getConstant()); + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java index 35db6fa314..a51e1cc3ca 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java @@ -18,6 +18,11 @@ public class IConst_2 extends Instruction implements PushConstantInstruction { super(instructions, type, pc); } + + public IConst_2(Instructions instructions) + { + super(instructions, InstructionType.ICONST_2, 0); + } @Override public void execute(Frame frame) @@ -44,4 +49,10 @@ public class IConst_2 extends Instruction implements PushConstantInstruction { return new LDC_W(this.getInstructions(), entry); } + + @Override + public Instruction makeGeneric() + { + return new LDC_W(this.getInstructions(), getConstant()); + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java index aefb49894a..02af0586c6 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java @@ -18,6 +18,11 @@ public class IConst_3 extends Instruction implements PushConstantInstruction { super(instructions, type, pc); } + + public IConst_3(Instructions instructions) + { + super(instructions, InstructionType.ICONST_3, 0); + } @Override public void execute(Frame frame) @@ -44,4 +49,10 @@ public class IConst_3 extends Instruction implements PushConstantInstruction { return new LDC_W(this.getInstructions(), entry); } + + @Override + public Instruction makeGeneric() + { + return new LDC_W(this.getInstructions(), getConstant()); + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java index e672610cb9..815c0736e4 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_4.java @@ -18,6 +18,11 @@ public class IConst_4 extends Instruction implements PushConstantInstruction { super(instructions, type, pc); } + + public IConst_4(Instructions instructions) + { + super(instructions, InstructionType.ICONST_4, 0); + } @Override public void execute(Frame frame) @@ -44,4 +49,10 @@ public class IConst_4 extends Instruction implements PushConstantInstruction { return new LDC_W(this.getInstructions(), entry); } + + @Override + public Instruction makeGeneric() + { + return new LDC_W(this.getInstructions(), getConstant()); + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java index f071b901cf..416473bd8f 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_5.java @@ -18,6 +18,11 @@ public class IConst_5 extends Instruction implements PushConstantInstruction { super(instructions, type, pc); } + + public IConst_5(Instructions instructions) + { + super(instructions, InstructionType.ICONST_5, 0); + } @Override public void execute(Frame frame) @@ -44,4 +49,10 @@ public class IConst_5 extends Instruction implements PushConstantInstruction { return new LDC_W(this.getInstructions(), entry); } + + @Override + public Instruction makeGeneric() + { + return new LDC_W(this.getInstructions(), getConstant()); + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java index e0eda969ce..7e41464342 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java @@ -18,6 +18,11 @@ public class IConst_M1 extends Instruction implements PushConstantInstruction { super(instructions, type, pc); } + + public IConst_M1(Instructions instructions) + { + super(instructions, InstructionType.ICONST_M1, 0); + } @Override public void execute(Frame frame) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java index 2b2e0d993a..a358f84ae1 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java @@ -110,4 +110,35 @@ public class LDC_W extends Instruction implements PushConstantInstruction value = entry; return this; } + + @Override + public Instruction makeSpecific() + { + switch (value.getType()) + { + case INTEGER: + { + int i = (int) value.getObject(); + switch (i) + { + case -1: + return new IConst_M1(this.getInstructions()); + case 0: + return new IConst_0(this.getInstructions()); + case 1: + return new IConst_1(this.getInstructions()); + case 2: + return new IConst_2(this.getInstructions()); + case 3: + return new IConst_3(this.getInstructions()); + case 4: + return new IConst_4(this.getInstructions()); + case 5: + return new IConst_5(this.getInstructions()); + } + } + } + + return super.makeSpecific(); + } } From 812975d7dc87610ca2588e510be0cbbb3bd62b97 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 27 Sep 2015 17:32:32 -0400 Subject: [PATCH 35/58] I don't know if this is right but can decompile 2201 okay --- .../instruction/types/DupInstruction.java | 6 +- .../attributes/code/instructions/Dup.java | 25 +++++++ .../attributes/code/instructions/Dup2.java | 12 ++++ .../attributes/code/instructions/Dup2_X1.java | 12 ++++ .../attributes/code/instructions/Dup2_X2.java | 12 ++++ .../attributes/code/instructions/Dup_X1.java | 54 ++++++++++++++ .../attributes/code/instructions/Dup_X2.java | 12 ++++ .../deobfuscators/arithmetic/ModArith.java | 10 +-- .../MultiplicationDeobfuscator.java | 72 +++++++++++++++---- .../arithmetic/MultiplicationExpression.java | 11 +++ 10 files changed, 207 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java b/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java index 6df5249512..4b3adb6d80 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java +++ b/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java @@ -1,6 +1,10 @@ package net.runelite.deob.attributes.code.instruction.types; +import net.runelite.deob.execution.StackContext; + public interface DupInstruction { - + public StackContext resolve(StackContext sctx); + + public StackContext getOtherBranch(StackContext sctx); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java index 853f7ba849..5a4cc85d6f 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java @@ -1,6 +1,7 @@ package net.runelite.deob.attributes.code.instructions; import java.io.IOException; +import java.util.List; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.InstructionType; import net.runelite.deob.attributes.code.Instructions; @@ -57,4 +58,28 @@ public class Dup extends Instruction implements DupInstruction // an unused new/invokesepcial return false; } + + @Override + public StackContext resolve(StackContext sctx) + { + // ctx = stack pushed by this instruction, return stack popped by this instruction + InstructionContext ctx = sctx.getPushed(); + assert ctx.getInstruction() == this; + return ctx.getPops().get(0); + } + + @Override + public StackContext getOtherBranch(StackContext sctx) + { + InstructionContext ctx = sctx.getPushed(); + assert ctx.getInstruction() == this; + + List pushes = ctx.getPushes(); + assert pushes.contains(sctx); + + int idx = pushes.indexOf(sctx); + assert idx == 0 || idx == 1; + + return pushes.get(~idx & 1); + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java index 3f4e7578de..d34b9abdda 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java @@ -71,4 +71,16 @@ public class Dup2 extends Instruction implements DupInstruction { throw new UnsupportedOperationException(); } + + @Override + public StackContext resolve(StackContext ctx) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public StackContext getOtherBranch(StackContext sctx) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java index ea1da1d658..3173636251 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java @@ -79,4 +79,16 @@ public class Dup2_X1 extends Instruction implements DupInstruction { throw new UnsupportedOperationException(); } + + @Override + public StackContext resolve(StackContext ctx) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public StackContext getOtherBranch(StackContext sctx) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java index 60553bd5f9..2bca24412f 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java @@ -93,4 +93,16 @@ public class Dup2_X2 extends Instruction implements DupInstruction { throw new UnsupportedOperationException(); } + + @Override + public StackContext resolve(StackContext ctx) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public StackContext getOtherBranch(StackContext sctx) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java index 3ee57b8797..dca4875579 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java @@ -54,4 +54,58 @@ public class Dup_X1 extends Instruction implements DupInstruction { throw new UnsupportedOperationException(); } + + @Override + public StackContext resolve(StackContext sctx) + { + // ctx = stack pushed by this instruction, return stack popped by this instruction + InstructionContext ctx = sctx.getPushed(); + assert ctx.getInstruction() == this; + + assert ctx.getPushes().contains(sctx); + int pushedIndex = ctx.getPushes().indexOf(sctx); + int poppedIndex; + + // 2 1 -> 1 2 1 + // index 0 is 0, index 1 is 1, index 2 is 2 + + switch (pushedIndex) + { + case 0: + case 2: + poppedIndex = 0; + break; + case 1: + poppedIndex = 1; + break; + default: + throw new IllegalStateException(); + } + + // get popped ctx + return ctx.getPops().get(poppedIndex); + } + + @Override + public StackContext getOtherBranch(StackContext sctx) + { + // sctx = stack pushed by this instruction, return the other branch + InstructionContext ctx = sctx.getPushed(); + assert ctx.getInstruction() == this; + + assert ctx.getPushes().contains(sctx); + int pushedIndex = ctx.getPushes().indexOf(sctx); + + // 2 1 -> 1 2 1 + + // if pushed index is 0 or 2, return other, if 1 there is no other side + assert pushedIndex >= 0 && pushedIndex <= 2; + + if (pushedIndex == 0) + return ctx.getPushes().get(2); + else if (pushedIndex == 2) + return ctx.getPushes().get(0); + + return null; + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java index 5df005d458..623760fad3 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java @@ -69,4 +69,16 @@ public class Dup_X2 extends Instruction implements DupInstruction { throw new UnsupportedOperationException(); } + + @Override + public StackContext resolve(StackContext ctx) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public StackContext getOtherBranch(StackContext sctx) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index bc52be249a..77fd0b938c 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -292,11 +292,11 @@ public class ModArith implements Deobfuscator Pair answer = reduce(getters, setters); - //if (answer == null) - // answer = guess(f, getters, true); - - //if (answer == null) - // answer = guess(f, setters, false); +// if (answer == null) +// answer = guess(f, getters, true); +// +// if (answer == null) +// answer = guess(f, setters, false); if (answer == null) continue; diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index adad743964..5878c505f3 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -7,12 +7,16 @@ import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instruction.types.DupInstruction; import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instructions.BiPush; +import net.runelite.deob.attributes.code.instructions.Dup; +import net.runelite.deob.attributes.code.instructions.Dup_X1; import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.ISub; +import net.runelite.deob.attributes.code.instructions.LDC_W; import net.runelite.deob.attributes.code.instructions.SiPush; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; @@ -23,8 +27,6 @@ public class MultiplicationDeobfuscator implements Deobfuscator { private ClassGroup group; - // find a chain of multiplication instructions, evaluate and set one to the constant and the others to 1 - @Override public void run(ClassGroup group) { @@ -41,25 +43,17 @@ public class MultiplicationDeobfuscator implements Deobfuscator } private MultiplicationExpression parseExpression(InstructionContext ctx) - //private List getConstants(InstructionContext ctx) { MultiplicationExpression me = new MultiplicationExpression(); - //assert ctx.getInstruction() instanceof IMul; + assert !(ctx.getInstruction() instanceof DupInstruction); - // if (ctx.getInstruction() instanceof PushConstantInstruction) { if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush) { throw new IllegalStateException(); } - -// PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); -// int value = (int) pci.getConstant().getObject(); -// -// if (value == 1) -// return null me.instructions.add(ctx); return me; @@ -69,6 +63,18 @@ public class MultiplicationDeobfuscator implements Deobfuscator { InstructionContext i = sctx.getPushed(); +// int count2 = 0; +// while (i.getInstruction() instanceof DupInstruction) +// { +// DupInstruction dup = (DupInstruction) i.getInstruction(); +// sctx = dup.resolve(sctx); +// i = sctx.getPushed(); +// +// ++count2; +// assert count2 < 10; +// //assert !(i.getInstruction() instanceof DupInstruction); +// } + // if this instruction is imul, look at pops if (ctx.getInstruction() instanceof IMul) { @@ -112,6 +118,44 @@ public class MultiplicationDeobfuscator implements Deobfuscator // subexpression is too complex. we can still simplify the top level though } } + else if (i.getInstruction() instanceof DupInstruction) + { + DupInstruction dup = (DupInstruction) i.getInstruction(); + + if (dup instanceof Dup || dup instanceof Dup_X1) + { + + // find other branch of the dup instruction + // sctx = what dup pushed, find other + StackContext otherCtx = dup.getOtherBranch(sctx); // other side of dup + InstructionContext otherCtxI = otherCtx.getPopped(); // would insert imul here? + + if (otherCtxI.getInstruction() instanceof IMul) + { + //assert otherCtxI.getInstruction() instanceof IMul; + + InstructionContext pushConstant = otherCtxI.getPops().get(0).getPushed(); + assert pushConstant.getInstruction() instanceof LDC_W; + + me.dupmagic = pushConstant; + + StackContext orig = dup.resolve(sctx); // original + try + { + MultiplicationExpression other = parseExpression(orig.getPushed()); + me.subexpressions.add(other); + } + catch (IllegalStateException ex) + { + assert me.subexpressions.isEmpty(); + } + } + else + { + System.out.println("dup ins " + i); + } + } + } else if (i.getInstruction() instanceof GetFieldInstruction) { // non constant, ignore @@ -175,7 +219,8 @@ public class MultiplicationDeobfuscator implements Deobfuscator return true; } - Set done = new HashSet<>(); + private Set done = new HashSet<>(); + private int runOnce() { group.buildClassGraph(); @@ -194,7 +239,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator Instruction instruction = ictx.getInstruction(); Instructions instructions = instruction.getInstructions(); -// if (!frame.getMethod().getMethods().getClassFile().getName().equals("class114")) +// if (!frame.getMethod().getMethods().getClassFile().getName().equals("class118")) // continue; if (!(instruction instanceof IMul)) @@ -228,6 +273,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator count += expression.simplify(1); if (MultiplicationExpression.replace) { + assert false; MultiplicationExpression.replace = false; return count; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java index 31587ea53e..9896b7e0c3 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java @@ -10,6 +10,7 @@ public class MultiplicationExpression { List instructions = new ArrayList<>(); // push constant instructions that are being multiplied List subexpressions = new ArrayList<>(); // for distributing, each subexpr is * by this + InstructionContext dupmagic; // inverse of what is distributed to subexpressions gets set here static boolean replace; int simplify(int start) @@ -34,6 +35,16 @@ public class MultiplicationExpression count += me.simplify(result); } + if (dupmagic != null) + { + PushConstantInstruction pci = (PushConstantInstruction) dupmagic.getInstruction(); + int value = (int) pci.getConstant().getObject(); + + value *= DMath.modInverse(result); + + pci.setConstant(new net.runelite.deob.pool.Integer(value)); + } + result = 1; // constant has been distributed, outer numbers all go to 1 } From d43dc0451997c27457f8b5e23b85eee1ad2d1b13 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 27 Sep 2015 21:26:05 -0400 Subject: [PATCH 36/58] something is wrong somewhere but I don't see anything --- .../instruction/types/DupInstruction.java | 2 +- .../attributes/code/instructions/Dup.java | 2 +- .../attributes/code/instructions/Dup2.java | 2 +- .../attributes/code/instructions/Dup2_X1.java | 2 +- .../attributes/code/instructions/Dup2_X2.java | 2 +- .../attributes/code/instructions/Dup_X1.java | 2 +- .../attributes/code/instructions/Dup_X2.java | 43 +++++++++++++++++-- .../MultiplicationDeobfuscator.java | 8 ++-- 8 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java b/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java index 4b3adb6d80..b9fd1a5c83 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java +++ b/src/main/java/net/runelite/deob/attributes/code/instruction/types/DupInstruction.java @@ -4,7 +4,7 @@ import net.runelite.deob.execution.StackContext; public interface DupInstruction { - public StackContext resolve(StackContext sctx); + public StackContext getOriginal(StackContext sctx); public StackContext getOtherBranch(StackContext sctx); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java index 5a4cc85d6f..5b98e3419b 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java @@ -60,7 +60,7 @@ public class Dup extends Instruction implements DupInstruction } @Override - public StackContext resolve(StackContext sctx) + public StackContext getOriginal(StackContext sctx) { // ctx = stack pushed by this instruction, return stack popped by this instruction InstructionContext ctx = sctx.getPushed(); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java index d34b9abdda..f7237716d1 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java @@ -73,7 +73,7 @@ public class Dup2 extends Instruction implements DupInstruction } @Override - public StackContext resolve(StackContext ctx) + public StackContext getOriginal(StackContext ctx) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java index 3173636251..30672b0374 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java @@ -81,7 +81,7 @@ public class Dup2_X1 extends Instruction implements DupInstruction } @Override - public StackContext resolve(StackContext ctx) + public StackContext getOriginal(StackContext ctx) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java index 2bca24412f..ffa13fecc7 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java @@ -95,7 +95,7 @@ public class Dup2_X2 extends Instruction implements DupInstruction } @Override - public StackContext resolve(StackContext ctx) + public StackContext getOriginal(StackContext ctx) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java index dca4875579..7c26c66d76 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java @@ -56,7 +56,7 @@ public class Dup_X1 extends Instruction implements DupInstruction } @Override - public StackContext resolve(StackContext sctx) + public StackContext getOriginal(StackContext sctx) { // ctx = stack pushed by this instruction, return stack popped by this instruction InstructionContext ctx = sctx.getPushed(); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java index 623760fad3..df3c12f98a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java @@ -71,14 +71,51 @@ public class Dup_X2 extends Instruction implements DupInstruction } @Override - public StackContext resolve(StackContext ctx) + public StackContext getOriginal(StackContext sctx) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + // 3 2 1 -> 1 3 2 1 + InstructionContext ctx = sctx.getPushed(); + assert ctx.getInstruction() == this; + + assert ctx.getPushes().contains(sctx); + int pushedIndex = ctx.getPushes().indexOf(sctx); + int poppedIndex; + + switch (pushedIndex) + { + case 0: + case 3: + poppedIndex = 0; + break; + case 1: + poppedIndex = 2; + break; + case 2: + poppedIndex = 1; + default: + throw new IllegalStateException(); + } + + return ctx.getPops().get(poppedIndex); } @Override public StackContext getOtherBranch(StackContext sctx) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + // sctx = stack pushed by this instruction, return the other branch + InstructionContext ctx = sctx.getPushed(); + assert ctx.getInstruction() == this; + + assert ctx.getPushes().contains(sctx); + int pushedIndex = ctx.getPushes().indexOf(sctx); + + // 3 2 1 -> 1 3 2 1 + + if (pushedIndex == 0) + return ctx.getPushes().get(3); + else if (pushedIndex == 3) + return ctx.getPushes().get(0); + + return null; } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 5878c505f3..55cb4cd775 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -120,9 +120,10 @@ public class MultiplicationDeobfuscator implements Deobfuscator } else if (i.getInstruction() instanceof DupInstruction) { + if(true) throw new IllegalStateException(); DupInstruction dup = (DupInstruction) i.getInstruction(); - if (dup instanceof Dup || dup instanceof Dup_X1) + //if (dup instanceof Dup || dup instanceof Dup_X1) { // find other branch of the dup instruction @@ -139,7 +140,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator me.dupmagic = pushConstant; - StackContext orig = dup.resolve(sctx); // original + StackContext orig = dup.getOriginal(sctx); // original try { MultiplicationExpression other = parseExpression(orig.getPushed()); @@ -152,7 +153,8 @@ public class MultiplicationDeobfuscator implements Deobfuscator } else { - System.out.println("dup ins " + i); + System.out.println("dup ins " + otherCtxI.getInstruction()); + throw new IllegalStateException(); } } } From d61d006b34c106c2ed9265e83f7726ddc0e8b08d Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 30 Sep 2015 20:39:35 -0400 Subject: [PATCH 37/58] Fix some of the dup stuff, works a little better? --- .../attributes/code/instructions/Dup.java | 1 + .../MultiplicationDeobfuscator.java | 9 +++- .../arithmetic/MultiplicationExpression.java | 47 +++++++++++++++---- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java index 5b98e3419b..2a984d6a44 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java @@ -65,6 +65,7 @@ public class Dup extends Instruction implements DupInstruction // ctx = stack pushed by this instruction, return stack popped by this instruction InstructionContext ctx = sctx.getPushed(); assert ctx.getInstruction() == this; + assert ctx.getPushes().contains(sctx); return ctx.getPops().get(0); } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 55cb4cd775..e334bab948 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -120,7 +120,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator } else if (i.getInstruction() instanceof DupInstruction) { - if(true) throw new IllegalStateException(); + //if(true) throw new IllegalStateException(); DupInstruction dup = (DupInstruction) i.getInstruction(); //if (dup instanceof Dup || dup instanceof Dup_X1) @@ -144,7 +144,12 @@ public class MultiplicationDeobfuscator implements Deobfuscator try { MultiplicationExpression other = parseExpression(orig.getPushed()); - me.subexpressions.add(other); + // this expression is used elsewhere like 'pushConstant' so any changes + // done to it affect that, too. so multiply it by existing values? + me.instructions.addAll(other.instructions); + me.dupedInstructions.addAll(other.instructions); + me.subexpressions.addAll(other.subexpressions); + //me.subexpressions.add(other); } catch (IllegalStateException ex) { diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java index 9896b7e0c3..6ee8e16dbe 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java @@ -8,7 +8,8 @@ import net.runelite.deob.execution.InstructionContext; public class MultiplicationExpression { - List instructions = new ArrayList<>(); // push constant instructions that are being multiplied + List instructions = new ArrayList<>(), // push constant instructions that are being multiplied + dupedInstructions = new ArrayList<>(); List subexpressions = new ArrayList<>(); // for distributing, each subexpr is * by this InstructionContext dupmagic; // inverse of what is distributed to subexpressions gets set here static boolean replace; @@ -27,23 +28,49 @@ public class MultiplicationExpression result *= value; } + // assert (dupmagic != null) == !dupedInstructions.isEmpty(); + if (dupmagic != null) + { + // mul dupmagic by result of dup ins? + + PushConstantInstruction pci = (PushConstantInstruction) dupmagic.getInstruction(); + int value = (int) pci.getConstant().getObject(); + + for (InstructionContext ic : dupedInstructions) + { + PushConstantInstruction pci2 = (PushConstantInstruction) ic.getInstruction(); + int value2 = (int) pci2.getConstant().getObject(); + + value *= value2; + } + + Instruction newIns = pci.setConstant(new net.runelite.deob.pool.Integer(value)); + System.out.println("dupmagic"); + assert newIns == (Instruction) pci; + } + // multiply subexpressions by result if (!subexpressions.isEmpty()) { for (MultiplicationExpression me : subexpressions) { +// if (me.instructions.isEmpty() && this.dupmagic != null) +// { +// assert me.dupmagic == null; +// me.dupmagic = this.dupmagic; +// } count += me.simplify(result); } - if (dupmagic != null) - { - PushConstantInstruction pci = (PushConstantInstruction) dupmagic.getInstruction(); - int value = (int) pci.getConstant().getObject(); - - value *= DMath.modInverse(result); - - pci.setConstant(new net.runelite.deob.pool.Integer(value)); - } +// if (dupmagic != null) +// { +// PushConstantInstruction pci = (PushConstantInstruction) dupmagic.getInstruction(); +// int value = (int) pci.getConstant().getObject(); +// +// value *= DMath.modInverse(result); +// +// pci.setConstant(new net.runelite.deob.pool.Integer(value)); +// } result = 1; // constant has been distributed, outer numbers all go to 1 } From 164b5fd5afccd336011d4b760e9ad2e4cbaf56f1 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 1 Oct 2015 17:02:25 -0400 Subject: [PATCH 38/58] ahhhhhhhhhhhhhhh --- src/main/java/net/runelite/deob/Deob.java | 2 +- .../arithmetic/MultiplicationDeobfuscator.java | 14 ++++++++++---- .../arithmetic/MultiplicationExpression.java | 18 +++++++++--------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 9008a1ae50..0a823896b2 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -84,7 +84,7 @@ public class Deob //new ModArith().run(group); - new MultiplicationDeobfuscator().run(group); // this causes spinning? + new MultiplicationDeobfuscator().run(group); // new MultiplyOneDeobfuscator().run(group); // diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index e334bab948..ea6b4cc598 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -146,10 +146,16 @@ public class MultiplicationDeobfuscator implements Deobfuscator MultiplicationExpression other = parseExpression(orig.getPushed()); // this expression is used elsewhere like 'pushConstant' so any changes // done to it affect that, too. so multiply it by existing values? - me.instructions.addAll(other.instructions); - me.dupedInstructions.addAll(other.instructions); - me.subexpressions.addAll(other.subexpressions); - //me.subexpressions.add(other); + if (orig.getPushed().getInstruction() instanceof IAdd || orig.getPushed().getInstruction() instanceof ISub) + { + me.subexpressions.add(other); + } + else + { + me.instructions.addAll(other.instructions); + me.dupedInstructions.addAll(other.instructions); + me.subexpressions.addAll(other.subexpressions); + } } catch (IllegalStateException ex) { diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java index 6ee8e16dbe..7f1ebb0cc1 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java @@ -62,15 +62,15 @@ public class MultiplicationExpression count += me.simplify(result); } -// if (dupmagic != null) -// { -// PushConstantInstruction pci = (PushConstantInstruction) dupmagic.getInstruction(); -// int value = (int) pci.getConstant().getObject(); -// -// value *= DMath.modInverse(result); -// -// pci.setConstant(new net.runelite.deob.pool.Integer(value)); -// } + if (dupmagic != null) + { + PushConstantInstruction pci = (PushConstantInstruction) dupmagic.getInstruction(); + int value = (int) pci.getConstant().getObject(); + + value *= DMath.modInverse(result); + + pci.setConstant(new net.runelite.deob.pool.Integer(value)); + } result = 1; // constant has been distributed, outer numbers all go to 1 } From 3e6213ea524bc29bf33982a80e9f8c225661e027 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 2 Oct 2015 17:14:14 -0400 Subject: [PATCH 39/58] ise fixes, grr --- .../deob/attributes/code/Instructions.java | 9 +++++++++ .../deob/deobfuscators/IllegalStateExceptions.java | 14 +++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/Instructions.java b/src/main/java/net/runelite/deob/attributes/code/Instructions.java index 54df6cf832..3f923b42a2 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instructions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instructions.java @@ -79,6 +79,15 @@ public class Instructions public void remove(Instruction ins) { + for (Instruction i : instructions) + { + if (i instanceof JumpingInstruction) + { + JumpingInstruction j = (JumpingInstruction) i; + assert !j.getJumps().contains(ins); + } + } + ins.remove(); instructions.remove(ins); } diff --git a/src/main/java/net/runelite/deob/deobfuscators/IllegalStateExceptions.java b/src/main/java/net/runelite/deob/deobfuscators/IllegalStateExceptions.java index cdff714ad5..b021725e40 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/IllegalStateExceptions.java +++ b/src/main/java/net/runelite/deob/deobfuscators/IllegalStateExceptions.java @@ -39,6 +39,7 @@ public class IllegalStateExceptions implements Deobfuscator Instructions instructions = c.getInstructions(); instructions.clearBlockGraph(); + instructions.buildJumpGraph(); List ilist = instructions.getInstructions(); for (int i = 0; i < ilist.size(); ++i) @@ -109,7 +110,11 @@ public class IllegalStateExceptions implements Deobfuscator instructions.remove(ins); // insert goto - ilist.add(i, new Goto(instructions, to)); + assert ilist.contains(to); + Goto g = new Goto(instructions, to); + g.jump.add(to); + to.from.add(g); + ilist.add(i, g); ++count; break; @@ -121,17 +126,20 @@ public class IllegalStateExceptions implements Deobfuscator @Override public void run(ClassGroup group) - { + { + group.buildClassGraph(); Execution execution = new Execution(group); execution.populateInitialMethods(); execution.run(); - + int count = 0; int passes = 0; int i; do { i = checkOnce(execution, group); + + System.out.println("ise removal pass " + passes + " removed " + i); count += i; ++passes; From 1608d84b391b4c8b2ee14eb77395cb0afafeddd4 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 2 Oct 2015 22:50:32 -0400 Subject: [PATCH 40/58] I need a better solution than having to edit the jumpgraph all the time --- .../deob/attributes/code/Instructions.java | 16 ++++++++-------- .../deob/deobfuscators/MethodInliner.java | 13 ++++++++++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/Instructions.java b/src/main/java/net/runelite/deob/attributes/code/Instructions.java index 3f923b42a2..bb7148659b 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instructions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instructions.java @@ -79,14 +79,14 @@ public class Instructions public void remove(Instruction ins) { - for (Instruction i : instructions) - { - if (i instanceof JumpingInstruction) - { - JumpingInstruction j = (JumpingInstruction) i; - assert !j.getJumps().contains(ins); - } - } +// for (Instruction i : instructions) +// { +// if (i instanceof JumpingInstruction) +// { +// JumpingInstruction j = (JumpingInstruction) i; +// assert !j.getJumps().contains(ins); +// } +// } ins.remove(); instructions.remove(ins); diff --git a/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java b/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java index 37e946ce68..b8cbd34826 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java +++ b/src/main/java/net/runelite/deob/deobfuscators/MethodInliner.java @@ -203,8 +203,8 @@ public class MethodInliner implements Deobfuscator fromI.jump.remove(invokeIns); fromI.replace(invokeIns, firstParamStore); - fromI.jump.add(firstParamStore); + firstParamStore.from.add(fromI); } invokeIns.from.clear(); @@ -225,8 +225,14 @@ public class MethodInliner implements Deobfuscator // instead of return, jump to next instruction after the invoke Instruction oldI = i; i = new Goto(methodInstructions, nextInstruction); + assert methodInstructions.getInstructions().contains(nextInstruction); - i.jump.addAll(oldI.jump); + assert oldI != nextInstruction; + i.jump.add(nextInstruction); + nextInstruction.from.add(i); + + assert oldI.jump.isEmpty(); + //i.jump.addAll(oldI.jump); i.from.addAll(oldI.from); for (Instruction i2 : oldI.from) @@ -249,7 +255,8 @@ public class MethodInliner implements Deobfuscator if (oldI != i) { - i.jump.addAll(oldI.jump); + assert oldI.jump.isEmpty(); + //i.jump.addAll(oldI.jump); i.from.addAll(oldI.from); for (Instruction i2 : oldI.from) From 6f6fd5150920ed2f403ad4b4d8230e647a175174 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 3 Oct 2015 00:36:30 -0400 Subject: [PATCH 41/58] Split datastream loading from classfile to prepare for tests --- .../java/net/runelite/deob/ClassFile.java | 24 +++--- .../java/net/runelite/deob/ClassGroup.java | 5 ++ .../java/net/runelite/deob/ConstantPool.java | 4 +- src/main/java/net/runelite/deob/Deob.java | 86 +++++++++---------- src/main/java/net/runelite/deob/Field.java | 5 +- src/main/java/net/runelite/deob/Fields.java | 11 ++- .../java/net/runelite/deob/Interfaces.java | 4 +- src/main/java/net/runelite/deob/Method.java | 5 +- src/main/java/net/runelite/deob/Methods.java | 11 ++- .../runelite/deob/attributes/Attribute.java | 7 +- .../runelite/deob/attributes/Attributes.java | 24 +++--- .../net/runelite/deob/attributes/Code.java | 10 +-- .../deob/attributes/ConstantValue.java | 3 +- .../runelite/deob/attributes/Exceptions.java | 4 +- .../net/runelite/deob/attributes/Unknown.java | 3 +- .../deob/attributes/code/Exception.java | 3 +- .../deob/attributes/code/Exceptions.java | 6 +- .../deob/attributes/code/Instruction.java | 5 ++ .../deob/attributes/code/Instructions.java | 7 +- .../attributes/code/instructions/ALoad.java | 25 ++++-- .../code/instructions/ANewArray.java | 9 +- .../attributes/code/instructions/AStore.java | 9 +- .../attributes/code/instructions/BiPush.java | 9 +- .../code/instructions/CheckCast.java | 9 +- .../attributes/code/instructions/DLoad.java | 29 ++++--- .../attributes/code/instructions/DStore.java | 9 +- .../attributes/code/instructions/FLoad.java | 29 ++++--- .../attributes/code/instructions/FStore.java | 9 +- .../code/instructions/GetField.java | 9 +- .../code/instructions/GetStatic.java | 9 +- .../attributes/code/instructions/Goto.java | 13 +-- .../attributes/code/instructions/GotoW.java | 9 +- .../attributes/code/instructions/IInc.java | 33 ++++--- .../attributes/code/instructions/ILoad.java | 29 ++++--- .../attributes/code/instructions/IStore.java | 18 ++-- .../deob/attributes/code/instructions/If.java | 9 +- .../attributes/code/instructions/If0.java | 9 +- .../code/instructions/InstanceOf.java | 9 +- .../code/instructions/InvokeInterface.java | 9 +- .../code/instructions/InvokeSpecial.java | 9 +- .../code/instructions/InvokeStatic.java | 9 +- .../code/instructions/InvokeVirtual.java | 9 +- .../attributes/code/instructions/LDC2_W.java | 9 +- .../attributes/code/instructions/LDC_W.java | 29 ++++--- .../attributes/code/instructions/LLoad.java | 29 ++++--- .../attributes/code/instructions/LStore.java | 9 +- .../code/instructions/LookupSwitch.java | 11 ++- .../code/instructions/MultiANewArray.java | 7 +- .../attributes/code/instructions/New.java | 9 +- .../code/instructions/NewArray.java | 9 +- .../code/instructions/PutField.java | 11 ++- .../code/instructions/PutStatic.java | 8 +- .../attributes/code/instructions/SiPush.java | 9 +- .../code/instructions/TableSwitch.java | 11 ++- .../attributes/code/instructions/Wide.java | 13 +-- .../net/runelite/deob/execution/Stack.java | 2 +- .../java/net/runelite/deob/pool/Class.java | 3 +- .../java/net/runelite/deob/pool/Double.java | 4 +- .../java/net/runelite/deob/pool/Field.java | 4 +- .../java/net/runelite/deob/pool/Float.java | 4 +- .../java/net/runelite/deob/pool/Integer.java | 4 +- .../runelite/deob/pool/InterfaceMethod.java | 4 +- .../java/net/runelite/deob/pool/Long.java | 4 +- .../java/net/runelite/deob/pool/Method.java | 4 +- .../net/runelite/deob/pool/NameAndType.java | 4 +- .../java/net/runelite/deob/pool/String.java | 4 +- .../java/net/runelite/deob/pool/UTF8.java | 5 +- 67 files changed, 436 insertions(+), 321 deletions(-) diff --git a/src/main/java/net/runelite/deob/ClassFile.java b/src/main/java/net/runelite/deob/ClassFile.java index 56915648da..c8713441ce 100644 --- a/src/main/java/net/runelite/deob/ClassFile.java +++ b/src/main/java/net/runelite/deob/ClassFile.java @@ -16,7 +16,6 @@ public class ClassFile private static final int MAGIC = 0xcafebabe; private ClassGroup group; - private DataInputStream is; private ClassFile parent; // super class private List children = new ArrayList<>(); // classes which inherit from this @@ -35,7 +34,6 @@ public class ClassFile public ClassFile(ClassGroup group, DataInputStream is) throws IOException { this.group = group; - this.is = is; int magic = is.readInt(); if (magic != MAGIC) @@ -50,12 +48,21 @@ public class ClassFile name = pool.getClass(is.readUnsignedShort()); super_class = pool.getClass(is.readUnsignedShort()); - interfaces = new Interfaces(this); + interfaces = new Interfaces(this, is); + fields = new Fields(this, is); + + methods = new Methods(this, is); + + attributes = new Attributes(this, is); + } + + public ClassFile(ClassGroup group) + { + this.group = group; + fields = new Fields(this); - methods = new Methods(this); - attributes = new Attributes(this); } @@ -93,12 +100,7 @@ public class ClassFile { return group; } - - public DataInputStream getStream() - { - return is; - } - + public ConstantPool getPool() { return pool; diff --git a/src/main/java/net/runelite/deob/ClassGroup.java b/src/main/java/net/runelite/deob/ClassGroup.java index f0d5cac302..c775db277f 100644 --- a/src/main/java/net/runelite/deob/ClassGroup.java +++ b/src/main/java/net/runelite/deob/ClassGroup.java @@ -20,6 +20,11 @@ public class ClassGroup return cf; } + public void addClass(ClassFile cf) + { + classes.add(cf); + } + public void removeClass(ClassFile cf) { classes.remove(cf); diff --git a/src/main/java/net/runelite/deob/ConstantPool.java b/src/main/java/net/runelite/deob/ConstantPool.java index 8193237f25..8dae509745 100644 --- a/src/main/java/net/runelite/deob/ConstantPool.java +++ b/src/main/java/net/runelite/deob/ConstantPool.java @@ -38,8 +38,8 @@ public class ConstantPool try { - Constructor con = type.getPoolClass().getConstructor(new Class[] { ConstantPool.class }); - PoolEntry entry = con.newInstance(this); + Constructor con = type.getPoolClass().getConstructor(new Class[] { ConstantPool.class, DataInputStream.class }); + PoolEntry entry = con.newInstance(this, is); entry.id = i; entries.add(entry); diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index 0a823896b2..b82ce45710 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -39,52 +39,52 @@ public class Deob ClassGroup group = loadJar(args[0]); -// run(group, new RenameUnique()); + //run(group, new RenameUnique()); -// // remove except RuntimeException -// run(group, new RuntimeExceptions()); -// -// // remove unused methods -// run(group, new UnusedMethods()); -// -// run(group, new UnreachedCode()); -// -// // remove illegal state exceptions, frees up some parameters -// run(group, new IllegalStateExceptions()); -// -// // remove constant logically dead parameters -// run(group, new ConstantParameter()); -// -// // remove unhit blocks -// run(group, new UnreachedCode()); -// -// // remove unused parameters -// run(group, new UnusedParameters()); -// -// // remove jump obfuscation -// //new Jumps().run(group); -// -// // remove unused fields -// run(group, new UnusedFields()); -// -// // remove unused methods, again? -// run(group, new UnusedMethods()); -// -// run(group, new MethodInliner()); -// -// run(group, new MethodMover()); -// -// run(group, new FieldInliner()); -// -// // XXX this is broken because when moving clinit around, some fields can depend on other fields -// // (like multianewarray) -// //new FieldMover().run(group); -// -// run(group, new UnusedClass()); + // remove except RuntimeException + run(group, new RuntimeExceptions()); - //new ModArith().run(group); + // remove unused methods + run(group, new UnusedMethods()); - new MultiplicationDeobfuscator().run(group); + run(group, new UnreachedCode()); + + // remove illegal state exceptions, frees up some parameters + run(group, new IllegalStateExceptions()); + + // remove constant logically dead parameters + run(group, new ConstantParameter()); + + // remove unhit blocks + run(group, new UnreachedCode()); + + // remove unused parameters + run(group, new UnusedParameters()); + + // remove jump obfuscation + //new Jumps().run(group); + + // remove unused fields + run(group, new UnusedFields()); + + // remove unused methods, again? + run(group, new UnusedMethods()); + + run(group, new MethodInliner()); + + run(group, new MethodMover()); + + run(group, new FieldInliner()); + + // XXX this is broken because when moving clinit around, some fields can depend on other fields + // (like multianewarray) + //new FieldMover().run(group); + + run(group, new UnusedClass()); + + new ModArith().run(group); + +// new MultiplicationDeobfuscator().run(group); // new MultiplyOneDeobfuscator().run(group); // diff --git a/src/main/java/net/runelite/deob/Field.java b/src/main/java/net/runelite/deob/Field.java index 74d2916598..c9f2bfd3a1 100644 --- a/src/main/java/net/runelite/deob/Field.java +++ b/src/main/java/net/runelite/deob/Field.java @@ -29,17 +29,16 @@ public class Field private Type type; private Attributes attributes; - Field(Fields fields) throws IOException + Field(Fields fields, DataInputStream is) throws IOException { this.fields = fields; - DataInputStream is = fields.getClassFile().getStream(); ConstantPool pool = fields.getClassFile().getPool(); accessFlags = is.readShort(); name = pool.getUTF8(is.readUnsignedShort()); type = new Type(pool.getUTF8(is.readUnsignedShort())); - attributes = new Attributes(this); + attributes = new Attributes(this, is); } public void write(DataOutputStream out) throws IOException diff --git a/src/main/java/net/runelite/deob/Fields.java b/src/main/java/net/runelite/deob/Fields.java index 49e2ffcefb..471eaaf9a7 100644 --- a/src/main/java/net/runelite/deob/Fields.java +++ b/src/main/java/net/runelite/deob/Fields.java @@ -14,16 +14,19 @@ public class Fields private List fields = new ArrayList<>(); - Fields(ClassFile c) throws IOException + Fields(ClassFile c, DataInputStream is) throws IOException { classFile = c; - DataInputStream is = c.getStream(); - int count = is.readUnsignedShort(); for (int i = 0; i < count; ++i) - fields.add(new Field(this)); + fields.add(new Field(this, is)); + } + + Fields(ClassFile c) + { + classFile = c; } public void write(DataOutputStream out) throws IOException diff --git a/src/main/java/net/runelite/deob/Interfaces.java b/src/main/java/net/runelite/deob/Interfaces.java index df3fbd1d66..4bee37f2df 100644 --- a/src/main/java/net/runelite/deob/Interfaces.java +++ b/src/main/java/net/runelite/deob/Interfaces.java @@ -14,12 +14,10 @@ public class Interfaces private List interfaces = new ArrayList(); - Interfaces(ClassFile c) throws IOException + Interfaces(ClassFile c, DataInputStream is) throws IOException { classFile = c; - DataInputStream is = c.getStream(); - int count = is.readUnsignedShort(); for (int i = 0; i < count; ++i) diff --git a/src/main/java/net/runelite/deob/Method.java b/src/main/java/net/runelite/deob/Method.java index a51508935c..a915c47c5a 100644 --- a/src/main/java/net/runelite/deob/Method.java +++ b/src/main/java/net/runelite/deob/Method.java @@ -27,18 +27,17 @@ public class Method public Signature arguments; private Attributes attributes; - Method(Methods methods) throws IOException + Method(Methods methods, DataInputStream is) throws IOException { this.methods = methods; - DataInputStream is = methods.getClassFile().getStream(); ConstantPool pool = methods.getClassFile().getPool(); accessFlags = is.readShort(); name = pool.getUTF8(is.readUnsignedShort()); arguments = new Signature(pool.getUTF8(is.readUnsignedShort())); attributes = new Attributes(this); - attributes.load(); + attributes.load(is); } public Method(Methods methods, String name, Signature signature) diff --git a/src/main/java/net/runelite/deob/Methods.java b/src/main/java/net/runelite/deob/Methods.java index 4bb6dceab3..63460f825b 100644 --- a/src/main/java/net/runelite/deob/Methods.java +++ b/src/main/java/net/runelite/deob/Methods.java @@ -15,16 +15,19 @@ public class Methods private List methods = new ArrayList<>(); - Methods(ClassFile cf) throws IOException + Methods(ClassFile cf, DataInputStream is) throws IOException { classFile = cf; - DataInputStream is = cf.getStream(); - int count = is.readUnsignedShort(); for (int i = 0; i < count; ++i) - methods.add(new Method(this)); + methods.add(new Method(this, is)); + } + + Methods(ClassFile cf) + { + classFile = cf; } public void write(DataOutputStream out) throws IOException diff --git a/src/main/java/net/runelite/deob/attributes/Attribute.java b/src/main/java/net/runelite/deob/attributes/Attribute.java index c92378223f..46980a5fb4 100644 --- a/src/main/java/net/runelite/deob/attributes/Attribute.java +++ b/src/main/java/net/runelite/deob/attributes/Attribute.java @@ -17,14 +17,13 @@ public abstract class Attribute this.type = type; } - public final void load() throws IOException + public final void load(DataInputStream is) throws IOException { - DataInputStream is = attributes.getStream(); this.length = is.readInt(); - this.loadAttribute(); + this.loadAttribute(is); } - public abstract void loadAttribute() throws IOException; + public abstract void loadAttribute(DataInputStream is) throws IOException; public final void write(DataOutputStream out) throws IOException { diff --git a/src/main/java/net/runelite/deob/attributes/Attributes.java b/src/main/java/net/runelite/deob/attributes/Attributes.java index e91300e2e5..be8c8a816c 100644 --- a/src/main/java/net/runelite/deob/attributes/Attributes.java +++ b/src/main/java/net/runelite/deob/attributes/Attributes.java @@ -19,18 +19,23 @@ public class Attributes private List attributes = new ArrayList<>(); - public Attributes(ClassFile cf) throws IOException + public Attributes(ClassFile cf, DataInputStream is) throws IOException { classFile = cf; - load(); + load(is); + } + + public Attributes(ClassFile cf) + { + classFile = cf; } - public Attributes(Field f) throws IOException + public Attributes(Field f, DataInputStream is) throws IOException { field = f; - load(); + load(is); } public Attributes(Method m) @@ -73,15 +78,8 @@ public class Attributes return null; } - public DataInputStream getStream() + public void load(DataInputStream is) throws IOException { - return getClassFile().getStream(); - } - - public void load() throws IOException - { - DataInputStream is = getStream(); - int count = is.readUnsignedShort(); for (int i = 0; i < count; ++i) @@ -93,7 +91,7 @@ public class Attributes { Constructor con = type.getAttributeClass().getConstructor(new Class[] { Attributes.class }); Attribute attr = con.newInstance(this); - attr.load(); + attr.load(is); if (type != AttributeType.UNKNOWN) attributes.add(attr); diff --git a/src/main/java/net/runelite/deob/attributes/Code.java b/src/main/java/net/runelite/deob/attributes/Code.java index edacb393de..6dee991646 100644 --- a/src/main/java/net/runelite/deob/attributes/Code.java +++ b/src/main/java/net/runelite/deob/attributes/Code.java @@ -26,21 +26,19 @@ public class Code extends Attribute } @Override - public void loadAttribute() throws IOException + public void loadAttribute(DataInputStream is) throws IOException { - DataInputStream is = this.getAttributes().getStream(); - maxStack = is.readUnsignedShort(); is.skip(2); // max locals instructions = new Instructions(this); - instructions.load(); + instructions.load(is); exceptions = new Exceptions(this); - exceptions.load(); + exceptions.load(is); this.attributes = new Attributes(this); - this.attributes.load(); + this.attributes.load(is); instructions.buildBlocks(); instructions.buildJumpGraph(); diff --git a/src/main/java/net/runelite/deob/attributes/ConstantValue.java b/src/main/java/net/runelite/deob/attributes/ConstantValue.java index 56e61c077a..44f8d92af3 100644 --- a/src/main/java/net/runelite/deob/attributes/ConstantValue.java +++ b/src/main/java/net/runelite/deob/attributes/ConstantValue.java @@ -23,9 +23,8 @@ public class ConstantValue extends Attribute } @Override - public void loadAttribute() throws IOException + public void loadAttribute(DataInputStream is) throws IOException { - DataInputStream is = this.getAttributes().getStream(); value = this.getAttributes().getClassFile().getPool().getEntry(is.readUnsignedShort()); } diff --git a/src/main/java/net/runelite/deob/attributes/Exceptions.java b/src/main/java/net/runelite/deob/attributes/Exceptions.java index d3542e8f84..adfa20444d 100644 --- a/src/main/java/net/runelite/deob/attributes/Exceptions.java +++ b/src/main/java/net/runelite/deob/attributes/Exceptions.java @@ -19,10 +19,8 @@ public class Exceptions extends Attribute } @Override - public void loadAttribute() throws IOException + public void loadAttribute(DataInputStream is) throws IOException { - DataInputStream is = this.getAttributes().getStream(); - int count = is.readUnsignedShort(); for (int i = 0; i < count; ++i) { diff --git a/src/main/java/net/runelite/deob/attributes/Unknown.java b/src/main/java/net/runelite/deob/attributes/Unknown.java index a37270b02d..74fc97ebb3 100644 --- a/src/main/java/net/runelite/deob/attributes/Unknown.java +++ b/src/main/java/net/runelite/deob/attributes/Unknown.java @@ -14,10 +14,9 @@ public class Unknown extends Attribute } @Override - public void loadAttribute() throws IOException + public void loadAttribute(DataInputStream is) throws IOException { int len = this.getLength(); - DataInputStream is = this.getAttributes().getStream(); data = new byte[len]; diff --git a/src/main/java/net/runelite/deob/attributes/code/Exception.java b/src/main/java/net/runelite/deob/attributes/code/Exception.java index 6ad9e1b32c..d7257deb03 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Exception.java +++ b/src/main/java/net/runelite/deob/attributes/code/Exception.java @@ -15,11 +15,10 @@ public class Exception private Instruction start, end, handler; private Class catchType; - public Exception(Exceptions exceptions) throws IOException + public Exception(Exceptions exceptions, DataInputStream is) throws IOException { this.exceptions = exceptions; - DataInputStream is = exceptions.getCode().getAttributes().getStream(); ConstantPool pool = exceptions.getCode().getAttributes().getClassFile().getPool(); int startPc = is.readUnsignedShort(); diff --git a/src/main/java/net/runelite/deob/attributes/code/Exceptions.java b/src/main/java/net/runelite/deob/attributes/code/Exceptions.java index e9de6f3c31..ea2a19f0e2 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Exceptions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Exceptions.java @@ -19,14 +19,12 @@ public class Exceptions this.code = code; } - public void load() throws IOException + public void load(DataInputStream is) throws IOException { - DataInputStream is = code.getAttributes().getStream(); - int count = is.readUnsignedShort(); for (int i = 0; i < count; ++i) - exceptions.add(new Exception(this)); + exceptions.add(new Exception(this, is)); } public void add(Exception e) diff --git a/src/main/java/net/runelite/deob/attributes/code/Instruction.java b/src/main/java/net/runelite/deob/attributes/code/Instruction.java index 9db98de703..dbd93a8736 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instruction.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instruction.java @@ -1,5 +1,6 @@ package net.runelite.deob.attributes.code; +import java.io.DataInputStream; import net.runelite.deob.ClassFile; import net.runelite.deob.ConstantPool; import net.runelite.deob.Field; @@ -31,6 +32,10 @@ public abstract class Instruction this.pc = pc; } + public void load(DataInputStream is) throws IOException + { + } + protected void remove() { assert block == null; diff --git a/src/main/java/net/runelite/deob/attributes/code/Instructions.java b/src/main/java/net/runelite/deob/attributes/code/Instructions.java index bb7148659b..20170e8b36 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instructions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instructions.java @@ -26,10 +26,8 @@ public class Instructions this.code = code; } - public void load() throws IOException + public void load(DataInputStream is) throws IOException { - DataInputStream is = code.getAttributes().getStream(); - int length = is.readInt(); int pc; @@ -43,8 +41,9 @@ public class Instructions { Constructor con = type.getInstructionClass().getConstructor(Instructions.class, InstructionType.class, int.class); Instruction ins = con.newInstance(this, type, pc); - Instruction genericIns = ins.makeGeneric(); + ins.load(is); + Instruction genericIns = ins.makeGeneric(); if (genericIns != ins) { genericIns.setPc(ins.getPc()); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/ALoad.java b/src/main/java/net/runelite/deob/attributes/code/instructions/ALoad.java index 19d09f8bda..2d606f6275 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/ALoad.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/ALoad.java @@ -19,6 +19,7 @@ import java.io.IOException; public class ALoad extends Instruction implements LVTInstruction, WideInstruction { private int index; + private boolean wide; public ALoad(Instructions instructions, int index) { @@ -30,19 +31,27 @@ public class ALoad extends Instruction implements LVTInstruction, WideInstructio public ALoad(Instructions instructions, InstructionType type, int pc) throws IOException { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readByte(); - length += 1; } public ALoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) throws IOException { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readShort(); - length += 2; + wide = true; + } + + @Override + public void load(DataInputStream is) throws IOException + { + if (wide) + { + index = is.readShort(); + length += 2; + } + else + { + index = is.readByte(); + length += 1; + } } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/ANewArray.java b/src/main/java/net/runelite/deob/attributes/code/instructions/ANewArray.java index 2258188730..0e47651364 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/ANewArray.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/ANewArray.java @@ -19,11 +19,14 @@ public class ANewArray extends Instruction { private Class clazz; - public ANewArray(Instructions instructions, InstructionType type, int pc) throws IOException + public ANewArray(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { clazz = this.getPool().getClass(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore.java index bc60499d24..b189381d3f 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/AStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/AStore.java @@ -27,11 +27,14 @@ public class AStore extends Instruction implements LVTInstruction, WideInstructi ++length; } - public AStore(Instructions instructions, InstructionType type, int pc) throws IOException + public AStore(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { index = is.readByte(); length += 1; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/BiPush.java b/src/main/java/net/runelite/deob/attributes/code/instructions/BiPush.java index 7207072db9..6404d7a48d 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/BiPush.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/BiPush.java @@ -18,11 +18,14 @@ public class BiPush extends Instruction implements PushConstantInstruction { private byte b; - public BiPush(Instructions instructions, InstructionType type, int pc) throws IOException + public BiPush(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { b = is.readByte(); length += 1; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/CheckCast.java b/src/main/java/net/runelite/deob/attributes/code/instructions/CheckCast.java index 8c424f5ea0..33a8cc9812 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/CheckCast.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/CheckCast.java @@ -19,11 +19,14 @@ public class CheckCast extends Instruction { private Class clazz; - public CheckCast(Instructions instructions, InstructionType type, int pc) throws IOException + public CheckCast(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { clazz = this.getPool().getClass(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DLoad.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DLoad.java index 7968b6f7dc..ae1c069026 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DLoad.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DLoad.java @@ -20,6 +20,7 @@ import java.io.IOException; public class DLoad extends Instruction implements LVTInstruction, WideInstruction { private int index; + private boolean wide; public DLoad(Instructions instructions, int index) { @@ -28,22 +29,30 @@ public class DLoad extends Instruction implements LVTInstruction, WideInstructio ++length; } - public DLoad(Instructions instructions, InstructionType type, int pc) throws IOException + public DLoad(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readByte(); - length += 1; } - public DLoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) throws IOException + public DLoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readShort(); - length += 2; + wide = true; + } + + @Override + public void load(DataInputStream is) throws IOException + { + if (wide) + { + index = is.readShort(); + length += 2; + } + else + { + index = is.readByte(); + length += 1; + } } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore.java index a42a618723..7696fbbcdc 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/DStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/DStore.java @@ -27,11 +27,14 @@ public class DStore extends Instruction implements LVTInstruction, WideInstructi ++length; } - public DStore(Instructions instructions, InstructionType type, int pc) throws IOException + public DStore(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { index = is.readByte(); length += 1; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FLoad.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FLoad.java index cda5057067..f6022d2464 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FLoad.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FLoad.java @@ -20,6 +20,7 @@ import java.io.IOException; public class FLoad extends Instruction implements LVTInstruction, WideInstruction { private int index; + private boolean wide; public FLoad(Instructions instructions, int index) { @@ -28,22 +29,30 @@ public class FLoad extends Instruction implements LVTInstruction, WideInstructio ++length; } - public FLoad(Instructions instructions, InstructionType type, int pc) throws IOException + public FLoad(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readByte(); - length += 1; } - public FLoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) throws IOException + public FLoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readShort(); - length += 2; + wide = true; + } + + @Override + public void load(DataInputStream is) throws IOException + { + if (wide) + { + index = is.readShort(); + length += 2; + } + else + { + index = is.readByte(); + length += 1; + } } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore.java index 53f08a4966..6bbb78c365 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/FStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/FStore.java @@ -27,11 +27,14 @@ public class FStore extends Instruction implements LVTInstruction, WideInstructi ++length; } - public FStore(Instructions instructions, InstructionType type, int pc) throws IOException + public FStore(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { index = is.readByte(); length += 1; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java index 84bbe1d55c..9cc68e0150 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java @@ -24,11 +24,14 @@ public class GetField extends Instruction implements GetFieldInstruction { private Field field; - public GetField(Instructions instructions, InstructionType type, int pc) throws IOException + public GetField(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { field = this.getPool().getField(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java index 68b2451a5d..fcc8bde040 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java @@ -24,11 +24,14 @@ public class GetStatic extends Instruction implements GetFieldInstruction { private Field field; - public GetStatic(Instructions instructions, InstructionType type, int pc) throws IOException + public GetStatic(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { field = this.getPool().getField(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Goto.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Goto.java index 38ddc9d37d..4f7b60fd6a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Goto.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Goto.java @@ -18,13 +18,9 @@ public class Goto extends Instruction implements JumpingInstruction private Instruction to; private short offset; - public Goto(Instructions instructions, InstructionType type, int pc) throws IOException + public Goto(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - offset = is.readShort(); - length += 2; } public Goto(Instructions instructions, Instruction to) @@ -34,6 +30,13 @@ public class Goto extends Instruction implements JumpingInstruction length += 2; } + @Override + public void load(DataInputStream is) throws IOException + { + offset = is.readShort(); + length += 2; + } + @Override public void resolve() { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GotoW.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GotoW.java index 67263ae0ca..123bed2413 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GotoW.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GotoW.java @@ -18,11 +18,14 @@ public class GotoW extends Instruction implements JumpingInstruction private Instruction to; private int offset; - public GotoW(Instructions instructions, InstructionType type, int pc) throws IOException + public GotoW(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { offset = is.readInt(); length += 4; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IInc.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IInc.java index 0ab042b8af..5e94c1497a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IInc.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IInc.java @@ -19,25 +19,34 @@ public class IInc extends Instruction implements LVTInstruction, WideInstruction { private short index; private short inc; + private boolean wide; - public IInc(Instructions instructions, InstructionType type, int pc) throws IOException + public IInc(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readByte(); - inc = is.readByte(); - length += 2; } - public IInc(Instructions instructions, InstructionType type, Instruction instruction, int pc) throws IOException + public IInc(Instructions instructions, InstructionType type, Instruction instruction, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readShort(); - inc = is.readShort(); - length += 4; + wide = true; + } + + @Override + public void load(DataInputStream is) throws IOException + { + if (wide) + { + index = is.readShort(); + inc = is.readShort(); + length += 4; + } + else + { + index = is.readByte(); + inc = is.readByte(); + length += 2; + } } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/ILoad.java b/src/main/java/net/runelite/deob/attributes/code/instructions/ILoad.java index 74cae101bf..b9b7403b07 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/ILoad.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/ILoad.java @@ -20,6 +20,7 @@ import java.io.IOException; public class ILoad extends Instruction implements LVTInstruction, WideInstruction { private int index; + private boolean wide; public ILoad(Instructions instructions, int index) { @@ -28,22 +29,30 @@ public class ILoad extends Instruction implements LVTInstruction, WideInstructio ++length; } - public ILoad(Instructions instructions, InstructionType type, int pc) throws IOException + public ILoad(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readByte(); - length += 1; } - public ILoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) throws IOException + public ILoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readShort(); - length += 2; + wide = true; + } + + @Override + public void load(DataInputStream is) throws IOException + { + if (wide) + { + index = is.readShort(); + length += 2; + } + else + { + index = is.readByte(); + length += 1; + } } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java index df295480f0..e9893542b2 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java @@ -28,24 +28,18 @@ public class IStore extends Instruction implements LVTInstruction, WideInstructi ++length; } - public IStore(Instructions instructions, InstructionType type, int pc) throws IOException + public IStore(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { index = is.readByte(); length += 1; } -// public IStore(Instructions instructions, InstructionType type, Instruction instruction, int pc) throws IOException -// { -// super(instructions, type, pc); -// -// DataInputStream is = instructions.getCode().getAttributes().getStream(); -// index = is.readShort(); -// length += 2; -// } - @Override public void write(DataOutputStream out) throws IOException { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/If.java b/src/main/java/net/runelite/deob/attributes/code/instructions/If.java index 33dea6a988..7d14cee235 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/If.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/If.java @@ -21,11 +21,14 @@ public class If extends Instruction implements JumpingInstruction, ComparisonIns private Instruction to; private short offset; - public If(Instructions instructions, InstructionType type, int pc) throws IOException + public If(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { offset = is.readShort(); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java index a0d1a538e7..4fb9f4272c 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java @@ -21,11 +21,14 @@ public class If0 extends Instruction implements JumpingInstruction, ComparisonIn private Instruction to; private short offset; - public If0(Instructions instructions, InstructionType type, int pc) throws IOException + public If0(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { offset = is.readShort(); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InstanceOf.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InstanceOf.java index c73ec2c0e1..76fdbd900e 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InstanceOf.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InstanceOf.java @@ -18,11 +18,14 @@ public class InstanceOf extends Instruction { private Class clazz; - public InstanceOf(Instructions instructions, InstructionType type, int pc) throws IOException + public InstanceOf(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { clazz = this.getPool().getClass(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeInterface.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeInterface.java index 316a96b001..e926446534 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeInterface.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeInterface.java @@ -30,11 +30,14 @@ public class InvokeInterface extends Instruction implements InvokeInstruction private InterfaceMethod method; private int count; - public InvokeInterface(Instructions instructions, InstructionType type, int pc) throws IOException + public InvokeInterface(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { method = this.getPool().getInterfaceMethod(is.readUnsignedShort()); count = is.readUnsignedByte(); is.skip(1); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeSpecial.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeSpecial.java index 4620440f14..8df3eceeb4 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeSpecial.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeSpecial.java @@ -28,11 +28,14 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction { private Method method; - public InvokeSpecial(Instructions instructions, InstructionType type, int pc) throws IOException + public InvokeSpecial(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { method = this.getPool().getMethod(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java index 6c3b057f73..5d434e9793 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java @@ -28,11 +28,14 @@ public class InvokeStatic extends Instruction implements InvokeInstruction { private Method method; - public InvokeStatic(Instructions instructions, InstructionType type, int pc) throws IOException + public InvokeStatic(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { method = this.getPool().getMethod(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeVirtual.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeVirtual.java index 8a33320d8e..c374548e57 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeVirtual.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeVirtual.java @@ -28,11 +28,14 @@ public class InvokeVirtual extends Instruction implements InvokeInstruction { private Method method; - public InvokeVirtual(Instructions instructions, InstructionType type, int pc) throws IOException + public InvokeVirtual(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { method = this.getPool().getMethod(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC2_W.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC2_W.java index cbc026db64..f770a6a6c5 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC2_W.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC2_W.java @@ -18,11 +18,14 @@ public class LDC2_W extends Instruction implements PushConstantInstruction { private PoolEntry value; - public LDC2_W(Instructions instructions, InstructionType type, int pc) throws IOException + public LDC2_W(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { value = this.getPool().getEntry(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java index a358f84ae1..303d944248 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java @@ -18,11 +18,26 @@ public class LDC_W extends Instruction implements PushConstantInstruction { private PoolEntry value; - public LDC_W(Instructions instructions, InstructionType type, int pc) throws IOException + public LDC_W(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + + assert type == InstructionType.LDC_W || type == InstructionType.LDC; + } + + public LDC_W(Instructions instructions, PoolEntry value) + { + super(instructions, InstructionType.LDC_W, 0); + + this.value = value; + length += 2; + } + + @Override + public void load(DataInputStream is) throws IOException + { + InstructionType type = this.getType(); + assert type == InstructionType.LDC_W || type == InstructionType.LDC; if (type == InstructionType.LDC_W) @@ -37,14 +52,6 @@ public class LDC_W extends Instruction implements PushConstantInstruction } } - public LDC_W(Instructions instructions, PoolEntry value) - { - super(instructions, InstructionType.LDC_W, 0); - - this.value = value; - length += 2; - } - @Override public void prime() { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LLoad.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LLoad.java index 85965b2b49..2fc0129555 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LLoad.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LLoad.java @@ -20,6 +20,7 @@ import java.io.IOException; public class LLoad extends Instruction implements LVTInstruction, WideInstruction { private int index; + private boolean wide; public LLoad(Instructions instructions, int index) { @@ -28,22 +29,30 @@ public class LLoad extends Instruction implements LVTInstruction, WideInstructio ++length; } - public LLoad(Instructions instructions, InstructionType type, int pc) throws IOException + public LLoad(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readByte(); - length += 1; } - public LLoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) throws IOException + public LLoad(Instructions instructions, InstructionType type, Instruction instruction, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - index = is.readShort(); - length += 2; + wide = true; + } + + @Override + public void load(DataInputStream is) throws IOException + { + if (wide) + { + index = is.readShort(); + length += 2; + } + else + { + index = is.readByte(); + length += 1; + } } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore.java index 7f519055e2..7a04bf927c 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LStore.java @@ -28,11 +28,14 @@ public class LStore extends Instruction implements LVTInstruction, WideInstructi ++length; } - public LStore(Instructions instructions, InstructionType type, int pc) throws IOException + public LStore(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { index = is.readByte(); length += 1; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LookupSwitch.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LookupSwitch.java index c1923d7d67..cf499f1086 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LookupSwitch.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LookupSwitch.java @@ -26,12 +26,15 @@ public class LookupSwitch extends Instruction implements JumpingInstruction private int[] match; private int[] branch; - public LookupSwitch(Instructions instructions, InstructionType type, int pc) throws IOException + public LookupSwitch(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - + } + + @Override + public void load(DataInputStream is) throws IOException + { + int pc = this.getPc(); int tableSkip = 4 - (pc + 1) % 4; if (tableSkip == 4) tableSkip = 0; if (tableSkip > 0) is.skip(tableSkip); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/MultiANewArray.java b/src/main/java/net/runelite/deob/attributes/code/instructions/MultiANewArray.java index 37f3a9a773..a29de34494 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/MultiANewArray.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/MultiANewArray.java @@ -23,8 +23,11 @@ public class MultiANewArray extends Instruction public MultiANewArray(Instructions instructions, InstructionType type, int pc) throws IOException { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { clazz = this.getPool().getClass(is.readUnsignedShort()); dimensions = is.readUnsignedByte(); length += 3; diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/New.java b/src/main/java/net/runelite/deob/attributes/code/instructions/New.java index b972ab959f..a3af1181eb 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/New.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/New.java @@ -19,11 +19,14 @@ public class New extends Instruction { private Class clazz; - public New(Instructions instructions, InstructionType type, int pc) throws IOException + public New(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { clazz = this.getPool().getClass(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/NewArray.java b/src/main/java/net/runelite/deob/attributes/code/instructions/NewArray.java index 153d07822b..90270616f0 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/NewArray.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/NewArray.java @@ -17,11 +17,14 @@ public class NewArray extends Instruction { private int type; - public NewArray(Instructions instructions, InstructionType type, int pc) throws IOException + public NewArray(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { this.type = is.readUnsignedByte(); length += 1; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java index 89cd1c12e6..99cc4246e2 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java @@ -16,10 +16,6 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.HashSet; -import java.util.List; -import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; -import static net.runelite.deob.attributes.code.instructions.PutStatic.translate; import net.runelite.deob.deobfuscators.arithmetic.Encryption; import net.runelite.deob.deobfuscators.arithmetic.Pair; @@ -30,8 +26,11 @@ public class PutField extends Instruction implements SetFieldInstruction public PutField(Instructions instructions, InstructionType type, int pc) throws IOException { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { field = this.getPool().getField(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index c71ec51a10..3b6a7aab36 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -16,7 +16,6 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.HashSet; import java.util.Set; import net.runelite.deob.attributes.code.instruction.types.DupInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; @@ -31,8 +30,11 @@ public class PutStatic extends Instruction implements SetFieldInstruction public PutStatic(Instructions instructions, InstructionType type, int pc) throws IOException { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { field = this.getPool().getField(is.readUnsignedShort()); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/SiPush.java b/src/main/java/net/runelite/deob/attributes/code/instructions/SiPush.java index e86ffe9159..0cad63a64c 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/SiPush.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/SiPush.java @@ -18,11 +18,14 @@ public class SiPush extends Instruction implements PushConstantInstruction { private short s; - public SiPush(Instructions instructions, InstructionType type, int pc) throws IOException + public SiPush(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); + } + + @Override + public void load(DataInputStream is) throws IOException + { s = is.readShort(); length += 2; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/TableSwitch.java b/src/main/java/net/runelite/deob/attributes/code/instructions/TableSwitch.java index 2e097b6cb8..cc88def589 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/TableSwitch.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/TableSwitch.java @@ -25,12 +25,15 @@ public class TableSwitch extends Instruction implements JumpingInstruction private int high; private int[] jumps; - public TableSwitch(Instructions instructions, InstructionType type, int pc) throws IOException + public TableSwitch(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - + } + + @Override + public void load(DataInputStream is) throws IOException + { + int pc = this.getPc(); int tableSkip = 4 - (pc + 1) % 4; if (tableSkip == 4) tableSkip = 0; if (tableSkip > 0) is.skip(tableSkip); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Wide.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Wide.java index c9f42abcce..4e83058175 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Wide.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Wide.java @@ -17,19 +17,22 @@ public class Wide extends Instruction implements LVTInstruction { private Instruction ins; - public Wide(Instructions instructions, InstructionType type, int pc) throws IOException + public Wide(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); - - DataInputStream is = instructions.getCode().getAttributes().getStream(); - + } + + @Override + public void load(DataInputStream is) throws IOException + { byte opcode = is.readByte(); // this byte is already in the length of the new instruction (length is initialized to 1) InstructionType op = InstructionType.findInstructionFromCode(opcode); try { Constructor con = op.getInstructionClass().getConstructor(Instructions.class, InstructionType.class, Instruction.class, int.class); - ins = con.newInstance(instructions, op, this, pc); + ins = con.newInstance(this.getInstructions(), op, this, this.getPc()); + ins.load(is); length += ins.getLength(); } catch (Exception ex) diff --git a/src/main/java/net/runelite/deob/execution/Stack.java b/src/main/java/net/runelite/deob/execution/Stack.java index 961d4725eb..5078344e76 100644 --- a/src/main/java/net/runelite/deob/execution/Stack.java +++ b/src/main/java/net/runelite/deob/execution/Stack.java @@ -9,7 +9,7 @@ public class Stack public Stack(int sz) { - stack = new StackContext[sz*2]; // XXX + stack = new StackContext[sz*2]; // XXX FIXME } protected Stack(Stack other) diff --git a/src/main/java/net/runelite/deob/pool/Class.java b/src/main/java/net/runelite/deob/pool/Class.java index b10b3b3f11..12c405fed4 100644 --- a/src/main/java/net/runelite/deob/pool/Class.java +++ b/src/main/java/net/runelite/deob/pool/Class.java @@ -12,11 +12,10 @@ public class Class extends PoolEntry private int index; private java.lang.String name; - public Class(ConstantPool pool) throws IOException + public Class(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.CLASS); - DataInputStream is = pool.getClassFile().getStream(); index = is.readUnsignedShort(); } diff --git a/src/main/java/net/runelite/deob/pool/Double.java b/src/main/java/net/runelite/deob/pool/Double.java index 79a5915d90..7ed74a9ade 100644 --- a/src/main/java/net/runelite/deob/pool/Double.java +++ b/src/main/java/net/runelite/deob/pool/Double.java @@ -11,12 +11,10 @@ public class Double extends PoolEntry { private double value; - public Double(ConstantPool pool) throws IOException + public Double(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.DOUBLE); - DataInputStream is = pool.getClassFile().getStream(); - value = is.readDouble(); } diff --git a/src/main/java/net/runelite/deob/pool/Field.java b/src/main/java/net/runelite/deob/pool/Field.java index ee8adbd168..87b569e7f3 100644 --- a/src/main/java/net/runelite/deob/pool/Field.java +++ b/src/main/java/net/runelite/deob/pool/Field.java @@ -12,12 +12,10 @@ public class Field extends PoolEntry private Class clazz; private NameAndType nat; - public Field(ConstantPool pool) throws IOException + public Field(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.FIELDREF); - DataInputStream is = pool.getClassFile().getStream(); - classIndex = is.readUnsignedShort(); natIndex = is.readUnsignedShort(); } diff --git a/src/main/java/net/runelite/deob/pool/Float.java b/src/main/java/net/runelite/deob/pool/Float.java index 293db1a282..33fa6f297d 100644 --- a/src/main/java/net/runelite/deob/pool/Float.java +++ b/src/main/java/net/runelite/deob/pool/Float.java @@ -11,12 +11,10 @@ public class Float extends PoolEntry { private float value; - public Float(ConstantPool pool) throws IOException + public Float(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.FLOAT); - DataInputStream is = pool.getClassFile().getStream(); - value = is.readFloat(); } diff --git a/src/main/java/net/runelite/deob/pool/Integer.java b/src/main/java/net/runelite/deob/pool/Integer.java index dd53b013f4..b0746dba10 100644 --- a/src/main/java/net/runelite/deob/pool/Integer.java +++ b/src/main/java/net/runelite/deob/pool/Integer.java @@ -11,12 +11,10 @@ public class Integer extends PoolEntry { private int value; - public Integer(ConstantPool pool) throws IOException + public Integer(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.INTEGER); - DataInputStream is = pool.getClassFile().getStream(); - value = is.readInt(); } diff --git a/src/main/java/net/runelite/deob/pool/InterfaceMethod.java b/src/main/java/net/runelite/deob/pool/InterfaceMethod.java index 836e62b148..0da3118783 100644 --- a/src/main/java/net/runelite/deob/pool/InterfaceMethod.java +++ b/src/main/java/net/runelite/deob/pool/InterfaceMethod.java @@ -20,12 +20,10 @@ public class InterfaceMethod extends PoolEntry this.nat = nat; } - public InterfaceMethod(ConstantPool pool) throws IOException + public InterfaceMethod(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.INTERFACE_METHOD_REF); - DataInputStream is = pool.getClassFile().getStream(); - classIndex = is.readUnsignedShort(); natIndex = is.readUnsignedShort(); } diff --git a/src/main/java/net/runelite/deob/pool/Long.java b/src/main/java/net/runelite/deob/pool/Long.java index 532dd049f2..c372c31a74 100644 --- a/src/main/java/net/runelite/deob/pool/Long.java +++ b/src/main/java/net/runelite/deob/pool/Long.java @@ -11,12 +11,10 @@ public class Long extends PoolEntry { private long value; - public Long(ConstantPool pool) throws IOException + public Long(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.LONG); - DataInputStream is = pool.getClassFile().getStream(); - value = is.readLong(); } diff --git a/src/main/java/net/runelite/deob/pool/Method.java b/src/main/java/net/runelite/deob/pool/Method.java index d7fa9d3c1b..91d2e34d44 100644 --- a/src/main/java/net/runelite/deob/pool/Method.java +++ b/src/main/java/net/runelite/deob/pool/Method.java @@ -20,12 +20,10 @@ public class Method extends PoolEntry this.nat = nat; } - public Method(ConstantPool pool) throws IOException + public Method(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.METHODREF); - DataInputStream is = pool.getClassFile().getStream(); - classIndex = is.readUnsignedShort(); natIndex = is.readUnsignedShort(); } diff --git a/src/main/java/net/runelite/deob/pool/NameAndType.java b/src/main/java/net/runelite/deob/pool/NameAndType.java index 85e6e2cede..58a7b12d3f 100644 --- a/src/main/java/net/runelite/deob/pool/NameAndType.java +++ b/src/main/java/net/runelite/deob/pool/NameAndType.java @@ -18,12 +18,10 @@ public class NameAndType extends PoolEntry /* type */ private Type type; - public NameAndType(ConstantPool pool) throws IOException + public NameAndType(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.NAME_AND_TYPE); - DataInputStream is = pool.getClassFile().getStream(); - nameIndex = is.readUnsignedShort(); descriptorIndex = is.readUnsignedShort(); } diff --git a/src/main/java/net/runelite/deob/pool/String.java b/src/main/java/net/runelite/deob/pool/String.java index 5bab46875c..b135e3f4a5 100644 --- a/src/main/java/net/runelite/deob/pool/String.java +++ b/src/main/java/net/runelite/deob/pool/String.java @@ -12,12 +12,10 @@ public class String extends PoolEntry private int stringIndex; private java.lang.String string; - public String(ConstantPool pool) throws IOException + public String(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.STRING); - DataInputStream is = pool.getClassFile().getStream(); - stringIndex = is.readUnsignedShort(); } diff --git a/src/main/java/net/runelite/deob/pool/UTF8.java b/src/main/java/net/runelite/deob/pool/UTF8.java index 95f3ca8cf7..e431e93837 100644 --- a/src/main/java/net/runelite/deob/pool/UTF8.java +++ b/src/main/java/net/runelite/deob/pool/UTF8.java @@ -10,12 +10,11 @@ public class UTF8 extends PoolEntry { private java.lang.String string; - public UTF8(ConstantPool pool) throws IOException + public UTF8(ConstantPool pool, DataInputStream is) throws IOException { super(ConstantType.UTF8); - DataInputStream ios = pool.getClassFile().getStream(); - string = ios.readUTF(); + string = is.readUTF(); } public UTF8(java.lang.String value) From ec034ce50ddf07d3ec3955821d0a4da96b3c5d5f Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 3 Oct 2015 00:37:59 -0400 Subject: [PATCH 42/58] Add junit as a test dependency --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index bc0a1b08cd..dfb330e6d2 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,12 @@ guava 18.0 + + junit + junit + 4.12 + test + 1.7 From fb10ab8daa9a372770adc4b6fec49a189fed265c Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 3 Oct 2015 11:42:04 -0400 Subject: [PATCH 43/58] dupx1 test --- .../java/net/runelite/deob/ClassFile.java | 11 ++ .../java/net/runelite/deob/Interfaces.java | 5 + src/main/java/net/runelite/deob/Method.java | 10 ++ src/main/java/net/runelite/deob/Methods.java | 5 + .../net/runelite/deob/attributes/Code.java | 1 + .../deob/attributes/code/Instructions.java | 5 + .../attributes/code/instructions/Dup_X1.java | 7 +- .../code/instructions/IConst_3.java | 2 +- .../attributes/code/instructions/ILoad.java | 2 +- .../code/instructions/IStore_0.java | 7 +- .../attributes/code/instructions/LDC_W.java | 10 ++ .../attributes/code/instructions/Pop.java | 8 +- .../attributes/code/instructions/VReturn.java | 5 + .../MultiplicationDeobfuscatorTest.java | 119 ++++++++++++++++++ 14 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java diff --git a/src/main/java/net/runelite/deob/ClassFile.java b/src/main/java/net/runelite/deob/ClassFile.java index c8713441ce..3320f250e8 100644 --- a/src/main/java/net/runelite/deob/ClassFile.java +++ b/src/main/java/net/runelite/deob/ClassFile.java @@ -61,6 +61,7 @@ public class ClassFile { this.group = group; + interfaces = new Interfaces(this); fields = new Fields(this); methods = new Methods(this); attributes = new Attributes(this); @@ -131,6 +132,16 @@ public class ClassFile this.name = new Class(name); } + public String getSuperName() + { + return super_class.getName(); + } + + public void setSuperName(String name) + { + super_class = new Class(name); + } + public Class getParentClass() { return this.super_class; diff --git a/src/main/java/net/runelite/deob/Interfaces.java b/src/main/java/net/runelite/deob/Interfaces.java index 4bee37f2df..f8a877721e 100644 --- a/src/main/java/net/runelite/deob/Interfaces.java +++ b/src/main/java/net/runelite/deob/Interfaces.java @@ -24,6 +24,11 @@ public class Interfaces interfaces.add(c.getPool().getClass(is.readUnsignedShort())); } + Interfaces(ClassFile c) + { + classFile = c; + } + public List getInterfaces() { return interfaces; diff --git a/src/main/java/net/runelite/deob/Method.java b/src/main/java/net/runelite/deob/Method.java index a915c47c5a..e32c63d51b 100644 --- a/src/main/java/net/runelite/deob/Method.java +++ b/src/main/java/net/runelite/deob/Method.java @@ -75,6 +75,11 @@ public class Method return attributes; } + public void setAttributes(Attributes a) + { + this.attributes = a; + } + public String getName() { return name; @@ -100,6 +105,11 @@ public class Method return (accessFlags & ACC_STATIC) != 0; } + public void setStatic() + { + accessFlags |= ACC_STATIC; + } + public boolean isSynchronized() { return (accessFlags & ACC_SYNCHRONIZED) != 0; diff --git a/src/main/java/net/runelite/deob/Methods.java b/src/main/java/net/runelite/deob/Methods.java index 63460f825b..dac43dc9f5 100644 --- a/src/main/java/net/runelite/deob/Methods.java +++ b/src/main/java/net/runelite/deob/Methods.java @@ -37,6 +37,11 @@ public class Methods m.write(out); } + public void addMethod(Method m) + { + methods.add(m); + } + public void removeMethod(Method m) { methods.remove(m); diff --git a/src/main/java/net/runelite/deob/attributes/Code.java b/src/main/java/net/runelite/deob/attributes/Code.java index 6dee991646..4ac3ccdc2e 100644 --- a/src/main/java/net/runelite/deob/attributes/Code.java +++ b/src/main/java/net/runelite/deob/attributes/Code.java @@ -23,6 +23,7 @@ public class Code extends Attribute exceptions = new Exceptions(this); this.attributes = new Attributes(this); + instructions = new Instructions(this); } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/Instructions.java b/src/main/java/net/runelite/deob/attributes/code/Instructions.java index 20170e8b36..2125c9c1a3 100644 --- a/src/main/java/net/runelite/deob/attributes/code/Instructions.java +++ b/src/main/java/net/runelite/deob/attributes/code/Instructions.java @@ -71,6 +71,11 @@ public class Instructions return instructions; } + public void addInstruction(Instruction i) + { + instructions.add(i); + } + public List getBlocks() { return blocks; diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java index 7c26c66d76..41a82e5ac3 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java @@ -12,10 +12,15 @@ import net.runelite.deob.attributes.code.instruction.types.DupInstruction; public class Dup_X1 extends Instruction implements DupInstruction { - public Dup_X1(Instructions instructions, InstructionType type, int pc) throws IOException + public Dup_X1(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); } + + public Dup_X1(Instructions instructions) + { + super(instructions, InstructionType.DUP_X1, -1); + } @Override public void execute(Frame frame) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java index 02af0586c6..80f4e35955 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_3.java @@ -21,7 +21,7 @@ public class IConst_3 extends Instruction implements PushConstantInstruction public IConst_3(Instructions instructions) { - super(instructions, InstructionType.ICONST_3, 0); + super(instructions, InstructionType.ICONST_3, -1); } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/ILoad.java b/src/main/java/net/runelite/deob/attributes/code/instructions/ILoad.java index b9b7403b07..88dd26a874 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/ILoad.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/ILoad.java @@ -24,7 +24,7 @@ public class ILoad extends Instruction implements LVTInstruction, WideInstructio public ILoad(Instructions instructions, int index) { - super(instructions, InstructionType.ILOAD, 0); + super(instructions, InstructionType.ILOAD, -1); this.index = index; ++length; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_0.java index 7b006d99a8..7bb7db6de1 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_0.java @@ -16,10 +16,15 @@ import java.io.IOException; public class IStore_0 extends Instruction implements LVTInstruction { - public IStore_0(Instructions instructions, InstructionType type, int pc) throws IOException + public IStore_0(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); } + + public IStore_0(Instructions instructions) + { + super(instructions, InstructionType.ISTORE_0, -1); + } @Override public void execute(Frame frame) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java index 303d944248..8064b069f5 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/LDC_W.java @@ -33,6 +33,11 @@ public class LDC_W extends Instruction implements PushConstantInstruction length += 2; } + public LDC_W(Instructions instructions, int value) + { + this(instructions, new net.runelite.deob.pool.Integer(value)); + } + @Override public void load(DataInputStream is) throws IOException { @@ -148,4 +153,9 @@ public class LDC_W extends Instruction implements PushConstantInstruction return super.makeSpecific(); } + + public int getConstantAsInt() + { + return (int) value.getObject(); + } } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Pop.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Pop.java index 03ede0dc36..44420a5bcf 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Pop.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Pop.java @@ -7,14 +7,18 @@ import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.StackContext; -import java.io.IOException; public class Pop extends Instruction { - public Pop(Instructions instructions, InstructionType type, int pc) throws IOException + public Pop(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); } + + public Pop(Instructions instructions) + { + super(instructions, InstructionType.POP, -1); + } @Override public void execute(Frame frame) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/VReturn.java b/src/main/java/net/runelite/deob/attributes/code/instructions/VReturn.java index 0e16aee782..952f3504e1 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/VReturn.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/VReturn.java @@ -14,6 +14,11 @@ public class VReturn extends Instruction implements ReturnInstruction { super(instructions, type, pc); } + + public VReturn(Instructions instructions) + { + super(instructions, InstructionType.RETURN, -1); + } @Override public void execute(Frame frame) diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java new file mode 100644 index 0000000000..1e1024152d --- /dev/null +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -0,0 +1,119 @@ +package net.runelite.deob.deobfuscators.arithmetic; + +import net.runelite.deob.ClassFile; +import net.runelite.deob.ClassGroup; +import net.runelite.deob.Deobfuscator; +import net.runelite.deob.Method; +import net.runelite.deob.Methods; +import net.runelite.deob.attributes.Attributes; +import net.runelite.deob.attributes.Code; +import net.runelite.deob.attributes.code.Instruction; +import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instructions.Dup_X1; +import net.runelite.deob.attributes.code.instructions.IConst_0; +import net.runelite.deob.attributes.code.instructions.IConst_3; +import net.runelite.deob.attributes.code.instructions.ILoad; +import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.IStore_0; +import net.runelite.deob.attributes.code.instructions.LDC_W; +import net.runelite.deob.attributes.code.instructions.Pop; +import net.runelite.deob.attributes.code.instructions.VReturn; +import net.runelite.deob.execution.Execution; +import net.runelite.deob.signature.Signature; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class MultiplicationDeobfuscatorTest +{ + private ClassGroup group; + private Code code; + private Instructions ins; + + @Before + public void init() + { + group = new ClassGroup(); + + ClassFile cf = new ClassFile(group); + cf.setName("test"); + cf.setSuperName("java/lang/Object"); + group.addClass(cf); + + Methods methods = cf.getMethods(); + Method method = new Method(methods, "func", new Signature("()V")); + method.setStatic(); + methods.addMethod(method); + + Attributes methodAttributes = method.getAttributes(); + + code = new Code(methodAttributes); + methodAttributes.addAttribute(code); + + ins = code.getInstructions(); + } + + // aload 2 + // ldc_w 1587543155 + // iload 4 + // imul + // dup_x1 + // ldc_w -2130376517 + // imul + // putfield class2/field279 I + // ldc_w -67313687 + // imul + // putstatic class29/field949 I + @Test + public void testDupX1() + { + code.setMaxStack(5); + + // vars[0] = 3 + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins) + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, 1587543155), + constant2 = new LDC_W(ins, -2130376517), + constant3 = new LDC_W(ins, -67313687); + + Instruction body[] = { + new IConst_0(ins), // for dup_x1 to place before this + constant1, + new ILoad(ins, 0), + new IMul(ins), + new Dup_X1(ins), + constant2, + new IMul(ins), + new Pop(ins), + new Pop(ins), + constant3, + new IMul(ins), + new Pop(ins), + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + // check execution runs ok + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1; + assert constant1.getConstantAsInt() * constant3.getConstantAsInt() == -1_095_175_765; + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1, constant1.getConstantAsInt()); + Assert.assertEquals(1, constant2.getConstantAsInt()); + Assert.assertEquals(-1_095_175_765, constant3.getConstantAsInt()); + } +} From f6f487ad6d16c505f053a43a523b2635b288bbc3 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 3 Oct 2015 12:48:51 -0400 Subject: [PATCH 44/58] Another dup1 test --- .../attributes/code/instructions/IAdd.java | 5 + .../net/runelite/deob/ClassGroupFactory.java | 30 +++++ .../MultiplicationDeobfuscatorTest.java | 113 ++++++++++++------ 3 files changed, 114 insertions(+), 34 deletions(-) create mode 100644 src/test/java/net/runelite/deob/ClassGroupFactory.java diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java index b6ec7a2d11..25e6501ac5 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java @@ -17,6 +17,11 @@ public class IAdd extends Instruction { super(instructions, type, pc); } + + public IAdd(Instructions instructions) + { + super(instructions, InstructionType.IADD, -1); + } @Override public void execute(Frame frame) diff --git a/src/test/java/net/runelite/deob/ClassGroupFactory.java b/src/test/java/net/runelite/deob/ClassGroupFactory.java new file mode 100644 index 0000000000..16fd6195ed --- /dev/null +++ b/src/test/java/net/runelite/deob/ClassGroupFactory.java @@ -0,0 +1,30 @@ +package net.runelite.deob; + +import net.runelite.deob.attributes.Attributes; +import net.runelite.deob.attributes.Code; +import net.runelite.deob.signature.Signature; + +public class ClassGroupFactory +{ + public static ClassGroup generateGroup() + { + ClassGroup group = new ClassGroup(); + + ClassFile cf = new ClassFile(group); + cf.setName("test"); + cf.setSuperName("java/lang/Object"); + group.addClass(cf); + + Methods methods = cf.getMethods(); + Method method = new Method(methods, "func", new Signature("()V")); + method.setStatic(); + methods.addMethod(method); + + Attributes methodAttributes = method.getAttributes(); + + Code code = new Code(methodAttributes); + methodAttributes.addAttribute(code); + + return group; + } +} diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index 1e1024152d..0986f93abb 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -1,15 +1,13 @@ package net.runelite.deob.deobfuscators.arithmetic; -import net.runelite.deob.ClassFile; import net.runelite.deob.ClassGroup; +import net.runelite.deob.ClassGroupFactory; import net.runelite.deob.Deobfuscator; -import net.runelite.deob.Method; -import net.runelite.deob.Methods; -import net.runelite.deob.attributes.Attributes; import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instructions.Dup_X1; +import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IConst_0; import net.runelite.deob.attributes.code.instructions.IConst_3; import net.runelite.deob.attributes.code.instructions.ILoad; @@ -19,40 +17,11 @@ import net.runelite.deob.attributes.code.instructions.LDC_W; import net.runelite.deob.attributes.code.instructions.Pop; import net.runelite.deob.attributes.code.instructions.VReturn; import net.runelite.deob.execution.Execution; -import net.runelite.deob.signature.Signature; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; public class MultiplicationDeobfuscatorTest { - private ClassGroup group; - private Code code; - private Instructions ins; - - @Before - public void init() - { - group = new ClassGroup(); - - ClassFile cf = new ClassFile(group); - cf.setName("test"); - cf.setSuperName("java/lang/Object"); - group.addClass(cf); - - Methods methods = cf.getMethods(); - Method method = new Method(methods, "func", new Signature("()V")); - method.setStatic(); - methods.addMethod(method); - - Attributes methodAttributes = method.getAttributes(); - - code = new Code(methodAttributes); - methodAttributes.addAttribute(code); - - ins = code.getInstructions(); - } - // aload 2 // ldc_w 1587543155 // iload 4 @@ -65,8 +34,12 @@ public class MultiplicationDeobfuscatorTest // imul // putstatic class29/field949 I @Test - public void testDupX1() + public void testDupX1_1() { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Instructions ins = code.getInstructions(); + code.setMaxStack(5); // vars[0] = 3 @@ -116,4 +89,76 @@ public class MultiplicationDeobfuscatorTest Assert.assertEquals(1, constant2.getConstantAsInt()); Assert.assertEquals(-1_095_175_765, constant3.getConstantAsInt()); } + + // aload_0 + // dup + // getfield class118/field2201 I + // ldc_w -2079217519 + // imul + // ldc -2079217519 + // iadd + // dup_x1 + // ldc_w 561453169 + // imul + // putfield class118/field2201 I + // ldc 561453169 + // imul + @Test + public void testDupX1_2() + { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Instructions ins = code.getInstructions(); + + code.setMaxStack(4); + + // vars[0] = 3 + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins) + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, -2079217519), + constant2 = new LDC_W(ins, -2079217519), + constant3 = new LDC_W(ins, 561453169), + constant4 = new LDC_W(ins, 561453169); + + Instruction body[] = { + new IConst_0(ins), // for dup_x1 to place before this + new ILoad(ins, 0), + constant1, + new IMul(ins), + constant2, + new IAdd(ins), + new Dup_X1(ins), // result, 0, result + constant3, + new IMul(ins), + new Pop(ins), + new Pop(ins), + constant4, + new IMul(ins), + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + assert constant1.getConstantAsInt() * constant3.getConstantAsInt() == 1; + assert constant2.getConstantAsInt() * constant4.getConstantAsInt() == 1; + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1, constant1.getConstantAsInt()); + Assert.assertEquals(1, constant2.getConstantAsInt()); + Assert.assertEquals(1, constant3.getConstantAsInt()); + Assert.assertEquals(1, constant4.getConstantAsInt()); + } } From 9ca81511626250ca464b5cd1506a0984e256f224 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 3 Oct 2015 23:31:00 -0400 Subject: [PATCH 45/58] Isolate a test I believe is wrong --- .../code/instructions/IConst_2.java | 2 +- .../attributes/code/instructions/IDiv.java | 5 + .../attributes/code/instructions/IStore.java | 2 +- .../code/instructions/IStore_1.java | 7 +- .../code/instructions/IStore_2.java | 7 +- .../deob/attributes/code/instructions/If.java | 10 ++ .../attributes/code/instructions/If0.java | 10 ++ .../attributes/code/instructions/NOP.java | 2 +- .../MultiplicationDeobfuscatorTest.java | 140 ++++++++++++++++++ 9 files changed, 180 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java index a51e1cc3ca..38ba4721da 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_2.java @@ -21,7 +21,7 @@ public class IConst_2 extends Instruction implements PushConstantInstruction public IConst_2(Instructions instructions) { - super(instructions, InstructionType.ICONST_2, 0); + super(instructions, InstructionType.ICONST_2, -1); } @Override diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IDiv.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IDiv.java index 37c001f8eb..4d39142f3f 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IDiv.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IDiv.java @@ -14,6 +14,11 @@ public class IDiv extends Instruction { super(instructions, type, pc); } + + public IDiv(Instructions instructions) + { + super(instructions, InstructionType.IDIV, -1); + } @Override public void execute(Frame frame) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java index e9893542b2..3283bbabeb 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore.java @@ -23,7 +23,7 @@ public class IStore extends Instruction implements LVTInstruction, WideInstructi public IStore(Instructions instructions, int index) { - super(instructions, InstructionType.ISTORE, 0); + super(instructions, InstructionType.ISTORE, -1); this.index = index; ++length; } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_1.java index 1479303179..5ec09ec4c7 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_1.java @@ -16,10 +16,15 @@ import java.io.IOException; public class IStore_1 extends Instruction implements LVTInstruction { - public IStore_1(Instructions instructions, InstructionType type, int pc) throws IOException + public IStore_1(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); } + + public IStore_1(Instructions instructions) + { + super(instructions, InstructionType.ISTORE_1, -1); + } @Override public void execute(Frame frame) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_2.java index 446174772d..cb9fe29e77 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IStore_2.java @@ -16,10 +16,15 @@ import java.io.IOException; public class IStore_2 extends Instruction implements LVTInstruction { - public IStore_2(Instructions instructions, InstructionType type, int pc) throws IOException + public IStore_2(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); } + + public IStore_2(Instructions instructions) + { + super(instructions, InstructionType.ISTORE_2, -1); + } @Override public void execute(Frame frame) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/If.java b/src/main/java/net/runelite/deob/attributes/code/instructions/If.java index 7d14cee235..c7e31b8b75 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/If.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/If.java @@ -26,6 +26,16 @@ public class If extends Instruction implements JumpingInstruction, ComparisonIns super(instructions, type, pc); } + public If(Instructions instructions, Instruction to) + { + super(instructions, InstructionType.IF_ICMPNE, -1); + + assert this != to; + assert to.getInstructions() == this.getInstructions(); + + this.to = to; + } + @Override public void load(DataInputStream is) throws IOException { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java b/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java index 4fb9f4272c..76ff52e671 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/If0.java @@ -26,6 +26,16 @@ public class If0 extends Instruction implements JumpingInstruction, ComparisonIn super(instructions, type, pc); } + public If0(Instructions instructions, Instruction to) + { + super(instructions, InstructionType.IFEQ, -1); + + assert this != to; + assert to.getInstructions() == this.getInstructions(); + + this.to = to; + } + @Override public void load(DataInputStream is) throws IOException { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/NOP.java b/src/main/java/net/runelite/deob/attributes/code/instructions/NOP.java index 9acc5b6211..4ec6d0c69a 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/NOP.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/NOP.java @@ -10,7 +10,7 @@ import java.io.IOException; public class NOP extends Instruction { - public NOP(Instructions instructions, InstructionType type, int pc) throws IOException + public NOP(Instructions instructions, InstructionType type, int pc) { super(instructions, type, pc); } diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index 0986f93abb..48171e8441 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -7,13 +7,23 @@ import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instructions.Dup_X1; +import net.runelite.deob.attributes.code.instructions.Goto; import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IConst_0; +import net.runelite.deob.attributes.code.instructions.IConst_1; +import net.runelite.deob.attributes.code.instructions.IConst_2; import net.runelite.deob.attributes.code.instructions.IConst_3; +import net.runelite.deob.attributes.code.instructions.IDiv; import net.runelite.deob.attributes.code.instructions.ILoad; import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.IStore; import net.runelite.deob.attributes.code.instructions.IStore_0; +import net.runelite.deob.attributes.code.instructions.IStore_1; +import net.runelite.deob.attributes.code.instructions.IStore_2; +import net.runelite.deob.attributes.code.instructions.If; +import net.runelite.deob.attributes.code.instructions.If0; import net.runelite.deob.attributes.code.instructions.LDC_W; +import net.runelite.deob.attributes.code.instructions.NOP; import net.runelite.deob.attributes.code.instructions.Pop; import net.runelite.deob.attributes.code.instructions.VReturn; import net.runelite.deob.execution.Execution; @@ -161,4 +171,134 @@ public class MultiplicationDeobfuscatorTest Assert.assertEquals(1, constant3.getConstantAsInt()); Assert.assertEquals(1, constant4.getConstantAsInt()); } + + //@Test +// public void testDupX1_3() +// { +// ClassGroup group = ClassGroupFactory.generateGroup(); +// Code code = group.findClass("test").findMethod("func").getCode(); +// Instructions ins = code.getInstructions(); +// +// code.setMaxStack(2); +// +// Instruction[] prepareVariables = { +// new IConst_3(ins), +// new IStore_0(ins), +// new IConst_3(ins), +// new IStore_1(ins), +// new IConst_3(ins), +// new IStore_2(ins), +// }; +// +// for (Instruction i : prepareVariables) +// ins.addInstruction(i); +// +// LDC_W constant1 = new LDC_W(ins, 1381104939), +// constant2 = new LDC_W(ins, 1381104939), +// constant3 = new LDC_W(ins, 981643079), +// constant4 = new LDC_W(ins, 1807370871), +// constant5 = new LDC_W(ins, 1807370871), +// constant6 = new LDC_W(ins, 981643079); +// +// NOP label1 = new NOP(ins), +// label2 = new NOP(ins); +// +// Instruction body[] = { +// new IConst_1(ins), +// new ILoad(ins, 0), +// new If(ins, label1), +// constant1, +// new ILoad(ins, 1), +// new IMul(ins), +// new Goto(ins, label2), +// label1, +// new ILoad(ins, 1), +// constant2, +// new IMul(ins), +// constant3, +// new ILoad(ins, 2), +// constant4, +// new IMul(ins), +// new IMul(ins), +// new IAdd(ins), +// new IConst_2(ins), +// new IDiv(ins), +// label2, +// constant5, +// new IMul(ins), +// constant6, +// new IMul(ins), +// new IStore(ins, 3), +// new VReturn(ins) +// }; +// +// for (Instruction i : body) +// ins.addInstruction(i); +// +// Execution e = new Execution(group); +// e.populateInitialMethods(); +// e.run(); +// +// Deobfuscator d = new MultiplicationDeobfuscator(); +// d.run(group); +// +// Assert.assertEquals(1381104939, constant1.getConstantAsInt()); +// Assert.assertEquals(1381104939, constant2.getConstantAsInt()); +// Assert.assertEquals(981643079, constant3.getConstantAsInt()); +// Assert.assertEquals(1807370871, constant4.getConstantAsInt()); +// Assert.assertEquals(1807370871, constant5.getConstantAsInt()); +// Assert.assertEquals(981643079, constant6.getConstantAsInt()); +// } + + @Test + public void testDupX1_3() + { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Instructions ins = code.getInstructions(); + + code.setMaxStack(2); + + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins), + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, 1381104939), + constant2 = new LDC_W(ins, 1381104939), + constant3 = new LDC_W(ins, 981643079); + + NOP label1 = new NOP(ins); + + Instruction body[] = { + constant1, + new ILoad(ins, 0), + new IMul(ins), + new IConst_0(ins), + new If0(ins, label1), + constant2, + new IMul(ins), + label1, + constant3, + new IMul(ins), + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1381104939, constant1.getConstantAsInt()); + Assert.assertEquals(1381104939, constant2.getConstantAsInt()); + Assert.assertEquals(981643079, constant3.getConstantAsInt()); + } } From 26b54f6278e87c1ad475d0e28d4e4eb7cb3827ea Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 4 Oct 2015 20:15:25 -0400 Subject: [PATCH 46/58] save --- src/main/java/net/runelite/deob/Deob.java | 86 +++++++++---------- .../MultiplicationDeobfuscator.java | 28 +++++- 2 files changed, 69 insertions(+), 45 deletions(-) diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index b82ce45710..ae12605449 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -41,50 +41,50 @@ public class Deob //run(group, new RenameUnique()); - // remove except RuntimeException - run(group, new RuntimeExceptions()); +// // remove except RuntimeException +// run(group, new RuntimeExceptions()); +// +// // remove unused methods +// run(group, new UnusedMethods()); +// +// run(group, new UnreachedCode()); +// +// // remove illegal state exceptions, frees up some parameters +// run(group, new IllegalStateExceptions()); +// +// // remove constant logically dead parameters +// run(group, new ConstantParameter()); +// +// // remove unhit blocks +// run(group, new UnreachedCode()); +// +// // remove unused parameters +// run(group, new UnusedParameters()); +// +// // remove jump obfuscation +// //new Jumps().run(group); +// +// // remove unused fields +// run(group, new UnusedFields()); +// +// // remove unused methods, again? +// run(group, new UnusedMethods()); +// +// run(group, new MethodInliner()); +// +// run(group, new MethodMover()); +// +// run(group, new FieldInliner()); +// +// // XXX this is broken because when moving clinit around, some fields can depend on other fields +// // (like multianewarray) +// //new FieldMover().run(group); +// +// run(group, new UnusedClass()); +// +// run(group, new ModArith()); - // remove unused methods - run(group, new UnusedMethods()); - - run(group, new UnreachedCode()); - - // remove illegal state exceptions, frees up some parameters - run(group, new IllegalStateExceptions()); - - // remove constant logically dead parameters - run(group, new ConstantParameter()); - - // remove unhit blocks - run(group, new UnreachedCode()); - - // remove unused parameters - run(group, new UnusedParameters()); - - // remove jump obfuscation - //new Jumps().run(group); - - // remove unused fields - run(group, new UnusedFields()); - - // remove unused methods, again? - run(group, new UnusedMethods()); - - run(group, new MethodInliner()); - - run(group, new MethodMover()); - - run(group, new FieldInliner()); - - // XXX this is broken because when moving clinit around, some fields can depend on other fields - // (like multianewarray) - //new FieldMover().run(group); - - run(group, new UnusedClass()); - - new ModArith().run(group); - -// new MultiplicationDeobfuscator().run(group); + new MultiplicationDeobfuscator().run(group); // new MultiplyOneDeobfuscator().run(group); // diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index ea6b4cc598..8b3a391af8 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -244,6 +244,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator int count = 0; + int mcount = 0; for (Frame frame : e.processedFrames) outer: @@ -252,12 +253,35 @@ public class MultiplicationDeobfuscator implements Deobfuscator Instruction instruction = ictx.getInstruction(); Instructions instructions = instruction.getInstructions(); -// if (!frame.getMethod().getMethods().getClassFile().getName().equals("class118")) -// continue; + String cname = frame.getMethod().getMethods().getClassFile().getName(); if (!(instruction instanceof IMul)) continue; +// if (cname.equals("client")) +// { +// // 7500 works ok +// // 8250 doesnt work +// //if (mcount++ > 8250) +// ++mcount; +// if (!(mcount >= 7500 && mcount <= 8250)) +// continue; +// } +// else +// { +// continue; +// } +//field721 = (-1 != var5 && 1 != var5 ? +// (class139.field2363 * 1381104939 + 981643079 * field721 * 1807370871) / 2 : +// 1381104939 * class139.field2363) +// * 1807370871 * 981643079; +// +//field721 = (-1 != var5 && 1 != var5 ? +// (class139.field2363 * 1381104939 + 981643079 * field721 * 1807370871) / 2 : +// 1 * class139.field2363) +// * 1 * 1381104939; + + MultiplicationExpression expression; try { From 86bddfed9b20840f463face39d90dafbced779a6 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 7 Oct 2015 15:23:54 -0400 Subject: [PATCH 47/58] This fixes the test, although there are simply multiplication expressions not being simplified now in the same expr --- .../MultiplicationDeobfuscator.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 8b3a391af8..c6749cdb1a 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -1,7 +1,9 @@ package net.runelite.deob.deobfuscators.arithmetic; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; @@ -11,8 +13,6 @@ import net.runelite.deob.attributes.code.instruction.types.DupInstruction; import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instructions.BiPush; -import net.runelite.deob.attributes.code.instructions.Dup; -import net.runelite.deob.attributes.code.instructions.Dup_X1; import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.ISub; @@ -215,6 +215,26 @@ public class MultiplicationDeobfuscator implements Deobfuscator return me; } + // for each instruction ctx in ths expression, see if it !equals any other for each ins? + + private List getInsInExpr(InstructionContext ctx, Set set) + { + List l = new ArrayList<>(); + + if (ctx == null || set.contains(ctx.getInstruction())) + return l; + + set.add(ctx.getInstruction()); + + l.add(ctx); + for (StackContext s : ctx.getPops()) + l.addAll(getInsInExpr(s.getPushed(), set)); + for (StackContext s : ctx.getPushes()) + l.addAll(getInsInExpr(s.getPopped(), set)); + + return l; + } + private boolean isOnlyPath(Execution execution, InstructionContext ctx) { Collection ins = execution.getInstructonContexts(ctx.getInstruction()); @@ -299,8 +319,11 @@ public class MultiplicationDeobfuscator implements Deobfuscator // continue; // there can only be one path to here, or else combinging would change code logic - if (!isOnlyPath(e, ictx)) - continue; + List ilist = this.getInsInExpr(ictx, new HashSet()); + for (InstructionContext i2 : ilist) + if (i2.getInstruction() instanceof IMul) + if (!isOnlyPath(e, i2)) + continue outer; if (done.contains(instruction)) From f4c004b7ad1a2dba31445ec70fd3d7ae17ca1782 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 7 Oct 2015 17:20:02 -0400 Subject: [PATCH 48/58] Add more to test, this fails --- .../arithmetic/MultiplicationDeobfuscatorTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index 48171e8441..006d5f1512 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -269,11 +269,14 @@ public class MultiplicationDeobfuscatorTest LDC_W constant1 = new LDC_W(ins, 1381104939), constant2 = new LDC_W(ins, 1381104939), - constant3 = new LDC_W(ins, 981643079); + constant3 = new LDC_W(ins, 981643079), + constant4 = new LDC_W(ins, 1807370871), + constant5 = new LDC_W(ins, 981643079); NOP label1 = new NOP(ins); Instruction body[] = { + constant4, constant1, new ILoad(ins, 0), new IMul(ins), @@ -284,6 +287,10 @@ public class MultiplicationDeobfuscatorTest label1, constant3, new IMul(ins), + new IMul(ins), // constant4 + constant5, + new IMul(ins), + new Pop(ins), new VReturn(ins) }; @@ -294,11 +301,15 @@ public class MultiplicationDeobfuscatorTest e.populateInitialMethods(); e.run(); + assert constant4.getConstantAsInt() * constant5.getConstantAsInt() == 1; + Deobfuscator d = new MultiplicationDeobfuscator(); d.run(group); Assert.assertEquals(1381104939, constant1.getConstantAsInt()); Assert.assertEquals(1381104939, constant2.getConstantAsInt()); Assert.assertEquals(981643079, constant3.getConstantAsInt()); + Assert.assertEquals(1, constant4.getConstantAsInt()); + Assert.assertEquals(1, constant5.getConstantAsInt()); } } From 9b4f4242ebf31c22bdab6a7f35481c3d1d7071ff Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 8 Oct 2015 17:29:31 -0400 Subject: [PATCH 49/58] hey this passes the test but doesnt compile. allow tracking more than one pops for stackctx. --- .../ModularArithmeticDeobfuscation.java | 824 ------------------ .../MultiplicationDeobfuscator.java | 99 ++- .../net/runelite/deob/execution/Frame.java | 2 + .../deob/execution/InstructionContext.java | 3 +- .../runelite/deob/execution/StackContext.java | 14 +- .../MultiplicationDeobfuscatorTest.java | 19 +- 6 files changed, 81 insertions(+), 880 deletions(-) delete mode 100644 src/main/java/net/runelite/deob/deobfuscators/ModularArithmeticDeobfuscation.java diff --git a/src/main/java/net/runelite/deob/deobfuscators/ModularArithmeticDeobfuscation.java b/src/main/java/net/runelite/deob/deobfuscators/ModularArithmeticDeobfuscation.java deleted file mode 100644 index 927fb5c13f..0000000000 --- a/src/main/java/net/runelite/deob/deobfuscators/ModularArithmeticDeobfuscation.java +++ /dev/null @@ -1,824 +0,0 @@ -package net.runelite.deob.deobfuscators; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import net.runelite.deob.ClassFile; -import net.runelite.deob.ClassGroup; -import net.runelite.deob.Deobfuscator; -import net.runelite.deob.Field; -import net.runelite.deob.attributes.code.Instruction; -import net.runelite.deob.attributes.code.instruction.types.FieldInstruction; -import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; -import net.runelite.deob.attributes.code.instruction.types.InvokeInstruction; -import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; -import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; -import net.runelite.deob.attributes.code.instructions.IMul; -import net.runelite.deob.execution.Execution; -import net.runelite.deob.execution.Frame; -import net.runelite.deob.execution.InstructionContext; -import net.runelite.deob.execution.StackContext; - -public class ModularArithmeticDeobfuscation implements Deobfuscator -{ - private Set obfuscatedFields; // reliability of these sucks - - static class Magic - { - Field field; - int getter, setter; - boolean unknownGetter, unknownSetter; - } - - static class Magics - { - Map magic = new HashMap<>(); - - Magic getMagic(Field field) - { - Magic m = magic.get(field); - if (m != null) - return m; - - m = new Magic(); - m.field = field; - magic.put(field, m); - return m; - } - - void pass1() - { - int good = 0, bad = 0, calculated = 0, mismatch = 0; - for (Magic m : new ArrayList<>(magic.values())) - if (m.getter == 0 && m.setter == 0) - { - magic.remove(m.field); - ++bad; - } - else if (m.getter == 0) - { - m.unknownGetter = false; - m.getter = modInverse(m.setter); - ++calculated; - } - else if (m.setter == 0) - { - m.unknownSetter = false; - m.setter = modInverse(m.getter); - ++calculated; - } - else if (m.getter != modInverse(m.setter) || m.setter != modInverse(m.getter)) - { - magic.remove(m.field); - ++mismatch; - } - else - { - ++good; - } - - System.out.println("Pass 1: Bad: " + bad + ", good: " + good + ", calculated " + calculated + ", mismatch: " + mismatch); - } - - void pass2() - { - int found = 0; - for (Magic m : new ArrayList<>(magic.values())) - { - if (!m.unknownGetter && !m.unknownSetter && (m.setter != 0 || m.getter != 0)) - { - ++found; - } - } - System.out.println("Pass 2: Calculated " + found); - } - - void merge(Magics other) - { - int merged = 0; - for (Magic m : other.magic.values()) - { - Field f = m.field; - - if (!this.magic.containsKey(f)) - { - this.magic.put(f, m); - ++merged; - continue; - } - - System.err.println("field exists in both pass 1 and 2"); - } - System.out.println("Merged " + merged); - } - } - - private Field convertFieldFromPool(ClassGroup group, net.runelite.deob.pool.Field field) - { - ClassFile cf = group.findClass(field.getClassEntry().getName()); - if (cf == null) - return null; - return cf.findFieldDeep(field.getNameAndType()); - } - - private List checkDown(InstructionContext context) - { - List fields = new ArrayList<>(); - - if (context.getInstruction() instanceof FieldInstruction) - { - FieldInstruction fi = (FieldInstruction) context.getInstruction(); - fields.add(fi.getField()); - } - - for (StackContext ctx : context.getPops()) - { - InstructionContext i = ctx.getPushed(); - - fields.addAll(checkDown(i)); - } - - return fields; - } - - private List checkUp(InstructionContext context) - { - List fields = new ArrayList<>(); - - if (context.getInstruction() instanceof InvokeInstruction) - { - // field = func(field * constant), the output of the function isn't directly related to the result of field * constant - return fields; - } - - if (context.getInstruction() instanceof FieldInstruction) - { - FieldInstruction fi = (FieldInstruction) context.getInstruction(); - fields.add(fi.getField()); - } - - for (StackContext ctx : context.getPushes()) - { - InstructionContext i = ctx.getPopped(); - - if (i == null) - continue; - - fields.addAll(checkUp(i)); - } - - return fields; - } - - /* check there are no other fields */ - private boolean checkFields(Magics goodMagics, ClassGroup group, Set obFields, net.runelite.deob.pool.Field imulField, InstructionContext context) - { - List fields = new ArrayList<>(); - fields.addAll(checkUp(context)); - fields.addAll(checkDown(context)); - - assert !fields.isEmpty(); - - for (net.runelite.deob.pool.Field f : fields) - { - if (f.equals(imulField)) - continue; - - Field field = convertFieldFromPool(group, f); - assert field != null; - - if (!obFields.contains(field)) - continue; - - return false; - } - - return true; - } - - private List getDown(InstructionContext context) - { - List instructions = new ArrayList<>(); - - instructions.add(context); - - for (StackContext ctx : context.getPops()) - { - InstructionContext i = ctx.getPushed(); - - instructions.addAll(getDown(i)); - } - - return instructions; - } - - private List getInstructions(InstructionContext context) - { - List instructions = new ArrayList<>(); - - instructions.add(context); - - instructions.addAll(getDown(context)); - - return instructions; - } - - private Set getObfuscatedFields(Execution execution, ClassGroup group) - { - Set fields = new HashSet<>(); - - // XXX this detects field = field * constant as ob when field isn't - - for (Frame frame : execution.processedFrames) - { - for (InstructionContext ctx : frame.getInstructions()) - { - if (ctx.getInstruction() instanceof IMul) - { - Instruction one = ctx.getPops().get(0).getPushed().getInstruction(); - Instruction two = ctx.getPops().get(1).getPushed().getInstruction(); - - PushConstantInstruction pc = null; - GetFieldInstruction gf = null; - if (one instanceof PushConstantInstruction && two instanceof GetFieldInstruction) - { - pc = (PushConstantInstruction) one; - gf = (GetFieldInstruction) two; - } - else if (two instanceof PushConstantInstruction && one instanceof GetFieldInstruction) - { - pc = (PushConstantInstruction) two; - gf = (GetFieldInstruction) one; - } - - if (pc == null) - continue; - - // get Field from pool Field - net.runelite.deob.pool.Field field = gf.getField(); - Field f = group.findClass(field.getClassEntry().getName()).findFieldDeep(field.getNameAndType()); - - assert f != null; - - fields.add(f); - } - else if (ctx.getInstruction() instanceof SetFieldInstruction) - { - SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction(); - - StackContext value = ctx.getPops().get(0); // what setfield pops as value - if (!(value.getPushed().getInstruction() instanceof IMul)) - continue; - - Instruction one = value.getPushed().getPops().get(0).getPushed().getInstruction(); - Instruction two = value.getPushed().getPops().get(1).getPushed().getInstruction(); - - PushConstantInstruction pc = null; - Instruction other = null; - if (one instanceof PushConstantInstruction) - { - pc = (PushConstantInstruction) one; - other = two; - } - else if (two instanceof PushConstantInstruction) - { - pc = (PushConstantInstruction) two; - other = one; - } - - if (pc == null) - continue; - - // get Field from pool Field - net.runelite.deob.pool.Field field = sf.getField(); - Field f = group.findClass(field.getClassEntry().getName()).findFieldDeep(field.getNameAndType()); - - assert f != null; - - fields.add(f); - } - } - } - - return fields; - } - - private void detectSetters(Magics goodMagics, Magics workMagics, Execution execution, ClassGroup group, InstructionContext ctx) - { - if (!(ctx.getInstruction() instanceof SetFieldInstruction)) - return; - - SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction(); - - StackContext value = ctx.getPops().get(0); // what setfield pops as value - if (!(value.getPushed().getInstruction() instanceof IMul)) - return; - - Instruction one = value.getPushed().getPops().get(0).getPushed().getInstruction(); - Instruction two = value.getPushed().getPops().get(1).getPushed().getInstruction(); - - PushConstantInstruction pc = null; - Instruction other = null; - if (one instanceof PushConstantInstruction) - { - pc = (PushConstantInstruction) one; - other = two; - } - else if (two instanceof PushConstantInstruction) - { - pc = (PushConstantInstruction) two; - other = one; - } - - if (pc == null) - return; - - if (!checkFields(goodMagics, group, obfuscatedFields, sf.getField(), value.getPushed())) - return; - - //System.out.println("Setter " + sf.getField().getClassEntry().getName() + "." + sf.getField().getNameAndType().getName() + " -> " + pc.getConstant().toString()); - - int constant = Integer.parseInt(pc.getConstant().toString()); - try - { - modInverse(constant); - } - catch (ArithmeticException ex) - { - //System.err.println("Constant " + constant + " passed setter logic tests but is not inversable"); - //printWhatCalls(execution, frame.getMethod(), 0); - return; // if the constant isn't inversable then it can't be the right one - } - - Field field = convertFieldFromPool(group, sf.getField()); - Magic magic = workMagics.getMagic(field); - - if (!magic.unknownSetter) - { - if (magic.setter == 0) - magic.setter = constant; - else if (magic.setter != constant) - { - magic.setter = 0; - magic.unknownSetter = true; - } - } - } - - private void detectGetters(Magics goodMagics, Magics workMagics, Execution execution, ClassGroup group, InstructionContext ctx) - { - if (!(ctx.getInstruction() instanceof IMul)) - return; - - // check for push constant and for get field instruction - Instruction one = ctx.getPops().get(0).getPushed().getInstruction(); - Instruction two = ctx.getPops().get(1).getPushed().getInstruction(); - - PushConstantInstruction pc = null; - GetFieldInstruction gf = null; - if (one instanceof PushConstantInstruction && two instanceof GetFieldInstruction) - { - pc = (PushConstantInstruction) one; - gf = (GetFieldInstruction) two; - } - else if (two instanceof PushConstantInstruction && one instanceof GetFieldInstruction) - { - pc = (PushConstantInstruction) two; - gf = (GetFieldInstruction) one; - } - - if (pc == null) - return; - - int constant = Integer.parseInt(pc.getConstant().toString()); - - StackContext push = ctx.getPushes().get(0); // result of imul operation - InstructionContext popCtx = push.getPopped(); // instruction which popped the result of mul - - if (popCtx == null) - { - return; - //System.err.println("Stack ctx never popped! Pushed by " + push.getPushed().getInstruction()); - //int i = frame.getInstructions().indexOf(push.getPushed().getInstruction()); - //System.err.println("next ins is " + frame.getInstructions().get(i + 1).getInstruction()); - } - - if (!checkFields(goodMagics, group, obfuscatedFields, gf.getField(), ctx)) - return; - - try - { - modInverse(constant); - } - catch (ArithmeticException ex) - { - //System.err.println("Constant " + constant + " passed getter logic tests but is not inversable"); - //printWhatCalls(execution, frame.getMethod(), 0); - return; // if the constant isn't inversable then it can't be the right one - } - - // get Field from pool Field - net.runelite.deob.pool.Field field = gf.getField(); - Field f = group.findClass(field.getClassEntry().getName()).findFieldDeep(field.getNameAndType()); - - Magic magic = workMagics.getMagic(f); - - if (!magic.unknownGetter) - { - if (magic.getter == 0) - magic.getter = constant; - else if (magic.getter != constant) - { - magic.getter = 0; - magic.unknownGetter = true; - } - } - } - - private void detectCombined(Magics goodMagics, Magics workMagics, Execution execution, ClassGroup group, InstructionContext ctx) - { - // look for put involving one other field, assume constant is combined field getter/setter - - if (!(ctx.getInstruction() instanceof SetFieldInstruction)) - return; - - SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction(); - Field thisField = convertFieldFromPool(group, sf.getField()); - - List ins = getInstructions(ctx); - - Field other = null; - int constant = 0; - for (InstructionContext i : ins) - if (i.getInstruction() instanceof FieldInstruction) - { - FieldInstruction fin = (FieldInstruction) i.getInstruction(); - if (fin.getField().equals(sf.getField())) - continue; - - if (other != null) - return; - - other = convertFieldFromPool(group, fin.getField()); - } - else if (i.getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); - try - { - constant = Integer.parseInt(pci.getConstant().toString()); - } - catch (NumberFormatException ex) - { - return; - } - } - - if (other == null || constant == 0) - return; - - if (goodMagics.magic.containsKey(thisField) && goodMagics.magic.containsKey(other)) - return; - - if (!thisField.getType().toString().equals("I") || !other.getType().toString().equals("I")) - return; - - // thisField = operations with field/constant - - //if (obfuscatedFields.contains(thisField) && obfuscatedFields.contains(other)) - { - // constant is thisField setter * otherField getter - - Magic thisMagic = goodMagics.magic.get(thisField); - Magic otherMagic = goodMagics.magic.get(other); - - if (thisMagic == null && otherMagic == null) - { - System.err.println("Combined fields with no known good magic"); - return; - } - - //if (thisMagic != null && otherMagic != null) - //{ - // return; // check? - //} - - if (thisMagic == null) - { - //System.out.println("Combined 1"); - - // this = other * constant - // constant = other getter * this setter - // solve for this setter - // this setter = constant * modInverse(other.getter) - - int thisSetter = constant * modInverse(otherMagic.getter); - - if (thisSetter == 1) - { - System.out.println(thisField.getFields().getClassFile().getName() + "." + thisField.getName() + " is not obd"); - // this means that this field isn't obbed - obfuscatedFields.remove(thisField); - otherMagic.setter = constant; - return; - } - - System.out.println("Calculated setter for " + thisField.getFields().getClassFile().getName() + "." + thisField.getName() + " to be " + thisSetter); - - Magic m = workMagics.getMagic(thisField); - - if (!m.unknownSetter) - if (m.setter != 0 && m.setter != thisSetter) - { - System.err.println("Calculated setter mismatch"); - m.unknownSetter = true; - m.setter = 0; - } - - m.setter = thisSetter; - } - else if (otherMagic == null) - { - //System.out.println("Combined 2"); - - // this = other * constant - // constant = other getter * this setter - // solve for other getter - // other getter = constant * modInverse(this setter) - - int otherGetter = constant * modInverse(thisMagic.setter); - - if (otherGetter == 1) - { - System.out.println(other.getFields().getClassFile().getName() + "." + other.getName() + " is not obd"); - obfuscatedFields.remove(other); - thisMagic.getter = constant; - return; - } - - System.out.println("Calculated getter for " + other.getFields().getClassFile().getName() + "." + other.getName() + " to be " + otherGetter); - - Magic m = workMagics.getMagic(other); - - if (!m.unknownGetter) - if (m.getter != 0 && m.getter != otherGetter) - { - System.err.println("Calculated getter mismatch"); - m.unknownGetter = true; - m.getter = 0; - } - - m.getter = otherGetter; - } - } - /* - else if (obfuscatedFields.contains(thisField)) - { - // constant is this fields setter - System.out.println("Only one field is obd 1 " + thisField.getFields().getClassFile().getName() + "." + thisField.getName() - + ", " + other.getFields().getClassFile().getName() + "." + other.getName()); - } - else if (obfuscatedFields.contains(other)) - { - // constant is other fields getter - System.out.println("Only one field is obd 2"); - } - else - { - System.err.println("detected combined field with both fields non obfuscated. " + thisField.getFields().getClassFile().getName() + "." + thisField.getName() - + ", " + other.getFields().getClassFile().getName() + "." + other.getName()); - //return; - }*/ - } - - private void check(Magics magics) - { - int missing = 0, mismatch = 0, good = 0, half = 0; - for (Field f : obfuscatedFields) - { - Magic magic = magics.magic.get(f); - - if (magic == null) - { - System.err.println(f.getFields().getClassFile().getName() + "." + f.getName() + " is obfuscated, but no magic found"); - ++missing; - continue; - } - - if (magic.getter != 0 && magic.setter != 0) - { - if (magic.getter != modInverse(magic.setter) || magic.setter != modInverse(magic.getter)) - { - ++mismatch; - System.err.println(f.getFields().getClassFile().getName() + "." + f.getName() + " has mismatch, get " + magic.getter + ", set " + magic.setter + ", modInverse(get) " + modInverse(magic.getter) + ", modInverse(set) " + modInverse(magic.setter)); - } - else - { - ++good; - //System.out.println(f.getFields().getClassFile().getName() + "." + f.getName() + " has get " + magic.getter + ", set " + magic.setter); - } - } - else - { - ++half; - System.out.println(f.getFields().getClassFile().getName() + "." + f.getName() + " 2 has get " + magic.getter + ", set " + magic.setter); - } - } - System.out.println("Check done missing: "+ missing + ", mismatch: " + mismatch + ", good: " + good + ", half: " + half); - } - - private void run(Magics magics /* known good */, Magics work, Execution execution, ClassGroup group) - { - obfuscatedFields = getObfuscatedFields(execution, group); - - for (Frame frame : execution.processedFrames) - { - for (InstructionContext ctx : frame.getInstructions()) - { - if (magics == null) - { - detectGetters(magics, work, execution, group, ctx); - detectSetters(magics, work, execution, group, ctx); - } - else - if (magics != null) - detectCombined(magics, work, execution, group, ctx); - } - } - - //if (magics == null) - //check(work); - } - - private static BigInteger modInverse(BigInteger val, int bits) - { - BigInteger shift = BigInteger.ONE.shiftLeft(bits); - return val.modInverse(shift); - } - - private static int modInverse(int val) - { - return modInverse(BigInteger.valueOf(val), 32).intValue(); - } - - private static long modInverse(long val) - { - return modInverse(BigInteger.valueOf(val), 64).longValue(); - } - - @Override - public void run(ClassGroup group) - { - group.buildClassGraph(); - - Execution execution = new Execution(group); - execution.populateInitialMethods(); - execution.run(); - - Magics work = new Magics(); - run(null, work, execution, group); - work.pass1(); -// check(work); - System.out.println("END OF PASS 1"); - - Magics magics = work; - work = new Magics(); - run(magics, work, execution, group); - work.pass2(); - - magics.merge(work); - - check(magics); - - replace(execution, group, magics); - } - - private void replace(Execution execution, ClassGroup group, Magics magics) - { - Set done = new HashSet<>(); - int replaced = 0; - for (Frame frame : execution.processedFrames) - { - for (InstructionContext ctx : frame.getInstructions()) - { - if (ctx.getInstruction() instanceof IMul) - { - Instruction one = ctx.getPops().get(0).getPushed().getInstruction(); - Instruction two = ctx.getPops().get(1).getPushed().getInstruction(); - - PushConstantInstruction pc = null; - GetFieldInstruction gf = null; - if (one instanceof PushConstantInstruction && two instanceof GetFieldInstruction) - { - pc = (PushConstantInstruction) one; - gf = (GetFieldInstruction) two; - } - else if (two instanceof PushConstantInstruction && one instanceof GetFieldInstruction) - { - pc = (PushConstantInstruction) two; - gf = (GetFieldInstruction) one; - } - - if (pc == null) - continue; - - Magic m = magics.magic.get(this.convertFieldFromPool(group, gf.getField())); - if (m == null) - { - System.out.println("No magc for field " + gf.getField()); - continue; - } - - if (done.contains(ctx.getInstruction())) - continue; - done.add(ctx.getInstruction()); - - int constant = Integer.parseInt(pc.getConstant().toString()); - - // we have field * constant - - // eg constant is 42 * getter do * modInverse(getter) to get result - - //assert m.setter == modInverse(m.getter); - int newConstant = constant * m.setter; - - Instruction i2 = pc.setConstant(new net.runelite.deob.pool.Integer(newConstant)); - assert i2 == (Instruction) pc; - if (newConstant != 1) - System.out.println("new constant: " + newConstant); - else - ++replaced; - } - else if (ctx.getInstruction() instanceof SetFieldInstruction) - { - SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction(); - StackContext value = ctx.getPops().get(0); // what setfield pops as value - - if (value.getPushed().getInstruction() instanceof PushConstantInstruction) - { - // field = constant - PushConstantInstruction pi = (PushConstantInstruction) value.getPushed().getInstruction(); - - Magic m = magics.magic.get(this.convertFieldFromPool(group, sf.getField())); - if (m == null) - continue; - - int constant = Integer.parseInt(pi.getConstant().toString()); - - if (done.contains(ctx.getInstruction())) - continue; - done.add(ctx.getInstruction()); - - // field = setter * value, solve for value by * modInverse(setter) - int newConstant = constant * m.getter; - Instruction i2 = pi.setConstant(new net.runelite.deob.pool.Integer(newConstant)); - assert i2 == (Instruction) pi; - ++replaced; - } - else if (value.getPushed().getInstruction() instanceof IMul) - { - InstructionContext imul = value.getPushed(); - - StackContext one = imul.getPops().get(0), two = imul.getPops().get(1); - - PushConstantInstruction pc; - if (one.getPushed().getInstruction() instanceof PushConstantInstruction) - { - pc = (PushConstantInstruction) one.getPushed().getInstruction(); - } - else if (two.getPushed().getInstruction() instanceof PushConstantInstruction) - { - pc = (PushConstantInstruction) two.getPushed().getInstruction(); - } - else - { - continue; - } - - int constant = Integer.parseInt(pc.getConstant().toString()); - - Magic m = magics.magic.get(this.convertFieldFromPool(group, sf.getField())); - if (m == null) - continue; - - if (done.contains(ctx.getInstruction())) - continue; - done.add(ctx.getInstruction()); - - // field = expression * constant - int newConstant = constant * m.getter; - Instruction i2 = pc.setConstant(new net.runelite.deob.pool.Integer(newConstant)); - assert i2 == (Instruction) pc; - ++replaced; - } - } - } - } - System.out.println("Replaced " + replaced + " constants"); - } -} diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index c6749cdb1a..9ee09713dc 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; @@ -42,7 +43,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator System.out.println("Total changed " + count); } - private MultiplicationExpression parseExpression(InstructionContext ctx) + private MultiplicationExpression parseExpression(Execution e, InstructionContext ctx) { MultiplicationExpression me = new MultiplicationExpression(); @@ -59,6 +60,12 @@ public class MultiplicationDeobfuscator implements Deobfuscator return me; } + if (ctx.getInstruction() instanceof IMul) + { + if (!this.isOnlyPath(e, ctx)) + throw new IllegalStateException(); + } + for (StackContext sctx : ctx.getPops()) { InstructionContext i = sctx.getPushed(); @@ -91,7 +98,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator // chained imul, append to me try { - MultiplicationExpression other = parseExpression(i); + MultiplicationExpression other = parseExpression(e, i); me.instructions.addAll(other.instructions); me.subexpressions.addAll(other.subexpressions); @@ -106,7 +113,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator // imul using result of iadd or isub. evaluate expression try { - MultiplicationExpression other = parseExpression(i); + MultiplicationExpression other = parseExpression(e, i); // subexpr //if (other != null) @@ -129,7 +136,8 @@ public class MultiplicationDeobfuscator implements Deobfuscator // find other branch of the dup instruction // sctx = what dup pushed, find other StackContext otherCtx = dup.getOtherBranch(sctx); // other side of dup - InstructionContext otherCtxI = otherCtx.getPopped(); // would insert imul here? + //InstructionContext otherCtxI = otherCtx.getPopped(); // would insert imul here? + InstructionContext otherCtxI = otherCtx.getPopped().get(0); // is this irght? if (otherCtxI.getInstruction() instanceof IMul) { @@ -143,7 +151,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator StackContext orig = dup.getOriginal(sctx); // original try { - MultiplicationExpression other = parseExpression(orig.getPushed()); + MultiplicationExpression other = parseExpression(e, orig.getPushed()); // this expression is used elsewhere like 'pushConstant' so any changes // done to it affect that, too. so multiply it by existing values? if (orig.getPushed().getInstruction() instanceof IAdd || orig.getPushed().getInstruction() instanceof ISub) @@ -182,7 +190,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator // this is an iadd/sub else if (ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub) { - MultiplicationExpression other = parseExpression(i); // parse this side of the add/sub + MultiplicationExpression other = parseExpression(e, i); // parse this side of the add/sub //if (other != null) me.subexpressions.add(other); @@ -216,39 +224,46 @@ public class MultiplicationDeobfuscator implements Deobfuscator } // for each instruction ctx in ths expression, see if it !equals any other for each ins? +// +// private List getInsInExpr(InstructionContext ctx, Set set) +// { +// List l = new ArrayList<>(); +// +// if (ctx == null || set.contains(ctx.getInstruction())) +// return l; +// +// set.add(ctx.getInstruction()); +// +// l.add(ctx); +// for (StackContext s : ctx.getPops()) +// l.addAll(getInsInExpr(s.getPushed(), set)); +// for (StackContext s : ctx.getPushes()) +// l.addAll(getInsInExpr(s.getPopped(), set)); +// +// return l; +// } - private List getInsInExpr(InstructionContext ctx, Set set) - { - List l = new ArrayList<>(); - - if (ctx == null || set.contains(ctx.getInstruction())) - return l; - - set.add(ctx.getInstruction()); - - l.add(ctx); - for (StackContext s : ctx.getPops()) - l.addAll(getInsInExpr(s.getPushed(), set)); - for (StackContext s : ctx.getPushes()) - l.addAll(getInsInExpr(s.getPopped(), set)); - - return l; - } - - private boolean isOnlyPath(Execution execution, InstructionContext ctx) + public static boolean isOnlyPath(Execution execution, InstructionContext ctx) { + assert ctx.getInstruction() instanceof IMul; Collection ins = execution.getInstructonContexts(ctx.getInstruction()); for (InstructionContext i : ins) - //for (Frame f : execution.processedFrames) - // if (f.getMethod() == frame.getMethod()) - // for (InstructionContext i : f.getInstructions()) - //if (i.getInstruction() == ctx.getInstruction()) - { - if (!i.equals(ctx)) - { - return false; - } - } + { + if (!i.equals(ctx)) + { + return false; + } + + for (StackContext sctx : i.getPushes()) + if (sctx.getPopped().size() > 1) + return false; + ///if (i.getPushes().size() > 1) + // return false; +// if (!Objects.equals(i.getPushes().get(0).getPopped(), ctx.getPushes().get(0).getPopped())) +// { +// return false; +// } + } return true; } @@ -267,7 +282,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator int mcount = 0; for (Frame frame : e.processedFrames) - outer: + //outer: for (InstructionContext ictx : frame.getInstructions()) { Instruction instruction = ictx.getInstruction(); @@ -305,7 +320,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator MultiplicationExpression expression; try { - expression = parseExpression(ictx); + expression = parseExpression(e, ictx); } catch (IllegalStateException ex) { @@ -319,11 +334,11 @@ public class MultiplicationDeobfuscator implements Deobfuscator // continue; // there can only be one path to here, or else combinging would change code logic - List ilist = this.getInsInExpr(ictx, new HashSet()); - for (InstructionContext i2 : ilist) - if (i2.getInstruction() instanceof IMul) - if (!isOnlyPath(e, i2)) - continue outer; +// List ilist = this.getInsInExpr(ictx, new HashSet()); +// for (InstructionContext i2 : ilist) +// if (i2.getInstruction() instanceof IMul) +// if (!isOnlyPath(e, i2)) +// continue outer; if (done.contains(instruction)) diff --git a/src/main/java/net/runelite/deob/execution/Frame.java b/src/main/java/net/runelite/deob/execution/Frame.java index ade776f508..5fa1af7cfc 100644 --- a/src/main/java/net/runelite/deob/execution/Frame.java +++ b/src/main/java/net/runelite/deob/execution/Frame.java @@ -30,6 +30,8 @@ public class Frame private Variables variables; private List instructions = new ArrayList<>(); // instructions executed in this frame private MultiValueMap visited = new MultiValueMap<>(); // shared + + public static long num; public Frame(Execution execution, Method method) { diff --git a/src/main/java/net/runelite/deob/execution/InstructionContext.java b/src/main/java/net/runelite/deob/execution/InstructionContext.java index 903cdbd837..fad054668b 100644 --- a/src/main/java/net/runelite/deob/execution/InstructionContext.java +++ b/src/main/java/net/runelite/deob/execution/InstructionContext.java @@ -16,6 +16,7 @@ public class InstructionContext private List pushes = new ArrayList<>(); // stack contexts pushed by instruction execution private List reads = new ArrayList<>(); // lvt reads private List invokes = new ArrayList<>(); // invokes + public long frameNum; public InstructionContext(Instruction i, Frame f) { @@ -28,7 +29,7 @@ public class InstructionContext { for (StackContext c : ctx) { - c.setPopped(this); // now we know which instruction popped this, record it + c.addPopped(this); // now we know which instruction popped this, record it pops.add(c); } } diff --git a/src/main/java/net/runelite/deob/execution/StackContext.java b/src/main/java/net/runelite/deob/execution/StackContext.java index 78d4a75f9d..ced878477c 100644 --- a/src/main/java/net/runelite/deob/execution/StackContext.java +++ b/src/main/java/net/runelite/deob/execution/StackContext.java @@ -6,7 +6,7 @@ import java.util.List; public class StackContext { public InstructionContext pushed; // instruction which pushed this - public InstructionContext popped; // instruction which popped this + public List poppeds = new ArrayList<>(); // instructions which popped this public Type type; // type of this public boolean removed; public int encryption; // if this value is encrypted, this is the key to get the real value @@ -34,14 +34,18 @@ public class StackContext return pushed; } - public InstructionContext getPopped() + public List getPopped() { - return popped; + return poppeds; } - public void setPopped(InstructionContext popped) + public void addPopped(InstructionContext popped) { - this.popped = popped; + //assert !this.poppeds.contains(popped); + if (!this.poppeds.contains(popped)) + this.poppeds.add(popped); + //assert this.popped == null; + //this.popped = popped; } public Type getType() diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index 006d5f1512..7d304f5280 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -1,5 +1,6 @@ package net.runelite.deob.deobfuscators.arithmetic; +import java.util.Collection; import net.runelite.deob.ClassGroup; import net.runelite.deob.ClassGroupFactory; import net.runelite.deob.Deobfuscator; @@ -7,26 +8,19 @@ import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instructions.Dup_X1; -import net.runelite.deob.attributes.code.instructions.Goto; import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IConst_0; -import net.runelite.deob.attributes.code.instructions.IConst_1; -import net.runelite.deob.attributes.code.instructions.IConst_2; import net.runelite.deob.attributes.code.instructions.IConst_3; -import net.runelite.deob.attributes.code.instructions.IDiv; import net.runelite.deob.attributes.code.instructions.ILoad; import net.runelite.deob.attributes.code.instructions.IMul; -import net.runelite.deob.attributes.code.instructions.IStore; import net.runelite.deob.attributes.code.instructions.IStore_0; -import net.runelite.deob.attributes.code.instructions.IStore_1; -import net.runelite.deob.attributes.code.instructions.IStore_2; -import net.runelite.deob.attributes.code.instructions.If; import net.runelite.deob.attributes.code.instructions.If0; import net.runelite.deob.attributes.code.instructions.LDC_W; import net.runelite.deob.attributes.code.instructions.NOP; import net.runelite.deob.attributes.code.instructions.Pop; import net.runelite.deob.attributes.code.instructions.VReturn; import net.runelite.deob.execution.Execution; +import net.runelite.deob.execution.InstructionContext; import org.junit.Assert; import org.junit.Test; @@ -303,6 +297,15 @@ public class MultiplicationDeobfuscatorTest assert constant4.getConstantAsInt() * constant5.getConstantAsInt() == 1; + { + Collection ctxs = e.getInstructonContexts(body[3]); + assert ctxs.size() == 1; + + InstructionContext ictx = ctxs.iterator().next(); + boolean onlyPath = MultiplicationDeobfuscator.isOnlyPath(e, ictx); + Assert.assertFalse(onlyPath); + } + Deobfuscator d = new MultiplicationDeobfuscator(); d.run(group); From 0bc49e1ec683350c126f55ffefbadb18c029f454 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 8 Oct 2015 21:00:45 -0400 Subject: [PATCH 50/58] Fix fieldmover build? Not sure if this is correct. This mul test doesn't cover what I was trying to fix, field721 = (-1 != var5 && 1 != var5?(class139.field2363 * 1381104939 + 1 * field721 * 1) / 2:1381104939 * class139.field2363) * 1807370871 * 981643079; --- src/main/java/net/runelite/deob/deobfuscators/FieldMover.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java b/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java index bafd0add4b..75ddd98117 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java +++ b/src/main/java/net/runelite/deob/deobfuscators/FieldMover.java @@ -307,7 +307,8 @@ public class FieldMover implements Deobfuscator { assert s.getPushed() == ctx; - getContexts(list, s.getPopped()); + for (InstructionContext i : s.getPopped()) + getContexts(list, i); } } From fd973a0a9520bae72dd7574323f9e3d5f1d46fc3 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 9 Oct 2015 14:14:14 -0400 Subject: [PATCH 51/58] Check per pop if its multiple places or not --- .../MultiplicationDeobfuscator.java | 68 +++++++-- .../arithmetic/MultiplicationExpression.java | 11 +- .../net/runelite/deob/execution/Stack.java | 8 +- .../runelite/deob/execution/StackContext.java | 3 - .../MultiplicationDeobfuscatorTest.java | 142 ++++++++---------- 5 files changed, 132 insertions(+), 100 deletions(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 9ee09713dc..11d6425065 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -22,6 +22,7 @@ import net.runelite.deob.attributes.code.instructions.SiPush; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; +import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; public class MultiplicationDeobfuscator implements Deobfuscator @@ -60,14 +61,21 @@ public class MultiplicationDeobfuscator implements Deobfuscator return me; } - if (ctx.getInstruction() instanceof IMul) - { - if (!this.isOnlyPath(e, ctx)) - throw new IllegalStateException(); - } +// if (ctx.getInstruction() instanceof IMul) +// { +// if (!isOnlyPath(e, ctx)) +// throw new IllegalStateException(); +// } for (StackContext sctx : ctx.getPops()) { + if (ctx.getInstruction() instanceof IMul) + { + if (!isOnlyPath(e, ctx, sctx)) + continue; + //throw new IllegalStateException(); + } + InstructionContext i = sctx.getPushed(); // int count2 = 0; @@ -257,12 +265,50 @@ public class MultiplicationDeobfuscator implements Deobfuscator for (StackContext sctx : i.getPushes()) if (sctx.getPopped().size() > 1) return false; - ///if (i.getPushes().size() > 1) - // return false; -// if (!Objects.equals(i.getPushes().get(0).getPopped(), ctx.getPushes().get(0).getPopped())) -// { -// return false; -// } + } + return true; + } + + private static boolean ictxEqualsDir(InstructionContext one, InstructionContext two, StackContext sctx) + { + if (one.getInstruction() != two.getInstruction()) + return false; + + // check if stack at time of execution is equal + List ours = one.getStack().getStack(), theirs = two.getStack().getStack(); + //Stack ours = new Stack(one.getStack()), // copy stacks since we destroy them +// theirs = new Stack(two.getStack()); + + if (ours.size() != theirs.size()) // is this possible? + return false; + + assert ours.contains(sctx); + int i = ours.indexOf(sctx); + + StackContext theirsctx = theirs.get(i); + + if (sctx.getPushed().getInstruction() != theirsctx.getPushed().getInstruction()) + return false; + + return true; + } + + public static boolean isOnlyPath(Execution execution, InstructionContext ctx, StackContext sctx) + { + // + assert ctx.getInstruction() instanceof IMul; + Collection ins = execution.getInstructonContexts(ctx.getInstruction()); + for (InstructionContext i : ins) + { + if (!ictxEqualsDir(ctx, i, sctx)) +/// if (!i.equals(ctx)) + { + return false; + } + + for (StackContext s : i.getPushes()) + if (s.getPopped().size() > 1) + return false; } return true; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java index 7f1ebb0cc1..f8ac40cfac 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java @@ -81,11 +81,12 @@ public class MultiplicationExpression PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); Instruction newIns = pci.setConstant(new net.runelite.deob.pool.Integer(result)); ++count; - if (newIns != pci) - { - newIns.getInstructions().replace((Instruction) pci, newIns); - replace = true; - } + assert newIns == pci; +// if (newIns != pci) +// { +// newIns.getInstructions().replace((Instruction) pci, newIns); +// replace = true; +// } result = 1; // rest of the results go to 1 } diff --git a/src/main/java/net/runelite/deob/execution/Stack.java b/src/main/java/net/runelite/deob/execution/Stack.java index 5078344e76..7db393816e 100644 --- a/src/main/java/net/runelite/deob/execution/Stack.java +++ b/src/main/java/net/runelite/deob/execution/Stack.java @@ -1,6 +1,7 @@ package net.runelite.deob.execution; import java.util.Arrays; +import java.util.List; public class Stack { @@ -12,7 +13,7 @@ public class Stack stack = new StackContext[sz*2]; // XXX FIXME } - protected Stack(Stack other) + public Stack(Stack other) { this.size = other.size; this.stack = Arrays.copyOf(other.stack, other.stack.length); @@ -56,4 +57,9 @@ public class Stack { return size; } + + public List getStack() + { + return Arrays.asList(stack); + } } diff --git a/src/main/java/net/runelite/deob/execution/StackContext.java b/src/main/java/net/runelite/deob/execution/StackContext.java index ced878477c..157fb947d9 100644 --- a/src/main/java/net/runelite/deob/execution/StackContext.java +++ b/src/main/java/net/runelite/deob/execution/StackContext.java @@ -41,11 +41,8 @@ public class StackContext public void addPopped(InstructionContext popped) { - //assert !this.poppeds.contains(popped); if (!this.poppeds.contains(popped)) this.poppeds.add(popped); - //assert this.popped == null; - //this.popped = popped; } public Type getType() diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index 7d304f5280..66da96a6d7 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -10,7 +10,10 @@ import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instructions.Dup_X1; import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IConst_0; +import net.runelite.deob.attributes.code.instructions.IConst_1; +import net.runelite.deob.attributes.code.instructions.IConst_2; import net.runelite.deob.attributes.code.instructions.IConst_3; +import net.runelite.deob.attributes.code.instructions.IDiv; import net.runelite.deob.attributes.code.instructions.ILoad; import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.IStore_0; @@ -166,84 +169,6 @@ public class MultiplicationDeobfuscatorTest Assert.assertEquals(1, constant4.getConstantAsInt()); } - //@Test -// public void testDupX1_3() -// { -// ClassGroup group = ClassGroupFactory.generateGroup(); -// Code code = group.findClass("test").findMethod("func").getCode(); -// Instructions ins = code.getInstructions(); -// -// code.setMaxStack(2); -// -// Instruction[] prepareVariables = { -// new IConst_3(ins), -// new IStore_0(ins), -// new IConst_3(ins), -// new IStore_1(ins), -// new IConst_3(ins), -// new IStore_2(ins), -// }; -// -// for (Instruction i : prepareVariables) -// ins.addInstruction(i); -// -// LDC_W constant1 = new LDC_W(ins, 1381104939), -// constant2 = new LDC_W(ins, 1381104939), -// constant3 = new LDC_W(ins, 981643079), -// constant4 = new LDC_W(ins, 1807370871), -// constant5 = new LDC_W(ins, 1807370871), -// constant6 = new LDC_W(ins, 981643079); -// -// NOP label1 = new NOP(ins), -// label2 = new NOP(ins); -// -// Instruction body[] = { -// new IConst_1(ins), -// new ILoad(ins, 0), -// new If(ins, label1), -// constant1, -// new ILoad(ins, 1), -// new IMul(ins), -// new Goto(ins, label2), -// label1, -// new ILoad(ins, 1), -// constant2, -// new IMul(ins), -// constant3, -// new ILoad(ins, 2), -// constant4, -// new IMul(ins), -// new IMul(ins), -// new IAdd(ins), -// new IConst_2(ins), -// new IDiv(ins), -// label2, -// constant5, -// new IMul(ins), -// constant6, -// new IMul(ins), -// new IStore(ins, 3), -// new VReturn(ins) -// }; -// -// for (Instruction i : body) -// ins.addInstruction(i); -// -// Execution e = new Execution(group); -// e.populateInitialMethods(); -// e.run(); -// -// Deobfuscator d = new MultiplicationDeobfuscator(); -// d.run(group); -// -// Assert.assertEquals(1381104939, constant1.getConstantAsInt()); -// Assert.assertEquals(1381104939, constant2.getConstantAsInt()); -// Assert.assertEquals(981643079, constant3.getConstantAsInt()); -// Assert.assertEquals(1807370871, constant4.getConstantAsInt()); -// Assert.assertEquals(1807370871, constant5.getConstantAsInt()); -// Assert.assertEquals(981643079, constant6.getConstantAsInt()); -// } - @Test public void testDupX1_3() { @@ -311,8 +236,65 @@ public class MultiplicationDeobfuscatorTest Assert.assertEquals(1381104939, constant1.getConstantAsInt()); Assert.assertEquals(1381104939, constant2.getConstantAsInt()); - Assert.assertEquals(981643079, constant3.getConstantAsInt()); + Assert.assertEquals(1, constant3.getConstantAsInt()); Assert.assertEquals(1, constant4.getConstantAsInt()); - Assert.assertEquals(1, constant5.getConstantAsInt()); + Assert.assertEquals(981643079, constant5.getConstantAsInt()); // assumes result is moved to the end here. + } + + @Test + public void testDupX1_4() + { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Instructions ins = code.getInstructions(); + + code.setMaxStack(2); + + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins), + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, 1807370871), + constant2 = new LDC_W(ins, 981643079); + + NOP label1 = new NOP(ins); + + Instruction body[] = { + new ILoad(ins, 0), + new LDC_W(ins, 2), + new IMul(ins), + + new IConst_0(ins), + new If0(ins, label1), + + new Pop(ins), + new LDC_W(ins, 3), + + label1, + constant1, + new IMul(ins), + constant2, + new IMul(ins), + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1; + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1, constant1.getConstantAsInt()); + Assert.assertEquals(1, constant2.getConstantAsInt()); } } From bd427975aecda07ad53ba74f250d859e5f2c4987 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 10 Oct 2015 10:35:20 -0400 Subject: [PATCH 52/58] Cleanup some of the old encr stuff --- .../attributes/code/instructions/Dup.java | 2 - .../attributes/code/instructions/Dup2.java | 4 - .../attributes/code/instructions/Dup2_X1.java | 5 - .../attributes/code/instructions/Dup2_X2.java | 6 - .../attributes/code/instructions/Dup_X1.java | 3 - .../attributes/code/instructions/Dup_X2.java | 4 - .../code/instructions/GetField.java | 12 -- .../code/instructions/GetStatic.java | 14 +- .../attributes/code/instructions/IAdd.java | 48 ----- .../attributes/code/instructions/IMul.java | 40 ---- .../attributes/code/instructions/ISub.java | 47 ---- .../code/instructions/PutField.java | 82 ------- .../code/instructions/PutStatic.java | 203 ------------------ .../deobfuscators/arithmetic/Encryption.java | 72 +------ .../deobfuscators/arithmetic/ModArith.java | 63 ++---- .../MultiplicationDeobfuscator.java | 53 ----- .../arithmetic/MultiplicationExpression.java | 11 - .../deob/execution/InstructionContext.java | 1 - .../runelite/deob/execution/StackContext.java | 1 - 19 files changed, 25 insertions(+), 646 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java index 2a984d6a44..f24a9803c9 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup.java @@ -28,13 +28,11 @@ public class Dup extends Instruction implements DupInstruction ins.pop(obj); StackContext ctx = new StackContext(ins, obj.getType()); - ctx.encryption = obj.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, obj.getType()); - ctx.encryption = obj.encryption; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java index f7237716d1..348e361a30 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2.java @@ -36,14 +36,12 @@ public class Dup2 extends Instruction implements DupInstruction if (two != null) { StackContext ctx = new StackContext(ins, two.getType()); - ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } StackContext ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(one); ins.push(ctx); @@ -51,14 +49,12 @@ public class Dup2 extends Instruction implements DupInstruction if (two != null) { ctx = new StackContext(ins, two.getType()); - ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(one); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java index 30672b0374..0f0f13afc7 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X1.java @@ -38,20 +38,17 @@ public class Dup2_X1 extends Instruction implements DupInstruction if (two != null) { StackContext ctx = new StackContext(ins, two.getType()); - ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } StackContext ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, three.getType()); - ctx.encryption = three.encryption; stack.push(ctx); ins.push(ctx); @@ -59,14 +56,12 @@ public class Dup2_X1 extends Instruction implements DupInstruction if (two != null) { ctx = new StackContext(ins, two.getType()); - ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java index ffa13fecc7..e4ca17c5ef 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup2_X2.java @@ -43,14 +43,12 @@ public class Dup2_X2 extends Instruction implements DupInstruction if (two != null) { StackContext ctx = new StackContext(ins, two.getType()); - ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } StackContext ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(one); ins.push(ctx); @@ -58,14 +56,12 @@ public class Dup2_X2 extends Instruction implements DupInstruction if (four != null) { ctx = new StackContext(ins, four.getType()); - ctx.encryption = four.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, three.getType()); - ctx.encryption = three.encryption; stack.push(one); ins.push(ctx); @@ -73,14 +69,12 @@ public class Dup2_X2 extends Instruction implements DupInstruction if (two != null) { ctx = new StackContext(ins, two.getType()); - ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(one); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java index 41a82e5ac3..4e0ce8ded2 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X1.java @@ -34,19 +34,16 @@ public class Dup_X1 extends Instruction implements DupInstruction ins.pop(one, two); StackContext ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, two.getType()); - ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java index df3c12f98a..8c300c0c74 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/Dup_X2.java @@ -35,7 +35,6 @@ public class Dup_X2 extends Instruction implements DupInstruction ins.pop(three); StackContext ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); @@ -43,20 +42,17 @@ public class Dup_X2 extends Instruction implements DupInstruction if (three != null) { ctx = new StackContext(ins, three.getType()); - ctx.encryption = three.encryption; stack.push(ctx); ins.push(ctx); } ctx = new StackContext(ins, two.getType()); - ctx.encryption = two.encryption; stack.push(ctx); ins.push(ctx); ctx = new StackContext(ins, one.getType()); - ctx.encryption = one.encryption; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java index 9cc68e0150..318645a9ad 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetField.java @@ -53,18 +53,6 @@ public class GetField extends Instruction implements GetFieldInstruction ins.pop(object); StackContext ctx = new StackContext(ins, new Type(field.getNameAndType().getDescriptorType()).toStackType()); - - Encryption encryption = frame.getExecution().getEncryption(); - net.runelite.deob.Field f = getMyField(); - if (encryption != null && f != null) - { - Pair pair = encryption.getField(f); - if (pair != null) - { - ctx.encryption = pair.getter; - } - } - stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java index fcc8bde040..3cd81d4496 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java @@ -49,19 +49,7 @@ public class GetStatic extends Instruction implements GetFieldInstruction InstructionContext ins = new InstructionContext(this, frame); Stack stack = frame.getStack(); - StackContext ctx = new StackContext(ins, new Type(field.getNameAndType().getDescriptorType()).toStackType()); - - Encryption encryption = frame.getExecution().getEncryption(); - net.runelite.deob.Field f = getMyField(); - if (f != null && encryption != null) - { - Pair pair = encryption.getField(f); - if (pair != null) - { - ctx.encryption = pair.getter; - } - } - + StackContext ctx = new StackContext(ins, new Type(field.getNameAndType().getDescriptorType()).toStackType()); stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java index 25e6501ac5..053a76de47 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IAdd.java @@ -34,55 +34,7 @@ public class IAdd extends Instruction ins.pop(two, one); - Encryption encryption = frame.getExecution().getEncryption(); - int encKey = 0; - if (encryption != null) - { - if (one.encryption != 0) - { - assert two.encryption == 0; - - if (two.getPushed().getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); - int value = (int) pci.getConstant().getObject(); - - //if (value != 0 && value != 1) - { - int o = value * one.encryption; - - encryption.change(pci, o, false); - } - // field is no longer encrypted - encKey = 1; - } - //else - // encKey = one.encryption; - } - else if (two.encryption != 0) - { - assert one.encryption == 0; - - if (one.getPushed().getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); - int value = (int) pci.getConstant().getObject(); - - //if (value != 0 && value != 1) - { - int o = value * two.encryption; - - encryption.change(pci, o, false); - } - encKey = 1; - } - - //encKey = two.encryption; - } - } - StackContext ctx = new StackContext(ins, int.class); - ctx.encryption = encKey; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java index d9c347ca83..73e6f27e58 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IMul.java @@ -35,47 +35,7 @@ public class IMul extends Instruction ins.pop(one, two); - Encryption encryption = frame.getExecution().getEncryption(); - int encKey = 0; - if (encryption != null) - { - if (one.encryption != 0) - { - assert two.encryption == 0; - PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); - int other = (int) pci.getConstant().getObject(); - - // 'one' is encrypted and we want to decrypt it by dividing by one.encryption - - if (other != 0) - { - int o = other * DMath.modInverse(one.encryption); - - encryption.change(pci, o, false); - } - - encKey = 1; - } - else if (two.encryption != 0) - { - assert one.encryption == 0; - - PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); - int other = (int) pci.getConstant().getObject(); - - if (other != 0) - { - int o = other * DMath.modInverse(two.encryption); - - encryption.change(pci, o, false); - } - - encKey = 1; - } - } - StackContext ctx = new StackContext(ins, int.class); - ctx.encryption = encKey; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java b/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java index a1c1b448f9..c1e2b73ceb 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/ISub.java @@ -28,54 +28,7 @@ public class ISub extends Instruction ins.pop(two, one); - Encryption encryption = frame.getExecution().getEncryption(); - int encKey = 0; - if (encryption != null) - { - if (one.encryption != 0) - { - assert two.encryption == 0; - - if (two.getPushed().getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); - int value = (int) pci.getConstant().getObject(); - - //if (value != 0 && value != 1) - { - int o = value * one.encryption; - - encryption.change(pci, o, false); - } - encKey = 1; - } - - // encKey = one.encryption; - } - else if (two.encryption != 0) - { - assert one.encryption == 0; - - if (one.getPushed().getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); - int value = (int) pci.getConstant().getObject(); - - //if (value != 0 && value != 1) - { - int o = value * two.encryption; - - encryption.change(pci, o, false); - } - encKey = 1; - } - - //encKey = two.encryption; - } - } - StackContext ctx = new StackContext(ins, int.class); - ctx.encryption = encKey; stack.push(ctx); ins.push(ctx); diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java index 99cc4246e2..1b4664e3d5 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutField.java @@ -52,88 +52,6 @@ public class PutField extends Instruction implements SetFieldInstruction StackContext object = stack.pop(); ins.pop(value, object); - Encryption encryption = frame.getExecution().getEncryption(); - net.runelite.deob.Field myField = getMyField(); - if (encryption != null && myField != null) - { - Pair pair = encryption.getField(myField); - //if (pair != null) - // translate(encryption, pair, ins, new HashSet()); -// XXX move translate() here -// InstructionContext ctx = value.getPushed(); -// if (ctx.getInstruction() instanceof IAdd && pair != null) -// { -// // field += constant * crap; -// // in bytecode is really -// // field = field + constant * crap -// -// List pops = ctx.getPops(); -// -// if (pops.get(0).getPushed().getInstruction() instanceof IMul) -// { -// ctx = pops.get(0).getPushed(); -// } -// else if (pops.get(1).getPushed().getInstruction() instanceof IMul) -// { -// ctx = pops.get(1).getPushed(); -// } -// } -// if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) -// { -// // field = encryptedvalue -// // decrypt value by * getter -// -// PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); -// int v = (int) pci.getConstant().getObject(); -// -// if (v != 0 && v != 1) -// { -// v = v * pair.getter; -// -// encryption.change(pci, v); -// } -// } -// if (ctx.getInstruction() instanceof ISub) -// { -// List stackCtx = ctx.getPops(); -// -// StackContext one = stackCtx.get(0), two = stackCtx.get(1); -// -// if (one.getPushed().getInstruction() instanceof IMul) -// { -// ctx = one.getPushed(); -// } -// else if (two.getPushed().getInstruction() instanceof IMul) -// { -// ctx = two.getPushed(); -// } -// } -// if (ctx.getInstruction() instanceof IMul && pair != null) -// { -// List stackCtx = ctx.getPops(); -// -// StackContext one = stackCtx.get(0), two = stackCtx.get(1); -// -// StackContext magicStack = PutStatic.findMagic(one, two); -// -// if (magicStack != null) -// { -// PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); -// int v = (int) pci.getConstant().getObject(); -// -// // field is encrypted with pair -// // divide value by setter -// -// if (v != 0 && v != 1) -// { -// v = v * pair.getter; -// -// encryption.change(pci, v); -// } -// } -// } - } - frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java index 3b6a7aab36..ce1d31b2f7 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/PutStatic.java @@ -16,12 +16,6 @@ import net.runelite.deob.pool.NameAndType; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.Set; -import net.runelite.deob.attributes.code.instruction.types.DupInstruction; -import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; -import net.runelite.deob.deobfuscators.arithmetic.DMath; -import net.runelite.deob.deobfuscators.arithmetic.Encryption; -import net.runelite.deob.deobfuscators.arithmetic.Pair; public class PutStatic extends Instruction implements SetFieldInstruction { @@ -45,122 +39,6 @@ public class PutStatic extends Instruction implements SetFieldInstruction super.write(out); out.writeShort(this.getPool().make(field)); } - - protected static StackContext findMagic(StackContext one, StackContext two) - { - if (one.getPushed().getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) one.getPushed().getInstruction(); - int value1 = (int) pci.getConstant().getObject(); - - if (DMath.isBig(value1)) - { - return one; - } - } - - if (two.getPushed().getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) two.getPushed().getInstruction(); - int value2 = (int) pci.getConstant().getObject(); - - if (DMath.isBig(value2)) - { - return two; - } - } - - return null; - } - - public static boolean translate(Encryption encryption, Pair pair, InstructionContext ctx, Set visited) - { - if (visited.contains(ctx.getInstruction())) - return true; - - visited.add(ctx.getInstruction()); - - if (ctx.getInstruction() instanceof PushConstantInstruction) - { - PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); - - if (pci.getConstant().getObject() instanceof Integer) - { - int value = (int) pci.getConstant().getObject(); - - if (encryption.hasChange(pci)) - return true; - - if (value != 0) - { - value = value * pair.getter; - - encryption.change(pci, value, true); - } - - return true; - } - } - - boolean ok = ctx.getInstruction() instanceof IAdd || - ctx.getInstruction() instanceof ISub || - ctx.getInstruction() instanceof IMul || - ctx.getInstruction() instanceof SetFieldInstruction || - ctx.getInstruction() instanceof DupInstruction; - - if (!ok) - return false; - - boolean multipleBranches = ctx.getInstruction() instanceof IAdd || - ctx.getInstruction() instanceof ISub; - boolean retVal = false; - - encryption.begin(); - - for (StackContext sctx : ctx.getPops()) - { - InstructionContext i = sctx.getPushed(); - - if (translate(encryption, pair, i, visited)) - { - retVal = true; - - if (!multipleBranches) // only need to translate the one branch, which we have, return. - break; - } - else - { - if (multipleBranches) - { - // we can't translate both branches so rollback - encryption.rollback(); - retVal = false; - break; - } - // else this is okay, we can try another - } - } - - encryption.end(); - -// for (StackContext sctx : ctx.getPushes()) -// { -// InstructionContext i = sctx.getPopped(); -// -// if (i != null) -// { -// boolean b = translate(encryption, pair, i, visited); // XXX? -// //System.out.println("up translate res " + b); -// } -// else -// assert false; -// // this hasn't been popped yet, so it hasn't been executed yet, -// // so mark it as encrypted so that when it is executed, we will decrypt it -// //sctx.encryption = pair.getter; -// } - - return retVal; - } @Override public void execute(Frame frame) @@ -171,87 +49,6 @@ public class PutStatic extends Instruction implements SetFieldInstruction StackContext object = stack.pop(); ins.pop(object); - Encryption encryption = frame.getExecution().getEncryption(); - net.runelite.deob.Field myField = getMyField(); - if (encryption != null && myField != null) - { - Pair pair = encryption.getField(myField); - //if (pair != null) - // translate(encryption, pair, ins, new HashSet()); -// InstructionContext ctx = object.getPushed(); -// if (ctx.getInstruction() instanceof IAdd && pair != null) -// { -// // field += constant * crap; -// // in bytecode is really -// // field = field + constant * crap -// -// List pops = ctx.getPops(); -// -// if (pops.get(0).getPushed().getInstruction() instanceof IMul) -// { -// ctx = pops.get(0).getPushed(); -// } -// else if (pops.get(1).getPushed().getInstruction() instanceof IMul) -// { -// ctx = pops.get(1).getPushed(); -// } -// } -// if (ctx.getInstruction() instanceof PushConstantInstruction && pair != null) -// { -// // field = encryptedvalue -// // decrypt value by * getter -// -// PushConstantInstruction pci = (PushConstantInstruction) ctx.getInstruction(); -// int value = (int) pci.getConstant().getObject(); -// -// if (value != 0 && value != 1) -// { -// value = value * pair.getter; -// -// encryption.change(pci, value); -// } -// } -// if (ctx.getInstruction() instanceof ISub) -// { -// List stackCtx = ctx.getPops(); -// -// StackContext one = stackCtx.get(0), two = stackCtx.get(1); -// -// if (one.getPushed().getInstruction() instanceof IMul) -// { -// ctx = one.getPushed(); -// } -// else if (two.getPushed().getInstruction() instanceof IMul) -// { -// ctx = two.getPushed(); -// } -// } -// if (ctx.getInstruction() instanceof IMul && pair != null) -// { -// List stackCtx = ctx.getPops(); -// -// StackContext one = stackCtx.get(0), two = stackCtx.get(1); -// -// StackContext magicStack = findMagic(one, two); -// -// if (magicStack != null) -// { -// PushConstantInstruction pci = (PushConstantInstruction) magicStack.getPushed().getInstruction(); -// int value = (int) pci.getConstant().getObject(); -// -// // field is encrypted with pair -// // divide value by setter -// -// if (value != 0 && value != 1) -// { -// value = value * pair.getter; -// -// encryption.change(pci, value); -// } -// } -// } - } - frame.addInstructionContext(ins); } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java index db58756b34..e626e94835 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/Encryption.java @@ -1,25 +1,12 @@ package net.runelite.deob.deobfuscators.arithmetic; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.Stack; import net.runelite.deob.Field; -import net.runelite.deob.attributes.code.Instruction; -import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; public class Encryption -{ - private static class PendingStack - { - private Set pending = new HashSet<>(); - } - - private Map fields = new HashMap<>(); - private Map changes = new HashMap<>(); - private Stack stack = new Stack<>(); +{ + private final Map fields = new HashMap<>(); public void addPair(Pair pair) { @@ -30,59 +17,4 @@ public class Encryption { return fields.get(field); } - - public boolean hasChange(PushConstantInstruction pci) - { - return changes.containsKey(pci); - } - - public void change(PushConstantInstruction pci, int value, boolean mul) - { - //Integer i = changes.get(pci); - assert !changes.containsKey(pci) || changes.get(pci) == value; -// if (i == null) -// changes.put(pci, value); -// else if (mul) -// changes.put(pci, value * i); -// else - changes.put(pci, value); - // assert i == value; - - if (stack.isEmpty()) - return; - PendingStack ps = stack.peek(); - ps.pending.add(pci); - } - - public void doChange() - { - for (Entry e : changes.entrySet()) - { - PushConstantInstruction pci = e.getKey(); - int value = e.getValue(); - - Instruction oldi = (Instruction) pci; - Instruction newi = pci.setConstant(new net.runelite.deob.pool.Integer(value)); - - if (oldi != newi) - oldi.getInstructions().replace(oldi, newi); - } - } - - public void begin() - { - stack.push(new PendingStack()); - } - - public void end() - { - stack.pop(); - } - - public void rollback() - { - PendingStack ps = stack.peek(); - for (PushConstantInstruction pci : ps.pending) - changes.remove(pci); - } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 77fd0b938c..1f3f53f9e5 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -21,7 +21,6 @@ import net.runelite.deob.attributes.code.instruction.types.PushConstantInstructi import net.runelite.deob.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.LDC_W; -import net.runelite.deob.attributes.code.instructions.PutStatic; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; @@ -29,10 +28,6 @@ import net.runelite.deob.execution.StackContext; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.MultiValueMap; -/* -store an encryption context on stack context that shows the value the ctx is encrypted with -*/ - public class ModArith implements Deobfuscator { private ClassGroup group; @@ -321,22 +316,22 @@ public class ModArith implements Deobfuscator } System.out.println("Finished arith deob on " + total + " fields in " + passes + " passes"); } - - private void translateSetFields(Execution e) - { - //Set visited = new HashSet<>(); - for (Frame f : e.processedFrames) - for (InstructionContext ins : f.getInstructions()) - if (ins.getInstruction() instanceof SetFieldInstruction) - { - SetFieldInstruction sfi = (SetFieldInstruction) ins.getInstruction(); - Pair pair = e.getEncryption().getField(sfi.getMyField()); - - if (pair != null) - PutStatic.translate(e.getEncryption(), pair, ins, new HashSet()); - // - } - } +// +// private void translateSetFields(Execution e) +// { +// //Set visited = new HashSet<>(); +// for (Frame f : e.processedFrames) +// for (InstructionContext ins : f.getInstructions()) +// if (ins.getInstruction() instanceof SetFieldInstruction) +// { +// SetFieldInstruction sfi = (SetFieldInstruction) ins.getInstruction(); +// Pair pair = e.getEncryption().getField(sfi.getMyField()); +// +// if (pair != null) +// PutStatic.translate(e.getEncryption(), pair, ins, new HashSet()); +// // +// } +// } private void insertGetterSetterMuls(Encryption encr) { @@ -410,6 +405,12 @@ public class ModArith implements Deobfuscator findUses(); reduce(); +// Encryption encr = new Encryption(); +// for (Pair pair : pairs) +// encr.addPair(pair); +// +// insertGetterSetterMuls(encr); + int i = 0; for (Pair pair : pairs) { @@ -429,26 +430,6 @@ public class ModArith implements Deobfuscator encr.addPair(pair); insertGetterSetterMuls(encr); -// -// execution = new Execution(group); -// execution.populateInitialMethods(); -// execution.setEncryption(encr); -// execution.run(); -// -// encr.doChange(); -// -// insertSetterMuls(encr); - -// execution = new Execution(group); -// execution.populateInitialMethods(); -// execution.run(); -// -// encr = new Encryption(); -// encr.addPair(pair); -// execution.setEncryption(encr); -// translateSetFields(execution); -// -// encr.doChange(); System.out.println("Changed " + ++i); //assert !deobfuscatedFields.contains(field); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 11d6425065..f85a9f15a0 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -1,10 +1,8 @@ package net.runelite.deob.deobfuscators.arithmetic; -import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Objects; import java.util.Set; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; @@ -22,7 +20,6 @@ import net.runelite.deob.attributes.code.instructions.SiPush; import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; -import net.runelite.deob.execution.Stack; import net.runelite.deob.execution.StackContext; public class MultiplicationDeobfuscator implements Deobfuscator @@ -392,56 +389,6 @@ public class MultiplicationDeobfuscator implements Deobfuscator done.add(instruction); count += expression.simplify(1); - if (MultiplicationExpression.replace) - { - assert false; - MultiplicationExpression.replace = false; - return count; - } - //break; -// List ins = getConstants(ictx); -// -// if (ins.size() == 1) -// continue; -// -// for (InstructionContext i : ins) -// { -// if (done.contains(i.getInstruction())) -// { -// continue outer; -// } -// } -// -// // there can only be one path to here, or else combinging would change code logic -// if (!isOnlyPath(e, frame, ictx)) -// continue; -// -// int result = 1; -// -// // calculate result -// for (InstructionContext i : ins) -// { -// PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); -// int value = (int) pci.getConstant().getObject(); -// -// result *= value; -// } -// -// // set result on ins -// for (InstructionContext i : ins) -// { -// PushConstantInstruction pci = (PushConstantInstruction) i.getInstruction(); -// Instruction newIns = pci.setConstant(new net.runelite.deob.pool.Integer(result)); -// ++count; -// if (newIns != pci) -// { -// instructions.replace((Instruction) pci, newIns); -// } -// result = 1; // rest of the results go to 1 -// } -// -// for (InstructionContext i : ins) -// done.add(i.getInstruction()); } return count; diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java index f8ac40cfac..0cab866840 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationExpression.java @@ -12,7 +12,6 @@ public class MultiplicationExpression dupedInstructions = new ArrayList<>(); List subexpressions = new ArrayList<>(); // for distributing, each subexpr is * by this InstructionContext dupmagic; // inverse of what is distributed to subexpressions gets set here - static boolean replace; int simplify(int start) { @@ -54,11 +53,6 @@ public class MultiplicationExpression { for (MultiplicationExpression me : subexpressions) { -// if (me.instructions.isEmpty() && this.dupmagic != null) -// { -// assert me.dupmagic == null; -// me.dupmagic = this.dupmagic; -// } count += me.simplify(result); } @@ -82,11 +76,6 @@ public class MultiplicationExpression Instruction newIns = pci.setConstant(new net.runelite.deob.pool.Integer(result)); ++count; assert newIns == pci; -// if (newIns != pci) -// { -// newIns.getInstructions().replace((Instruction) pci, newIns); -// replace = true; -// } result = 1; // rest of the results go to 1 } diff --git a/src/main/java/net/runelite/deob/execution/InstructionContext.java b/src/main/java/net/runelite/deob/execution/InstructionContext.java index fad054668b..737f3df0a6 100644 --- a/src/main/java/net/runelite/deob/execution/InstructionContext.java +++ b/src/main/java/net/runelite/deob/execution/InstructionContext.java @@ -16,7 +16,6 @@ public class InstructionContext private List pushes = new ArrayList<>(); // stack contexts pushed by instruction execution private List reads = new ArrayList<>(); // lvt reads private List invokes = new ArrayList<>(); // invokes - public long frameNum; public InstructionContext(Instruction i, Frame f) { diff --git a/src/main/java/net/runelite/deob/execution/StackContext.java b/src/main/java/net/runelite/deob/execution/StackContext.java index 157fb947d9..27cd190364 100644 --- a/src/main/java/net/runelite/deob/execution/StackContext.java +++ b/src/main/java/net/runelite/deob/execution/StackContext.java @@ -9,7 +9,6 @@ public class StackContext public List poppeds = new ArrayList<>(); // instructions which popped this public Type type; // type of this public boolean removed; - public int encryption; // if this value is encrypted, this is the key to get the real value public StackContext(InstructionContext pushed, Type type) { From db089ab628939268139c42a96d753060151b4379 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 10 Oct 2015 15:21:45 -0400 Subject: [PATCH 53/58] Small fixups i guess --- .../deobfuscators/arithmetic/ModArith.java | 140 +++++++++--------- .../MultiplicationDeobfuscator.java | 35 +++-- 2 files changed, 94 insertions(+), 81 deletions(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 1f3f53f9e5..7cfc6f9622 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -97,6 +97,11 @@ public class ModArith implements Deobfuscator if (field == null) continue; + if (field.getName().equals("field2201")) + { + int k=7; + } + int value = (int) pc.getConstant().getObject(); if (value == 1 || value == 0) @@ -112,17 +117,17 @@ public class ModArith implements Deobfuscator if (field == null) continue; - List constants = null; - try - { - constants = findAssocConstants(field, ctx); - for (int i : constants) - if (i != 1 && i != 0) - constantSetters.put(field, i); - } - catch (OtherFieldException ex) { } +// List constants = null; +// try +// { +// constants = findAssocConstants(field, ctx); +// for (int i : constants) +// if (i != 1 && i != 0) +// constantSetters.put(field, i); +// } +// catch (OtherFieldException ex) { } - StackContext value = ctx.getPops().get(0); // the first thing poppe from both putfield and putstatic is the value + StackContext value = ctx.getPops().get(0); // the first thing popped from both putfield and putstatic is the value if (!(value.getPushed().getInstruction() instanceof IMul)) continue; @@ -150,6 +155,11 @@ public class ModArith implements Deobfuscator if (value2 == 1 || value2 == 0) continue; + if (field.getName().equals("field2201")) + { + int k=7; + } + constantSetters.put(field, value2); } } @@ -214,60 +224,60 @@ public class ModArith implements Deobfuscator return p; } - private Pair guess(Field field, Collection values, boolean getter) - { - Map map = CollectionUtils.getCardinalityMap(values); // value -> how many times it occurs - int max = Collections.max(map.values()); // largest occurance # - int size = values.size(); - -// if (max == size) -// { -// // all getters are the same value -// int constant = getters.iterator().next(); -// Pair pair = new Pair(); -// pair.getter = constant; -// System.out.println("Guessing " + field.getName() + " getter " + constant + " setter "); -// pair.setter = DMath.modInverse(constant); -// return pair; +// private Pair guess(Field field, Collection values, boolean getter) +// { +// Map map = CollectionUtils.getCardinalityMap(values); // value -> how many times it occurs +// int max = Collections.max(map.values()); // largest occurance # +// int size = values.size(); +// +//// if (max == size) +//// { +//// // all getters are the same value +//// int constant = getters.iterator().next(); +//// Pair pair = new Pair(); +//// pair.getter = constant; +//// System.out.println("Guessing " + field.getName() + " getter " + constant + " setter "); +//// pair.setter = DMath.modInverse(constant); +//// return pair; +//// } +//// +//// if (size < 50) +//// return null; +// +//// if (((float) max / (float) size) < 0.9) +//// return null; +// +// for (final Map.Entry entry : map.entrySet()) { +// if (max == entry.getValue()) { +// int constant = entry.getKey(); +// int inverse; +// try +// { +// inverse = DMath.modInverse(constant); +// } +// catch (ArithmeticException ex) +// { +// break; +// } +// +// Pair pair = new Pair(); +// if (getter) +// { +// pair.getter = constant; +// pair.setter = inverse; +// } +// else +// { +// pair.getter = inverse; +// pair.setter = constant; +// } +// +// return pair; +// } // } // -// if (size < 50) -// return null; - -// if (((float) max / (float) size) < 0.9) -// return null; - - for (final Map.Entry entry : map.entrySet()) { - if (max == entry.getValue()) { - int constant = entry.getKey(); - int inverse; - try - { - inverse = DMath.modInverse(constant); - } - catch (ArithmeticException ex) - { - break; - } - - Pair pair = new Pair(); - if (getter) - { - pair.getter = constant; - pair.setter = inverse; - } - else - { - pair.getter = inverse; - pair.setter = constant; - } - - return pair; - } - } - - return null; - } +// return null; +// } private void reduce() { @@ -277,11 +287,6 @@ public class ModArith implements Deobfuscator Collection getters = constantGetters.getCollection(f), setters = constantSetters.getCollection(f); - if (f.getName().equals("field542")) - { - int i =5; - } - if (getters == null || setters == null) continue; @@ -421,6 +426,7 @@ public class ModArith implements Deobfuscator //if (!field.getName().equals("field3014") && !field.getName().equals("field2960")) if (!field.getName().equals("field2201")) { + int j =5; // continue; } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index f85a9f15a0..0c8fe514a3 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -13,6 +13,7 @@ import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instructions.BiPush; import net.runelite.deob.attributes.code.instructions.IAdd; +import net.runelite.deob.attributes.code.instructions.IConst_M1; import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.ISub; import net.runelite.deob.attributes.code.instructions.LDC_W; @@ -49,7 +50,8 @@ public class MultiplicationDeobfuscator implements Deobfuscator if (ctx.getInstruction() instanceof PushConstantInstruction) { - if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush) + if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush + || ctx.getInstruction() instanceof IConst_M1) { throw new IllegalStateException(); } @@ -92,7 +94,8 @@ public class MultiplicationDeobfuscator implements Deobfuscator { if (i.getInstruction() instanceof PushConstantInstruction) { - if (i.getInstruction() instanceof BiPush || i.getInstruction() instanceof SiPush) + if (i.getInstruction() instanceof BiPush || i.getInstruction() instanceof SiPush + || i.getInstruction() instanceof IConst_M1) throw new IllegalStateException(); // a constant of imul @@ -271,19 +274,23 @@ public class MultiplicationDeobfuscator implements Deobfuscator if (one.getInstruction() != two.getInstruction()) return false; - // check if stack at time of execution is equal - List ours = one.getStack().getStack(), theirs = two.getStack().getStack(); - //Stack ours = new Stack(one.getStack()), // copy stacks since we destroy them -// theirs = new Stack(two.getStack()); - - if (ours.size() != theirs.size()) // is this possible? - return false; - - assert ours.contains(sctx); - int i = ours.indexOf(sctx); - - StackContext theirsctx = theirs.get(i); + assert one.getPops().contains(sctx); + int i = one.getPops().indexOf(sctx); + StackContext theirsctx = two.getPops().get(i); +// // check if stack at time of execution is equal +// List ours = one.getStack().getStack(), theirs = two.getStack().getStack(); +// //Stack ours = new Stack(one.getStack()), // copy stacks since we destroy them +//// theirs = new Stack(two.getStack()); +// +// if (ours.size() != theirs.size()) // is this possible? +// return false; +// +// assert ours.contains(sctx); +// int i = ours.indexOf(sctx); +// +// StackContext theirsctx = theirs.get(i); +// if (sctx.getPushed().getInstruction() != theirsctx.getPushed().getInstruction()) return false; From 27f2edbea663dc97016a62336720bb1a643e0b40 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 10 Oct 2015 16:21:22 -0400 Subject: [PATCH 54/58] Limited support for getting around iload/istore, Add test too. Seems to work? --- .../MultiplicationDeobfuscator.java | 53 ++++++++++------ .../deob/execution/InstructionContext.java | 10 +++ .../deob/execution/VariableContext.java | 20 ++++++ .../MultiplicationDeobfuscatorTest.java | 61 +++++++++++++++++++ 4 files changed, 124 insertions(+), 20 deletions(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 0c8fe514a3..440c7ba9b4 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -2,7 +2,6 @@ package net.runelite.deob.deobfuscators.arithmetic; import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.Set; import net.runelite.deob.ClassGroup; import net.runelite.deob.Deobfuscator; @@ -10,6 +9,7 @@ import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instruction.types.DupInstruction; import net.runelite.deob.attributes.code.instruction.types.GetFieldInstruction; +import net.runelite.deob.attributes.code.instruction.types.LVTInstruction; import net.runelite.deob.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.deob.attributes.code.instructions.BiPush; import net.runelite.deob.attributes.code.instructions.IAdd; @@ -22,6 +22,8 @@ import net.runelite.deob.execution.Execution; import net.runelite.deob.execution.Frame; import net.runelite.deob.execution.InstructionContext; import net.runelite.deob.execution.StackContext; +import net.runelite.deob.execution.VariableContext; +import net.runelite.deob.execution.Variables; public class MultiplicationDeobfuscator implements Deobfuscator { @@ -48,6 +50,36 @@ public class MultiplicationDeobfuscator implements Deobfuscator assert !(ctx.getInstruction() instanceof DupInstruction); + if (ctx.getInstruction() instanceof LVTInstruction) + { + LVTInstruction lvt = (LVTInstruction) ctx.getInstruction(); + + // loading a variable + if (!lvt.store()) + { + int idx = lvt.getVariableIndex(); // var index + Variables vars = ctx.getVariables(); // variables at time of execution + + VariableContext vctx = vars.get(idx); // get the variable + + if (vctx.getRead().size() == 1) // ? + { + InstructionContext storeCtx = vctx.getInstructionWhichStored(); // this is an istore + if (storeCtx.getInstruction() instanceof LVTInstruction) + { + // invoking funcs can put stuff in lvt + + LVTInstruction storelvt = (LVTInstruction) storeCtx.getInstruction(); + + assert storelvt.store(); + + InstructionContext pushed = storeCtx.getPops().get(0).getPushed(); + return parseExpression(e, pushed); + } + } + } + } + if (ctx.getInstruction() instanceof PushConstantInstruction) { if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush @@ -60,35 +92,16 @@ public class MultiplicationDeobfuscator implements Deobfuscator return me; } -// if (ctx.getInstruction() instanceof IMul) -// { -// if (!isOnlyPath(e, ctx)) -// throw new IllegalStateException(); -// } - for (StackContext sctx : ctx.getPops()) { if (ctx.getInstruction() instanceof IMul) { if (!isOnlyPath(e, ctx, sctx)) continue; - //throw new IllegalStateException(); } InstructionContext i = sctx.getPushed(); -// int count2 = 0; -// while (i.getInstruction() instanceof DupInstruction) -// { -// DupInstruction dup = (DupInstruction) i.getInstruction(); -// sctx = dup.resolve(sctx); -// i = sctx.getPushed(); -// -// ++count2; -// assert count2 < 10; -// //assert !(i.getInstruction() instanceof DupInstruction); -// } - // if this instruction is imul, look at pops if (ctx.getInstruction() instanceof IMul) { diff --git a/src/main/java/net/runelite/deob/execution/InstructionContext.java b/src/main/java/net/runelite/deob/execution/InstructionContext.java index 737f3df0a6..10c62f6c9d 100644 --- a/src/main/java/net/runelite/deob/execution/InstructionContext.java +++ b/src/main/java/net/runelite/deob/execution/InstructionContext.java @@ -12,6 +12,7 @@ public class InstructionContext private Instruction ins; private Frame frame; private Stack stack; // stack at time ins was executed + private Variables variables; // variables at time ins was executed private List pops = new ArrayList<>(); // stack contexts popped by instruction execution private List pushes = new ArrayList<>(); // stack contexts pushed by instruction execution private List reads = new ArrayList<>(); // lvt reads @@ -22,6 +23,7 @@ public class InstructionContext ins = i; frame = f; stack = new Stack(frame.getStack()); + variables = new Variables(frame.getVariables()); } public void pop(StackContext... ctx) @@ -42,7 +44,10 @@ public class InstructionContext public void read(VariableContext... ctx) { for (VariableContext c : ctx) + { + c.addRead(this); reads.add(c); + } } public void invoke(Method method) @@ -60,6 +65,11 @@ public class InstructionContext return stack; } + public Variables getVariables() + { + return variables; + } + public List getPops() { return pops; diff --git a/src/main/java/net/runelite/deob/execution/VariableContext.java b/src/main/java/net/runelite/deob/execution/VariableContext.java index 3e6a0f9fd6..9b4560e4c5 100644 --- a/src/main/java/net/runelite/deob/execution/VariableContext.java +++ b/src/main/java/net/runelite/deob/execution/VariableContext.java @@ -1,10 +1,14 @@ package net.runelite.deob.execution; +import java.util.ArrayList; +import java.util.List; + public class VariableContext { private StackContext ctx; // the value stored private InstructionContext ic; // the instruction which stored it. also ctx.popped? private Type type; + private List read = new ArrayList<>(); // instructions which reads this public VariableContext(InstructionContext i, StackContext ctx) { @@ -23,8 +27,24 @@ public class VariableContext return ctx; } + public InstructionContext getInstructionWhichStored() + { + return ic; + } + public Type getType() { return type; } + + public void addRead(InstructionContext ctx) + { + if (!read.contains(ctx)) + read.add(ctx); + } + + public List getRead() + { + return read; + } } diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index 66da96a6d7..aff4323282 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -16,6 +16,7 @@ import net.runelite.deob.attributes.code.instructions.IConst_3; import net.runelite.deob.attributes.code.instructions.IDiv; import net.runelite.deob.attributes.code.instructions.ILoad; import net.runelite.deob.attributes.code.instructions.IMul; +import net.runelite.deob.attributes.code.instructions.IStore; import net.runelite.deob.attributes.code.instructions.IStore_0; import net.runelite.deob.attributes.code.instructions.If0; import net.runelite.deob.attributes.code.instructions.LDC_W; @@ -297,4 +298,64 @@ public class MultiplicationDeobfuscatorTest Assert.assertEquals(1, constant1.getConstantAsInt()); Assert.assertEquals(1, constant2.getConstantAsInt()); } + + @Test + public void testDupX1_5() + { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Instructions ins = code.getInstructions(); + + code.setMaxStack(2); + + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins), + new IConst_2(ins), + new IStore(ins, 1) + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, -2079217519), + constant2 = new LDC_W(ins, -2079217519), + constant3 = new LDC_W(ins, 561453169); + + Instruction body[] = { + new ILoad(ins, 0), + constant1, + new IMul(ins), + new IStore(ins, 2), + + new ILoad(ins, 2), + + new ILoad(ins, 1), + constant2, + new IMul(ins), + + new IAdd(ins), + + constant3, + new IMul(ins), + + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + assert constant1.getConstantAsInt() * constant3.getConstantAsInt() == 1; + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1, constant1.getConstantAsInt()); + Assert.assertEquals(1, constant2.getConstantAsInt()); + Assert.assertEquals(1, constant3.getConstantAsInt()); + } } From 734f15fa4a8e086ef37d34c819a90af0850879b9 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 10 Oct 2015 21:15:07 -0400 Subject: [PATCH 55/58] More tests/fixes I dont know if this is right --- .../code/instructions/IConst_M1.java | 6 + .../deobfuscators/arithmetic/ModArith.java | 22 ++-- .../MultiplicationDeobfuscator.java | 5 +- .../MultiplicationDeobfuscatorTest.java | 103 ++++++++++++++++++ 4 files changed, 122 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java index 7e41464342..bfbe243c6b 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/IConst_M1.java @@ -49,4 +49,10 @@ public class IConst_M1 extends Instruction implements PushConstantInstruction { return new LDC_W(this.getInstructions(), entry); } + + @Override + public Instruction makeGeneric() + { + return new LDC_W(this.getInstructions(), getConstant()); + } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 7cfc6f9622..8e0c14b301 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -310,16 +310,16 @@ public class ModArith implements Deobfuscator public void run(ClassGroup group) { this.group = group; - runOnce(); - if (true) return; - - int passes = 0, total = 0, i; - while ((i = runOnce()) > 0) - { - ++passes; - total += i; - } - System.out.println("Finished arith deob on " + total + " fields in " + passes + " passes"); + //return runOnce(); +// if (true) return; +// +// int passes = 0, total = 0, i; +// while ((i = runOnce()) > 0) +// { +// ++passes; +// total += i; +// } +// System.out.println("Finished arith deob on " + total + " fields in " + passes + " passes"); } // // private void translateSetFields(Execution e) @@ -395,7 +395,7 @@ public class ModArith implements Deobfuscator } } - private int runOnce() + public int runOnce() { group.buildClassGraph(); diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java index 440c7ba9b4..b162082d7b 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscator.java @@ -107,8 +107,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator { if (i.getInstruction() instanceof PushConstantInstruction) { - if (i.getInstruction() instanceof BiPush || i.getInstruction() instanceof SiPush - || i.getInstruction() instanceof IConst_M1) + if (i.getInstruction() instanceof BiPush || i.getInstruction() instanceof SiPush) throw new IllegalStateException(); // a constant of imul @@ -194,7 +193,7 @@ public class MultiplicationDeobfuscator implements Deobfuscator else { System.out.println("dup ins " + otherCtxI.getInstruction()); - throw new IllegalStateException(); + //throw new IllegalStateException(); } } } diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index aff4323282..b803bc3d12 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -13,6 +13,7 @@ import net.runelite.deob.attributes.code.instructions.IConst_0; import net.runelite.deob.attributes.code.instructions.IConst_1; import net.runelite.deob.attributes.code.instructions.IConst_2; import net.runelite.deob.attributes.code.instructions.IConst_3; +import net.runelite.deob.attributes.code.instructions.IConst_M1; import net.runelite.deob.attributes.code.instructions.IDiv; import net.runelite.deob.attributes.code.instructions.ILoad; import net.runelite.deob.attributes.code.instructions.IMul; @@ -358,4 +359,106 @@ public class MultiplicationDeobfuscatorTest Assert.assertEquals(1, constant2.getConstantAsInt()); Assert.assertEquals(1, constant3.getConstantAsInt()); } + + @Test + public void testDupX1_6() + { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Instructions ins = code.getInstructions(); + + code.setMaxStack(2); + + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins), + new IConst_2(ins), + new IStore(ins, 1) + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, 575391417), + constant2 = new LDC_W(ins, -497786999); + + Instruction body[] = { + new ILoad(ins, 0), + new ILoad(ins, 1), + new Dup_X1(ins), + new Pop(ins), + new Pop(ins), + constant1, + new IMul(ins), + constant2, + new IMul(ins), + new Pop(ins), + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1; + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1, constant1.getConstantAsInt()); + Assert.assertEquals(1, constant2.getConstantAsInt()); + } + + @Test + public void testDupX1_7() + { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Instructions ins = code.getInstructions(); + + code.setMaxStack(2); + + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins), + new IConst_2(ins), + new IStore(ins, 1) + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, 2131037801), + constant2 = new LDC_W(ins, -1306959399), + constant3 = new LDC_W(ins, -1); + + Instruction body[] = { + constant3, + constant1, + new IMul(ins), + constant2, + new IMul(ins), + new Pop(ins), + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1; + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1, constant1.getConstantAsInt()); + Assert.assertEquals(-1, constant2.getConstantAsInt()); + Assert.assertEquals(1, constant3.getConstantAsInt()); + } } From 76206edeff9f648be46a82d58d2f2cac0cd4637f Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 10 Oct 2015 22:05:25 -0400 Subject: [PATCH 56/58] More guessing stuff. Need an isobfuscated() func. --- .../deobfuscators/arithmetic/ModArith.java | 145 ++++++++++-------- 1 file changed, 83 insertions(+), 62 deletions(-) diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 8e0c14b301..82140b32ff 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -224,60 +224,75 @@ public class ModArith implements Deobfuscator return p; } -// private Pair guess(Field field, Collection values, boolean getter) -// { -// Map map = CollectionUtils.getCardinalityMap(values); // value -> how many times it occurs -// int max = Collections.max(map.values()); // largest occurance # -// int size = values.size(); -// -//// if (max == size) -//// { -//// // all getters are the same value -//// int constant = getters.iterator().next(); -//// Pair pair = new Pair(); -//// pair.getter = constant; -//// System.out.println("Guessing " + field.getName() + " getter " + constant + " setter "); -//// pair.setter = DMath.modInverse(constant); -//// return pair; -//// } -//// -//// if (size < 50) -//// return null; -// -//// if (((float) max / (float) size) < 0.9) -//// return null; -// -// for (final Map.Entry entry : map.entrySet()) { -// if (max == entry.getValue()) { -// int constant = entry.getKey(); -// int inverse; -// try -// { -// inverse = DMath.modInverse(constant); -// } -// catch (ArithmeticException ex) -// { -// break; -// } -// -// Pair pair = new Pair(); -// if (getter) -// { -// pair.getter = constant; -// pair.setter = inverse; -// } -// else -// { -// pair.getter = inverse; -// pair.setter = constant; -// } -// -// return pair; -// } -// } -// -// return null; -// } + private Pair guess(Field field, Collection values, boolean getter) + { + Map map = CollectionUtils.getCardinalityMap(values); // value -> how many times it occurs + int max = Collections.max(map.values()); // largest occurance # + int size = values.size(); + + try + { + if (max == size) + { + // all getters are the same value + int constant = values.iterator().next(); + if (DMath.isBig(constant)) + { + Pair pair = new Pair(); + if (getter) + { + pair.getter = constant; + //System.out.println("Guessing " + field.getName() + " getter " + constant + " setter "); + pair.setter = DMath.modInverse(constant); + } + else + { + pair.setter = constant; + pair.getter = DMath.modInverse(constant); + } + return pair; + } + } + } + catch (ArithmeticException ex) { } + +// if (size < 50) +// return null; + + if (((float) max / (float) size) < 0.9) + return null; + + for (final Map.Entry entry : map.entrySet()) { + if (max == entry.getValue()) { + int constant = entry.getKey(); + int inverse; + try + { + inverse = DMath.modInverse(constant); + } + catch (ArithmeticException ex) + { + break; + } + + Pair pair = new Pair(); + if (getter) + { + pair.getter = constant; + pair.setter = inverse; + } + else + { + pair.getter = inverse; + pair.setter = constant; + } + + return pair; + } + } + + return null; + } private void reduce() { @@ -287,16 +302,22 @@ public class ModArith implements Deobfuscator Collection getters = constantGetters.getCollection(f), setters = constantSetters.getCollection(f); - if (getters == null || setters == null) - continue; + if (f.getName().equals("field551")) + { + int k=5; + } - Pair answer = reduce(getters, setters); + + Pair answer = null; -// if (answer == null) -// answer = guess(f, getters, true); -// -// if (answer == null) -// answer = guess(f, setters, false); + if (getters != null && setters != null) + answer = reduce(getters, setters); + + if (answer == null && getters != null) + answer = guess(f, getters, true); + + if (answer == null && setters != null) + answer = guess(f, setters, false); if (answer == null) continue; From a0cb4c96d6818a34de48b9dd3ee7475e003ec70a Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 10 Oct 2015 22:05:36 -0400 Subject: [PATCH 57/58] loop multi stuff --- src/main/java/net/runelite/deob/Deob.java | 27 +++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/runelite/deob/Deob.java b/src/main/java/net/runelite/deob/Deob.java index ae12605449..c6cc59b132 100644 --- a/src/main/java/net/runelite/deob/Deob.java +++ b/src/main/java/net/runelite/deob/Deob.java @@ -81,14 +81,27 @@ public class Deob // //new FieldMover().run(group); // // run(group, new UnusedClass()); -// -// run(group, new ModArith()); + + ModArith mod = new ModArith(); + mod.run(group); - new MultiplicationDeobfuscator().run(group); - -// new MultiplyOneDeobfuscator().run(group); -// -// new MultiplyZeroDeobfuscator().run(group); + int last = -1, cur; + while ((cur = mod.runOnce()) > 0) + { + new MultiplicationDeobfuscator().run(group); + + new MultiplyOneDeobfuscator().run(group); + + new MultiplyZeroDeobfuscator().run(group); + + if (last == cur) + { + System.out.println("break"); + break; + } + + last = cur; + } saveJar(group, args[1]); From 99985d7d6f6223a7ad38a9c9995dfd1bdd822813 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 11 Oct 2015 19:38:36 -0400 Subject: [PATCH 58/58] class172/field2976 passed to invoke is not simplified --- src/main/java/net/runelite/deob/Field.java | 23 +++++ src/main/java/net/runelite/deob/Fields.java | 5 ++ src/main/java/net/runelite/deob/Method.java | 10 ++- .../runelite/deob/attributes/Attributes.java | 5 ++ .../code/instructions/GetStatic.java | 7 ++ .../code/instructions/InvokeStatic.java | 7 ++ .../deob/deobfuscators/arithmetic/DMath.java | 5 +- .../deobfuscators/arithmetic/ModArith.java | 83 ++++++++++++++++-- .../net/runelite/deob/ClassGroupFactory.java | 20 +++++ .../MultiplicationDeobfuscatorTest.java | 87 +++++++++++++++++-- 10 files changed, 237 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/runelite/deob/Field.java b/src/main/java/net/runelite/deob/Field.java index c9f2bfd3a1..05bb4aeff5 100644 --- a/src/main/java/net/runelite/deob/Field.java +++ b/src/main/java/net/runelite/deob/Field.java @@ -9,6 +9,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Objects; +import net.runelite.deob.pool.NameAndType; public class Field { @@ -41,6 +42,15 @@ public class Field attributes = new Attributes(this, is); } + public Field(Fields fields, String name, Type type) + { + this.fields = fields; + this.name = name; + this.type = type; + + attributes = new Attributes(this); + } + public void write(DataOutputStream out) throws IOException { ConstantPool pool = fields.getClassFile().getPool(); @@ -70,6 +80,11 @@ public class Field { return (accessFlags & ACC_STATIC) != 0; } + + public void setStatic() + { + accessFlags |= ACC_STATIC; + } public String getName() { @@ -95,6 +110,14 @@ public class Field { return attributes; } + + public net.runelite.deob.pool.Field getPoolField() + { + return new net.runelite.deob.pool.Field( + new net.runelite.deob.pool.Class(this.getFields().getClassFile().getName()), + new NameAndType(this.getName(), this.getType()) + ); + } @Override public int hashCode() diff --git a/src/main/java/net/runelite/deob/Fields.java b/src/main/java/net/runelite/deob/Fields.java index 471eaaf9a7..d363dabfc9 100644 --- a/src/main/java/net/runelite/deob/Fields.java +++ b/src/main/java/net/runelite/deob/Fields.java @@ -40,6 +40,11 @@ public class Fields { return classFile; } + + public void addField(Field field) + { + fields.add(field); + } public List getFields() { diff --git a/src/main/java/net/runelite/deob/Method.java b/src/main/java/net/runelite/deob/Method.java index e32c63d51b..77a2833c83 100644 --- a/src/main/java/net/runelite/deob/Method.java +++ b/src/main/java/net/runelite/deob/Method.java @@ -145,5 +145,13 @@ public class Method } return list; - } + } + + public net.runelite.deob.pool.Method getPoolMethod() + { + return new net.runelite.deob.pool.Method( + new net.runelite.deob.pool.Class(this.getMethods().getClassFile().getName()), + new NameAndType(this.getName(), this.getDescriptor()) + ); + } } diff --git a/src/main/java/net/runelite/deob/attributes/Attributes.java b/src/main/java/net/runelite/deob/attributes/Attributes.java index be8c8a816c..b76cf0d24c 100644 --- a/src/main/java/net/runelite/deob/attributes/Attributes.java +++ b/src/main/java/net/runelite/deob/attributes/Attributes.java @@ -37,6 +37,11 @@ public class Attributes load(is); } + + public Attributes(Field f) + { + field = f; + } public Attributes(Method m) { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java index 3cd81d4496..7299357251 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/GetStatic.java @@ -29,6 +29,13 @@ public class GetStatic extends Instruction implements GetFieldInstruction super(instructions, type, pc); } + public GetStatic(Instructions instructions, Field field) + { + super(instructions, InstructionType.GETSTATIC, -1); + + this.field = field; + } + @Override public void load(DataInputStream is) throws IOException { diff --git a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java index 5d434e9793..d3bc166584 100644 --- a/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java +++ b/src/main/java/net/runelite/deob/attributes/code/instructions/InvokeStatic.java @@ -33,6 +33,13 @@ public class InvokeStatic extends Instruction implements InvokeInstruction super(instructions, type, pc); } + public InvokeStatic(Instructions instructions, Method method) + { + super(instructions, InstructionType.INVOKESTATIC, -1); + + this.method = method; + } + @Override public void load(DataInputStream is) throws IOException { diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java index 84496a5c93..3fe017b9c2 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/DMath.java @@ -35,6 +35,9 @@ public class DMath public static boolean isBig(int val) { - return (val & 0xFFF00000) != 0; + if ((val & 0x80000000) != 0) + val = ~val + 1; + + return (val & 0x7FF00000) != 0; } } diff --git a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java index 82140b32ff..7be0b2f06a 100644 --- a/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java +++ b/src/main/java/net/runelite/deob/deobfuscators/arithmetic/ModArith.java @@ -37,6 +37,76 @@ public class ModArith implements Deobfuscator private List pairs = new ArrayList<>(); private Set deobfuscatedFields = new HashSet<>(); + private List getInsInExpr(InstructionContext ctx, Set set) + { + List l = new ArrayList<>(); + + if (ctx == null || set.contains(ctx.getInstruction())) + return l; + + set.add(ctx.getInstruction()); + + l.add(ctx); + + for (StackContext s : ctx.getPops()) + l.addAll(getInsInExpr(s.getPushed(), set)); + for (StackContext s : ctx.getPushes()) + for (InstructionContext i : s.getPopped()) + l.addAll(getInsInExpr(i, set)); + + return l; + } + + private boolean isFieldObfuscated(Execution e, Field field) + { + // field isn't obfuscated if there are no usages with big constants and no other fields + + for (Frame f : execution.processedFrames) + outer: + for (InstructionContext ctx : f.getInstructions()) + { + if (!(ctx.getInstruction() instanceof FieldInstruction)) + continue; + + FieldInstruction fi = (FieldInstruction) ctx.getInstruction(); + + if (fi.getMyField() != field) + continue; + + List ins = getInsInExpr(ctx, new HashSet()); + + // continue if expr contains another ins + for (InstructionContext i : ins) + { + if (i.getInstruction() instanceof FieldInstruction) + { + FieldInstruction ifi = (FieldInstruction) i.getInstruction(); + + if (ifi.getMyField() != field) + continue outer; + } + } + + // find big constant + for (InstructionContext i : ins) + { + if (i.getInstruction() instanceof LDC_W) + { + LDC_W ldc = (LDC_W) i.getInstruction(); + if (ldc.getConstant().getObject() instanceof Integer) + { + int value = ldc.getConstantAsInt(); + + if (DMath.isBig(value)) + return true; + } + } + } + } + + return false; + } + private List findAssocConstants(Field field, InstructionContext ctx) throws OtherFieldException { // starts with ctx = setfield @@ -97,11 +167,6 @@ public class ModArith implements Deobfuscator if (field == null) continue; - if (field.getName().equals("field2201")) - { - int k=7; - } - int value = (int) pc.getConstant().getObject(); if (value == 1 || value == 0) @@ -302,7 +367,7 @@ public class ModArith implements Deobfuscator Collection getters = constantGetters.getCollection(f), setters = constantSetters.getCollection(f); - if (f.getName().equals("field551")) + if (f.getName().equals("field2976")) { int k=5; } @@ -322,6 +387,12 @@ public class ModArith implements Deobfuscator if (answer == null) continue; + if (!this.isFieldObfuscated(execution, f)) + { + System.out.println("Skipping field " + f.getName() + " which isnt obfuscated"); + continue; + } + answer.field = f; pairs.add(answer); } diff --git a/src/test/java/net/runelite/deob/ClassGroupFactory.java b/src/test/java/net/runelite/deob/ClassGroupFactory.java index 16fd6195ed..f9553259e6 100644 --- a/src/test/java/net/runelite/deob/ClassGroupFactory.java +++ b/src/test/java/net/runelite/deob/ClassGroupFactory.java @@ -2,7 +2,10 @@ package net.runelite.deob; import net.runelite.deob.attributes.Attributes; import net.runelite.deob.attributes.Code; +import net.runelite.deob.attributes.code.Instructions; +import net.runelite.deob.attributes.code.instructions.VReturn; import net.runelite.deob.signature.Signature; +import net.runelite.deob.signature.Type; public class ClassGroupFactory { @@ -15,6 +18,11 @@ public class ClassGroupFactory cf.setSuperName("java/lang/Object"); group.addClass(cf); + Fields fields = cf.getFields(); + Field field = new Field(fields, "field", new Type("I")); + field.setStatic(); + fields.addField(field); + Methods methods = cf.getMethods(); Method method = new Method(methods, "func", new Signature("()V")); method.setStatic(); @@ -25,6 +33,18 @@ public class ClassGroupFactory Code code = new Code(methodAttributes); methodAttributes.addAttribute(code); + method = new Method(methods, "func2", new Signature("(III)V")); + method.setStatic(); + methods.addMethod(method); + + methodAttributes = method.getAttributes(); + + code = new Code(methodAttributes); + methodAttributes.addAttribute(code); + + Instructions ins = code.getInstructions(); + ins.addInstruction(new VReturn(ins)); + return group; } } diff --git a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java index b803bc3d12..d1fc2b2952 100644 --- a/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java +++ b/src/test/java/net/runelite/deob/deobfuscators/arithmetic/MultiplicationDeobfuscatorTest.java @@ -4,10 +4,13 @@ import java.util.Collection; import net.runelite.deob.ClassGroup; import net.runelite.deob.ClassGroupFactory; import net.runelite.deob.Deobfuscator; +import net.runelite.deob.Field; import net.runelite.deob.attributes.Code; import net.runelite.deob.attributes.code.Instruction; import net.runelite.deob.attributes.code.Instructions; import net.runelite.deob.attributes.code.instructions.Dup_X1; +import net.runelite.deob.attributes.code.instructions.GetStatic; +import net.runelite.deob.attributes.code.instructions.Goto; import net.runelite.deob.attributes.code.instructions.IAdd; import net.runelite.deob.attributes.code.instructions.IConst_0; import net.runelite.deob.attributes.code.instructions.IConst_1; @@ -20,6 +23,7 @@ import net.runelite.deob.attributes.code.instructions.IMul; import net.runelite.deob.attributes.code.instructions.IStore; import net.runelite.deob.attributes.code.instructions.IStore_0; import net.runelite.deob.attributes.code.instructions.If0; +import net.runelite.deob.attributes.code.instructions.InvokeStatic; import net.runelite.deob.attributes.code.instructions.LDC_W; import net.runelite.deob.attributes.code.instructions.NOP; import net.runelite.deob.attributes.code.instructions.Pop; @@ -43,7 +47,7 @@ public class MultiplicationDeobfuscatorTest // imul // putstatic class29/field949 I @Test - public void testDupX1_1() + public void test1() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -113,7 +117,7 @@ public class MultiplicationDeobfuscatorTest // ldc 561453169 // imul @Test - public void testDupX1_2() + public void test2() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -172,7 +176,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_3() + public void test3() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -244,7 +248,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_4() + public void test4() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -301,7 +305,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_5() + public void test5() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -361,7 +365,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_6() + public void test6() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -413,7 +417,7 @@ public class MultiplicationDeobfuscatorTest } @Test - public void testDupX1_7() + public void test7() { ClassGroup group = ClassGroupFactory.generateGroup(); Code code = group.findClass("test").findMethod("func").getCode(); @@ -461,4 +465,73 @@ public class MultiplicationDeobfuscatorTest Assert.assertEquals(-1, constant2.getConstantAsInt()); Assert.assertEquals(1, constant3.getConstantAsInt()); } + + @Test + public void test8() + { + ClassGroup group = ClassGroupFactory.generateGroup(); + Code code = group.findClass("test").findMethod("func").getCode(); + Code code2 = group.findClass("test").findMethod("func2").getCode(); + Field field = group.findClass("test").findField("field"); + Instructions ins = code.getInstructions(); + + code.setMaxStack(2); + + Instruction[] prepareVariables = { + new IConst_3(ins), + new IStore_0(ins) + }; + + for (Instruction i : prepareVariables) + ins.addInstruction(i); + + LDC_W constant1 = new LDC_W(ins, -1616202347), + constant2 = new LDC_W(ins, 2747837); + + NOP label1 = new NOP(ins), + label2 = new NOP(ins), + label3 = new NOP(ins); + + Instruction body[] = { + new GetStatic(ins, field.getPoolField()), + constant1, + new IMul(ins), + constant2, + new IMul(ins), + + new ILoad(ins, 0), + + new LDC_W(ins, 42), + new If0(ins, label1), + new Goto(ins, label2), + + label1, + new IConst_M1(ins), + new Goto(ins, label3), + + label2, + new IConst_0(ins), + new Goto(ins, label3), + + label3, + new InvokeStatic(ins, group.findClass("test").findMethod("func2").getPoolMethod()), + + new VReturn(ins) + }; + + for (Instruction i : body) + ins.addInstruction(i); + + Execution e = new Execution(group); + e.populateInitialMethods(); + e.run(); + + assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1; + + Deobfuscator d = new MultiplicationDeobfuscator(); + d.run(group); + + Assert.assertEquals(1, constant1.getConstantAsInt()); + Assert.assertEquals(1, constant2.getConstantAsInt()); + } }