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.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import net.runelite.deob.ClassGroup;
|
import net.runelite.deob.ClassGroup;
|
||||||
import net.runelite.deob.Deobfuscator;
|
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.Instructions;
|
||||||
import net.runelite.deob.attributes.code.instruction.types.DupInstruction;
|
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.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.instruction.types.PushConstantInstruction;
|
||||||
import net.runelite.deob.attributes.code.instructions.BiPush;
|
import net.runelite.deob.attributes.code.instructions.BiPush;
|
||||||
import net.runelite.deob.attributes.code.instructions.IAdd;
|
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.Frame;
|
||||||
import net.runelite.deob.execution.InstructionContext;
|
import net.runelite.deob.execution.InstructionContext;
|
||||||
import net.runelite.deob.execution.StackContext;
|
import net.runelite.deob.execution.StackContext;
|
||||||
|
import net.runelite.deob.execution.VariableContext;
|
||||||
|
import net.runelite.deob.execution.Variables;
|
||||||
|
|
||||||
public class MultiplicationDeobfuscator implements Deobfuscator
|
public class MultiplicationDeobfuscator implements Deobfuscator
|
||||||
{
|
{
|
||||||
@@ -48,6 +50,36 @@ public class MultiplicationDeobfuscator implements Deobfuscator
|
|||||||
|
|
||||||
assert !(ctx.getInstruction() instanceof DupInstruction);
|
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 PushConstantInstruction)
|
||||||
{
|
{
|
||||||
if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush
|
if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush
|
||||||
@@ -60,35 +92,16 @@ public class MultiplicationDeobfuscator implements Deobfuscator
|
|||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (ctx.getInstruction() instanceof IMul)
|
|
||||||
// {
|
|
||||||
// if (!isOnlyPath(e, ctx))
|
|
||||||
// throw new IllegalStateException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
for (StackContext sctx : ctx.getPops())
|
for (StackContext sctx : ctx.getPops())
|
||||||
{
|
{
|
||||||
if (ctx.getInstruction() instanceof IMul)
|
if (ctx.getInstruction() instanceof IMul)
|
||||||
{
|
{
|
||||||
if (!isOnlyPath(e, ctx, sctx))
|
if (!isOnlyPath(e, ctx, sctx))
|
||||||
continue;
|
continue;
|
||||||
//throw new IllegalStateException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionContext i = sctx.getPushed();
|
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 this instruction is imul, look at pops
|
||||||
if (ctx.getInstruction() instanceof IMul)
|
if (ctx.getInstruction() instanceof IMul)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public class InstructionContext
|
|||||||
private Instruction ins;
|
private Instruction ins;
|
||||||
private Frame frame;
|
private Frame frame;
|
||||||
private Stack stack; // stack at time ins was executed
|
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> pops = new ArrayList<>(); // stack contexts popped by instruction execution
|
||||||
private List<StackContext> pushes = new ArrayList<>(); // stack contexts pushed by instruction execution
|
private List<StackContext> pushes = new ArrayList<>(); // stack contexts pushed by instruction execution
|
||||||
private List<VariableContext> reads = new ArrayList<>(); // lvt reads
|
private List<VariableContext> reads = new ArrayList<>(); // lvt reads
|
||||||
@@ -22,6 +23,7 @@ public class InstructionContext
|
|||||||
ins = i;
|
ins = i;
|
||||||
frame = f;
|
frame = f;
|
||||||
stack = new Stack(frame.getStack());
|
stack = new Stack(frame.getStack());
|
||||||
|
variables = new Variables(frame.getVariables());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pop(StackContext... ctx)
|
public void pop(StackContext... ctx)
|
||||||
@@ -42,7 +44,10 @@ public class InstructionContext
|
|||||||
public void read(VariableContext... ctx)
|
public void read(VariableContext... ctx)
|
||||||
{
|
{
|
||||||
for (VariableContext c : ctx)
|
for (VariableContext c : ctx)
|
||||||
|
{
|
||||||
|
c.addRead(this);
|
||||||
reads.add(c);
|
reads.add(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invoke(Method method)
|
public void invoke(Method method)
|
||||||
@@ -60,6 +65,11 @@ public class InstructionContext
|
|||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Variables getVariables()
|
||||||
|
{
|
||||||
|
return variables;
|
||||||
|
}
|
||||||
|
|
||||||
public List<StackContext> getPops()
|
public List<StackContext> getPops()
|
||||||
{
|
{
|
||||||
return pops;
|
return pops;
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
package net.runelite.deob.execution;
|
package net.runelite.deob.execution;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class VariableContext
|
public class VariableContext
|
||||||
{
|
{
|
||||||
private StackContext ctx; // the value stored
|
private StackContext ctx; // the value stored
|
||||||
private InstructionContext ic; // the instruction which stored it. also ctx.popped?
|
private InstructionContext ic; // the instruction which stored it. also ctx.popped?
|
||||||
private Type type;
|
private Type type;
|
||||||
|
private List<InstructionContext> read = new ArrayList<>(); // instructions which reads this
|
||||||
|
|
||||||
public VariableContext(InstructionContext i, StackContext ctx)
|
public VariableContext(InstructionContext i, StackContext ctx)
|
||||||
{
|
{
|
||||||
@@ -23,8 +27,24 @@ public class VariableContext
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InstructionContext getInstructionWhichStored()
|
||||||
|
{
|
||||||
|
return ic;
|
||||||
|
}
|
||||||
|
|
||||||
public Type getType()
|
public Type getType()
|
||||||
{
|
{
|
||||||
return type;
|
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.IDiv;
|
||||||
import net.runelite.deob.attributes.code.instructions.ILoad;
|
import net.runelite.deob.attributes.code.instructions.ILoad;
|
||||||
import net.runelite.deob.attributes.code.instructions.IMul;
|
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_0;
|
||||||
import net.runelite.deob.attributes.code.instructions.If0;
|
import net.runelite.deob.attributes.code.instructions.If0;
|
||||||
import net.runelite.deob.attributes.code.instructions.LDC_W;
|
import net.runelite.deob.attributes.code.instructions.LDC_W;
|
||||||
@@ -297,4 +298,64 @@ public class MultiplicationDeobfuscatorTest
|
|||||||
Assert.assertEquals(1, constant1.getConstantAsInt());
|
Assert.assertEquals(1, constant1.getConstantAsInt());
|
||||||
Assert.assertEquals(1, constant2.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