Search in sources :

Example 71 with StackContext

use of net.runelite.asm.execution.StackContext in project runelite by runelite.

the class FNeg method execute.

@Override
public InstructionContext execute(Frame frame) {
    InstructionContext ins = new InstructionContext(this, frame);
    Stack stack = frame.getStack();
    StackContext value = stack.pop();
    ins.pop(value);
    Value result = Value.UNKNOWN;
    if (!value.getValue().isUnknownOrNull()) {
        float f = (float) value.getValue().getValue();
        result = new Value(-f);
    }
    StackContext ctx = new StackContext(ins, Type.FLOAT, result);
    stack.push(ctx);
    ins.push(ctx);
    return ins;
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) StackContext(net.runelite.asm.execution.StackContext) Value(net.runelite.asm.execution.Value) Stack(net.runelite.asm.execution.Stack)

Example 72 with StackContext

use of net.runelite.asm.execution.StackContext in project runelite by runelite.

the class ModArith method getInsInExpr.

private static List<InstructionContext> getInsInExpr(InstructionContext ctx, Set<Instruction> set, boolean imul) {
    List<InstructionContext> l = new ArrayList<>();
    if (ctx == null || set.contains(ctx.getInstruction())) {
        return l;
    }
    set.add(ctx.getInstruction());
    if (imul) {
        if (!(ctx.getInstruction() instanceof IMul) & !(ctx.getInstruction() instanceof LMul)) {
            l.add(ctx);
            return l;
        }
    } else {
        // invoke and array store pops are unrelated to each other
        if (ctx.getInstruction() instanceof InvokeInstruction || ctx.getInstruction() instanceof ArrayStoreInstruction || ctx.getInstruction() instanceof ArrayLoad || ctx.getInstruction() instanceof If || ctx.getInstruction() instanceof If0 || ctx.getInstruction() instanceof LCmp || ctx.getInstruction() instanceof DivisionInstruction || ctx.getInstruction() instanceof IShR) {
            return l;
        }
        l.add(ctx);
    }
    for (StackContext s : ctx.getPops()) {
        l.addAll(getInsInExpr(s.getPushed(), set, imul));
    }
    for (StackContext s : ctx.getPushes()) {
        for (InstructionContext i : s.getPopped()) {
            l.addAll(getInsInExpr(i, set, imul));
        }
    }
    return l;
}
Also used : ArrayLoad(net.runelite.asm.attributes.code.instruction.types.ArrayLoad) InstructionContext(net.runelite.asm.execution.InstructionContext) DivisionInstruction(net.runelite.asm.attributes.code.instruction.types.DivisionInstruction) ArrayList(java.util.ArrayList) ArrayStoreInstruction(net.runelite.asm.attributes.code.instruction.types.ArrayStoreInstruction) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) If0(net.runelite.asm.attributes.code.instructions.If0) IShR(net.runelite.asm.attributes.code.instructions.IShR) StackContext(net.runelite.asm.execution.StackContext) IMul(net.runelite.asm.attributes.code.instructions.IMul) LCmp(net.runelite.asm.attributes.code.instructions.LCmp) LMul(net.runelite.asm.attributes.code.instructions.LMul) If(net.runelite.asm.attributes.code.instructions.If)

Example 73 with StackContext

use of net.runelite.asm.execution.StackContext 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 74 with StackContext

use of net.runelite.asm.execution.StackContext in project runelite by runelite.

the class UnusedParameters method removeParameter.

