Search in sources :

Example 1 with Swap

use of net.runelite.asm.attributes.code.instructions.Swap in project runelite by runelite.

the class MultiplicationDeobfuscator method parseExpression.

public static MultiplicationExpression parseExpression(InstructionContext ctx, Class want) {
    MultiplicationExpression me = new MultiplicationExpression();
    if (ctx.getInstruction() instanceof LVTInstruction) {
        LVTInstruction lvt = (LVTInstruction) ctx.getInstruction();
        // loading a variable
        if (!lvt.store()) {
            // var index
            int idx = lvt.getVariableIndex();
            // variables at time of execution
            Variables vars = ctx.getVariables();
            // get the variable
            VariableContext vctx = vars.get(idx);
            if (// ?
            vctx.getRead().size() == 1) {
                // this is an istore
                InstructionContext storeCtx = vctx.getInstructionWhichStored();
                if (storeCtx.getInstruction() instanceof LVTInstruction) {
                    // invoking funcs can put stuff in lvt
                    LVTInstruction storelvt = (LVTInstruction) storeCtx.getInstruction();
                    if (storelvt instanceof IInc)
                        throw new IllegalStateException();
                    assert storelvt.store();
                    InstructionContext pushed = storeCtx.getPops().get(0).getPushed();
                    return parseExpression(pushed, want);
                }
            }
        }
    }
    if (ctx.getInstruction() instanceof PushConstantInstruction) {
        if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush) {
            throw new IllegalStateException();
        }
        me.instructions.add(ctx);
        return me;
    }
    for (StackContext sctx : ctx.getPops()) {
        if (ctx.getInstruction().getClass() == want) {
            if (!isOnlyPath(ctx, sctx))
                continue;
        }
        InstructionContext i = sctx.getPushed();
        // if this instruction is imul, look at pops
        if (ctx.getInstruction().getClass() == want) {
            if (i.getInstruction() instanceof Swap) {
                logger.debug("Resolving swap");
                Swap swap = (Swap) i.getInstruction();
                sctx = swap.getOriginal(sctx);
                i = sctx.getPushed();
            }
            if (i.getInstruction() instanceof PushConstantInstruction) {
                // bipush/sipush are always not obfuscated
                if (i.getInstruction() instanceof BiPush || i.getInstruction() instanceof SiPush)
                    continue;
                // a constant of imul
                me.instructions.add(i);
            } else if (i.getInstruction().getClass() == want) {
                // chained imul, append to me
                try {
                    MultiplicationExpression other = parseExpression(i, want);
                    if (other.dupmagic != null) {
                        assert me.dupmagic == null;
                        me.dupmagic = other.dupmagic;
                    }
                    me.instructions.addAll(other.instructions);
                    me.dupedInstructions.addAll(other.dupedInstructions);
                    me.subexpressions.addAll(other.subexpressions);
                } catch (IllegalStateException ex) {
                // this is ok? just don't include it?
                }
            } else if (i.getInstruction() instanceof IAdd || i.getInstruction() instanceof ISub || i.getInstruction() instanceof LAdd || i.getInstruction() instanceof LSub) {
                // imul using result of iadd or isub. evaluate expression
                try {
                    MultiplicationExpression other = parseExpression(i, want);
                    assert other.dupmagic == null;
                    // subexpr
                    me.subexpressions.add(other);
                } catch (IllegalStateException ex) {
                    assert me.subexpressions.isEmpty();
                // subexpression is too complex. we can still simplify the top level though
                }
            } else if (i.getInstruction() instanceof DupInstruction) {
                DupInstruction dup = (DupInstruction) i.getInstruction();
                // find other branch of the dup instruction
                // sctx = what dup pushed, find other
                // other side of dup
                StackContext otherCtx = dup.getOtherBranch(sctx);
                // what popped other side of dup. is this right?
                InstructionContext otherCtxI = otherCtx.getPopped().get(0);
                if (otherCtxI.getInstruction().getClass() == want) {
                    // assert otherCtxI.getInstruction() instanceof IMul;
                    // other side of that imul
                    InstructionContext pushConstant = otherCtxI.getPops().get(0).getPushed();
                    assert pushConstant.getInstruction() instanceof LDC;
                    me.dupmagic = pushConstant;
                    // original
                    StackContext orig = dup.getOriginal(sctx);
                    try {
                        MultiplicationExpression other = parseExpression(orig.getPushed(), want);
                        // done to it affect that, too. so multiply it by existing values?
                        if (orig.getPushed().getInstruction() instanceof IAdd || orig.getPushed().getInstruction() instanceof ISub || orig.getPushed().getInstruction() instanceof LAdd || orig.getPushed().getInstruction() instanceof LSub) {
                            me.subexpressions.add(other);
                        } else {
                            assert other.dupmagic == null;
                            me.instructions.addAll(other.instructions);
                            me.dupedInstructions.addAll(other.instructions);
                            me.subexpressions.addAll(other.subexpressions);
                        }
                    } catch (IllegalStateException ex) {
                        assert me.subexpressions.isEmpty();
                    }
                }
            } else if (i.getInstruction() instanceof GetFieldInstruction) {
                me.fieldInstructions.add(i);
            // non constant, ignore
            } else {
            // System.out.println("imul pops something I don't know " + i.getInstruction());
            }
        } else // this is an iadd/sub
        if (ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub || ctx.getInstruction() instanceof LAdd || ctx.getInstruction() instanceof LSub) {
            // parse this side of the add/sub
            MultiplicationExpression other = parseExpression(i, want);
            me.subexpressions.add(other);
        } else {
        // System.out.println(ctx.getInstruction() + " pops something I dont know " + i.getInstruction());
        }
    }
    if (me.instructions.isEmpty() && me.subexpressions.isEmpty())
        throw new IllegalStateException();
    return me;
}
Also used : SiPush(net.runelite.asm.attributes.code.instructions.SiPush) InstructionContext(net.runelite.asm.execution.InstructionContext) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) DupInstruction(net.runelite.asm.attributes.code.instruction.types.DupInstruction) LDC(net.runelite.asm.attributes.code.instructions.LDC) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) VariableContext(net.runelite.asm.execution.VariableContext) BiPush(net.runelite.asm.attributes.code.instructions.BiPush) Variables(net.runelite.asm.execution.Variables) Swap(net.runelite.asm.attributes.code.instructions.Swap) ISub(net.runelite.asm.attributes.code.instructions.ISub) StackContext(net.runelite.asm.execution.StackContext) LAdd(net.runelite.asm.attributes.code.instructions.LAdd) IInc(net.runelite.asm.attributes.code.instructions.IInc) LSub(net.runelite.asm.attributes.code.instructions.LSub) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)

