From 27f2edbea663dc97016a62336720bb1a643e0b40 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 10 Oct 2015 16:21:22 -0400 Subject: [PATCH] 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()); + } }