Limited support for getting around iload/istore, Add test too. Seems to work?

This commit is contained in:
Adam
2015-10-10 16:21:22 -04:00
parent db089ab628
commit 27f2edbea6
4 changed files with 124 additions and 20 deletions

View File

@@ -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)
{ {

View File

@@ -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;

View File

@@ -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;
}
} }

View File

@@ -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());
}
} }