Search in sources :

Example 6 with LVTInstruction

use of net.runelite.asm.attributes.code.instruction.types.LVTInstruction 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 7 with LVTInstruction

use of net.runelite.asm.attributes.code.instruction.types.LVTInstruction 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 8 with LVTInstruction

use of net.runelite.asm.attributes.code.instruction.types.LVTInstruction in project runelite by runelite.

the class ExprArgOrder method hash.

private static void hash(Method method, MessageDigest sha256, InstructionContext ic) {
    Instruction i = ic.getInstruction();
    // this relies on all push constants are converted to ldc..
    sha256.update((byte) i.getType().getCode());
    if (i instanceof PushConstantInstruction) {
        PushConstantInstruction pci = (PushConstantInstruction) i;
        Object constant = pci.getConstant();
        if (constant instanceof Number) {
            long l = ((Number) constant).longValue();
            sha256.update(Longs.toByteArray(l));
        }
    } else if (i instanceof LVTInstruction) {
        int idx = ((LVTInstruction) i).getVariableIndex();
        Signature signature = method.getDescriptor();
        int lvt = method.isStatic() ? 0 : 1;
        for (Type type : signature.getArguments()) {
            if (idx == lvt) {
                // Accessing a method parameter
                sha256.update(Ints.toByteArray(idx));
                break;
            }
            lvt += type.getSize();
        }
    }
    for (StackContext sctx : ic.getPops()) {
        hash(method, sha256, sctx.getPushed());
    }
}
Also used : InstructionType(net.runelite.asm.attributes.code.InstructionType) Type(net.runelite.asm.Type) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) StackContext(net.runelite.asm.execution.StackContext) Signature(net.runelite.asm.signature.Signature) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) 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)

Example 9 with LVTInstruction

use of net.runelite.asm.attributes.code.instruction.types.LVTInstruction 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 10 with LVTInstruction

use of net.runelite.asm.attributes.code.instruction.types.LVTInstruction in project runelite by runelite.

the class Lvt method process.

private void process(Method method) {
    Code code = method.getCode();
    if (code == null) {
        return;
    }
    Mappings mappings = new Mappings(code.getMaxLocals());
    for (Instruction ins : code.getInstructions().getInstructions()) {
        if (!(ins instanceof LVTInstruction)) {
            continue;
        }
        LVTInstruction lv = (LVTInstruction) ins;
        Integer newIdx = mappings.remap(lv.getVariableIndex(), lv.type());
        if (newIdx == null) {
            continue;
        }
        assert newIdx != lv.getVariableIndex();
        Instruction newIns = lv.setVariableIndex(newIdx);
        assert ins == newIns;
        ++count;
    }
}
Also used : Mappings(net.runelite.deob.deobfuscators.lvt.Mappings) Instruction(net.runelite.asm.attributes.code.Instruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) Code(net.runelite.asm.attributes.Code)

Aggregations

LVTInstruction (net.runelite.asm.attributes.code.instruction.types.LVTInstruction)16 Instruction (net.runelite.asm.attributes.code.Instruction)11 InvokeInstruction (net.runelite.asm.attributes.code.instruction.types.InvokeInstruction)6 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)6 InstructionContext (net.runelite.asm.execution.InstructionContext)6 StackContext (net.runelite.asm.execution.StackContext)6 ArrayList (java.util.ArrayList)5 Signature (net.runelite.asm.signature.Signature)5 Method (net.runelite.asm.Method)4 InstructionType (net.runelite.asm.attributes.code.InstructionType)4 SetFieldInstruction (net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction)4 Collections (java.util.Collections)3 List (java.util.List)3 ClassFile (net.runelite.asm.ClassFile)3 ClassGroup (net.runelite.asm.ClassGroup)3 Type (net.runelite.asm.Type)3 DupInstruction (net.runelite.asm.attributes.code.instruction.types.DupInstruction)3 If (net.runelite.asm.attributes.code.instructions.If)3 HashMultimap (com.google.common.collect.HashMultimap)2 Multimap (com.google.common.collect.Multimap)2