Example 2 with Swap

use of net.runelite.asm.attributes.code.instructions.Swap in project runelite by runelite.

the class DupDeobfuscator method undup_x1.

private void undup_x1(InstructionContext ictx) {
    assert ictx.getInstruction() instanceof Dup_X1;
    Instructions instructions = ictx.getInstruction().getInstructions();
    StackContext duplicated = ictx.getPops().get(0);
    // replace dup_x1 with swap
    int idx = instructions.replace(ictx.getInstruction(), new Swap(instructions));
    // copy imul and insert after idx
    copy(duplicated, instructions, idx + 1);
}
Also used : Swap(net.runelite.asm.attributes.code.instructions.Swap) StackContext(net.runelite.asm.execution.StackContext) Dup_X1(net.runelite.asm.attributes.code.instructions.Dup_X1) Instructions(net.runelite.asm.attributes.code.Instructions)

Example 3 with Swap

use of net.runelite.asm.attributes.code.instructions.Swap in project runelite by runelite.

the class InstructionContext method resolve.

public InstructionContext resolve(// pushed from this
StackContext from) {
    InstructionContext ctx = this;
    if (ctx.getInstruction() instanceof SetFieldInstruction) {
        StackContext s = ctx.getPops().get(0);
        return s.getPushed().resolve(s);
    }
    if (ctx.getInstruction() instanceof DupInstruction) {
        DupInstruction d = (DupInstruction) ctx.getInstruction();
        StackContext s = d.getOriginal(from);
        return s.getPushed().resolve(s);
    }
    if (ctx.getInstruction() instanceof LVTInstruction) {
        LVTInstruction lvt = (LVTInstruction) ctx.getInstruction();
        Variables variables = ctx.getVariables();
        if (lvt.store()) {
            // is this right?
            StackContext s = ctx.getPops().get(0);
            return s.getPushed().resolve(s);
        } else {
            // variable being loaded
            VariableContext vctx = variables.get(lvt.getVariableIndex());
            assert vctx != null;
            InstructionContext storedCtx = vctx.getInstructionWhichStored();
            if (storedCtx == null)
                // initial parameter
                return ctx;
            if (vctx.isIsParameter())
                // parameter (storedCtx is invoking instruction in another frame). this lvt index is fixed.
                return ctx;
            return storedCtx.resolve(null);
        }
    }
    if (ctx.getInstruction() instanceof Swap) {
        Swap swap = (Swap) ctx.getInstruction();
        StackContext s = swap.getOriginal(from);
        return s.getPushed().resolve(s);
    }
    return ctx;
}
Also used : SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) Swap(net.runelite.asm.attributes.code.instructions.Swap) DupInstruction(net.runelite.asm.attributes.code.instruction.types.DupInstruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction)