public void removeParameter(ClassGroup group, List<Method> methods, Signature signature, Execution execution, int paramIndex, int lvtIndex) {
    int slots = signature.getTypeOfArg(paramIndex).getSize();
    for (ClassFile cf : group.getClasses()) {
        for (Method m : cf.getMethods()) {
            Code c = m.getCode();
            if (c == null) {
                continue;
            }
            for (Instruction i : new ArrayList<>(c.getInstructions().getInstructions())) {
                if (!(i instanceof InvokeInstruction)) {
                    continue;
                }
                InvokeInstruction ii = (InvokeInstruction) i;
                if (!ii.getMethods().stream().anyMatch(me -> methods.contains(me))) {
                    continue;
                }
                // remove parameter from instruction
                ii.removeParameter(paramIndex);
                Collection<InstructionContext> ics = invokes.get(i);
                assert ics != null;
                if (ics != null) {
                    for (InstructionContext ins : ics) {
                        // index from top of stack of parameter. 0 is the last parameter
                        int pops = signature.size() - paramIndex - 1;
                        StackContext sctx = ins.getPops().get(pops);
                        if (sctx.getPushed().getInstruction().getInstructions() == null) {
                            continue;
                        }
                        // remove parameter from stack
                        ins.removeStack(pops);
                    }
                }
            }
        }
    }
    for (Method method : methods) {
        if (method.getCode() != null) // adjust lvt indexes to get rid of idx in the method
        {
            for (Instruction ins : method.getCode().getInstructions().getInstructions()) {
                if (ins instanceof LVTInstruction) {
                    LVTInstruction lins = (LVTInstruction) ins;
                    int i = lins.getVariableIndex();
                    // current unused variable detection just looks for no accesses
                    assert i != lvtIndex;
                    // reassign
                    if (i > lvtIndex) {
                        assert i > 0;
                        assert i >= lvtIndex + slots;
                        Instruction newIns = lins.setVariableIndex(i - slots);
                        assert ins == newIns;
                    }
                }
            }
        }
    }
    for (Method method : methods) {
        method.getDescriptor().remove(paramIndex);
    }
}
Also used : LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) Code(net.runelite.asm.attributes.Code) Multimap(com.google.common.collect.Multimap) ArrayList(java.util.ArrayList) ClassGroup(net.runelite.asm.ClassGroup) StackContext(net.runelite.asm.execution.StackContext) HashMultimap(com.google.common.collect.HashMultimap) Method(net.runelite.asm.Method) Map(java.util.Map) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) VirtualMethods(net.runelite.asm.signature.util.VirtualMethods) ImmutableSet(com.google.common.collect.ImmutableSet) DeobAnnotations(net.runelite.deob.DeobAnnotations) Logger(org.slf4j.Logger) Deob(net.runelite.deob.Deob) Collection(java.util.Collection) Set(java.util.Set) Deobfuscator(net.runelite.deob.Deobfuscator) InstructionContext(net.runelite.asm.execution.InstructionContext) Sets(com.google.common.collect.Sets) Execution(net.runelite.asm.execution.Execution) List(java.util.List) ClassFile(net.runelite.asm.ClassFile) Signature(net.runelite.asm.signature.Signature) Instruction(net.runelite.asm.attributes.code.Instruction) Collections(java.util.Collections) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) InstructionContext(net.runelite.asm.execution.InstructionContext) ClassFile(net.runelite.asm.ClassFile) StackContext(net.runelite.asm.execution.StackContext) ArrayList(java.util.ArrayList) Method(net.runelite.asm.Method) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) Instruction(net.runelite.asm.attributes.code.Instruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) Code(net.runelite.asm.attributes.Code)

Example 75 with StackContext

use of net.runelite.asm.execution.StackContext in project runelite by runelite.

the class DupDeobfuscator method copy.

/**
 * copy the instruction which pushed sctx and insert into instructions
 * starting at index idx
 */
private int copy(StackContext sctx, Instructions instructions, int idx) {
    InstructionContext ictx = sctx.getPushed();
    if (ictx.getInstruction() instanceof DupInstruction) {
        // we only care about one path
        DupInstruction di = (DupInstruction) ictx.getInstruction();
        sctx = di.getOriginal(sctx);
        ictx = sctx.getPushed();
    }
    // the first thing popped was pushed last, so reverse
    for (StackContext s : Lists.reverse(ictx.getPops())) {
        idx = copy(s, instructions, idx);
    }
    // copy instruction
    Instruction i = ictx.getInstruction();
    logger.debug("Duplicating instruction {} at index {}", i, idx);
    i = i.clone();
    instructions.addInstruction(idx, i);
    // move on to next instruction
    return idx + 1;
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) StackContext(net.runelite.asm.execution.StackContext) DupInstruction(net.runelite.asm.attributes.code.instruction.types.DupInstruction) DupInstruction(net.runelite.asm.attributes.code.instruction.types.DupInstruction) Instruction(net.runelite.asm.attributes.code.Instruction)

Aggregations

StackContext (net.runelite.asm.execution.StackContext)162 InstructionContext (net.runelite.asm.execution.InstructionContext)153 Stack (net.runelite.asm.execution.Stack)119 Value (net.runelite.asm.execution.Value)47 Field (net.runelite.asm.Field)15 Variables (net.runelite.asm.execution.Variables)14 VariableContext (net.runelite.asm.execution.VariableContext)13 Instruction (net.runelite.asm.attributes.code.Instruction)12 GetFieldInstruction (net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)12 Instructions (net.runelite.asm.attributes.code.Instructions)8 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)8 LVTInstruction (net.runelite.asm.attributes.code.instruction.types.LVTInstruction)7 Execution (net.runelite.asm.execution.Execution)7 Frame (net.runelite.asm.execution.Frame)7 DupInstruction (net.runelite.asm.attributes.code.instruction.types.DupInstruction)6 InvokeInstruction (net.runelite.asm.attributes.code.instruction.types.InvokeInstruction)6 Method (net.runelite.asm.pool.Method)5 ClassFile (net.runelite.asm.ClassFile)4 Method (net.runelite.asm.Method)4 Type (net.runelite.asm.Type)4