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 }