Example 4 with Swap

use of net.runelite.asm.attributes.code.instructions.Swap in project runelite by runelite.

the class MultiplicationDeobfuscatorTest method test12.

// 020   aload_0
// 021   aload_0
// 022   iload_1
// 023   ldc                   1129258489
// 024   imul						// this, this, mul
// 025   swap						// this, mul s, this
// 026   iload_1
// 027   iconst_1
// 028   imul						// this, mul s, this, mul
// 029   iconst_1
// 030   imul
// 031   putfield              class81/field1351 I       // this, mul
// 032   iconst_1
// 033   imul
// 034   ldc                   -1692330935
// 035   imul
// 036   putfield              class81/field1326 I
@Test
public void test12() {
    ClassGroup group = ClassGroupFactory.generateGroup();
    Code code = group.findClass("test").findMethod("func").getCode();
    Instructions ins = code.getInstructions();
    code.setMaxStack(5);
    Instruction[] prepareVariables = { new LDC(ins, 1), new IStore(ins, 0) };
    for (Instruction i : prepareVariables) {
        ins.addInstruction(i);
    }
    LDC constant1 = new LDC(ins, 1129258489);
    LDC constant2 = new LDC(ins, -1692330935);
    Instruction[] body = { // this
    new AConstNull(ins), // this
    new AConstNull(ins), new ILoad(ins, 0), constant1, new IMul(ins), // null, mul, null
    new Swap(ins), new ILoad(ins, 0), // putfield
    new Pop2(ins), constant2, new IMul(ins), // putfield
    new Pop2(ins), new VReturn(ins) };
    for (Instruction i : body) {
        ins.addInstruction(i);
    }
    Execution e = new Execution(group);
    e.populateInitialMethods();
    e.run();
    assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
    Deobfuscator d = new MultiplicationDeobfuscator();
    d.run(group);
    Assert.assertEquals(1, constant1.getConstantAsInt());
    Assert.assertEquals(1, constant2.getConstantAsInt());
}
Also used : IStore(net.runelite.asm.attributes.code.instructions.IStore) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) Pop2(net.runelite.asm.attributes.code.instructions.Pop2) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.instructions.LDC) AConstNull(net.runelite.asm.attributes.code.instructions.AConstNull) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) VReturn(net.runelite.asm.attributes.code.instructions.VReturn) Deobfuscator(net.runelite.deob.Deobfuscator) Execution(net.runelite.asm.execution.Execution) Swap(net.runelite.asm.attributes.code.instructions.Swap) ClassGroup(net.runelite.asm.ClassGroup) IMul(net.runelite.asm.attributes.code.instructions.IMul) Test(org.junit.Test)

Aggregations

Swap (net.runelite.asm.attributes.code.instructions.Swap)4 Instructions (net.runelite.asm.attributes.code.Instructions)2 DupInstruction (net.runelite.asm.attributes.code.instruction.types.DupInstruction)2 LVTInstruction (net.runelite.asm.attributes.code.instruction.types.LVTInstruction)2 LDC (net.runelite.asm.attributes.code.instructions.LDC)2 StackContext (net.runelite.asm.execution.StackContext)2 ClassGroup (net.runelite.asm.ClassGroup)1 Code (net.runelite.asm.attributes.Code)1 Instruction (net.runelite.asm.attributes.code.Instruction)1 GetFieldInstruction (net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)1 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)1 SetFieldInstruction (net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction)1 AConstNull (net.runelite.asm.attributes.code.instructions.AConstNull)1 BiPush (net.runelite.asm.attributes.code.instructions.BiPush)1 Dup_X1 (net.runelite.asm.attributes.code.instructions.Dup_X1)1 IAdd (net.runelite.asm.attributes.code.instructions.IAdd)1 IInc (net.runelite.asm.attributes.code.instructions.IInc)1 ILoad (net.runelite.asm.attributes.code.instructions.ILoad)1 IMul (net.runelite.asm.attributes.code.instructions.IMul)1 IStore (net.runelite.asm.attributes.code.instructions.IStore)1