Limited support for getting around iload/istore, Add test too. Seems to work?
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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<StackContext> pops = new ArrayList<>(); // stack contexts popped by instruction execution
|
||||
private List<StackContext> pushes = new ArrayList<>(); // stack contexts pushed by instruction execution
|
||||
private List<VariableContext> 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<StackContext> getPops()
|
||||
{
|
||||
return pops;
|
||||
|
||||
@@ -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<InstructionContext> 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<InstructionContext> getRead()
|
||||
{
|
||||
return read;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user