From f46e4dfdceaa43f3d02e53c0266c22c082ed7d7d Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 6 Sep 2015 23:39:47 -0400 Subject: [PATCH] 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();