Search in sources :

Example 81 with Instruction

use of net.runelite.asm.attributes.code.Instruction in project runelite by runelite.

the class RuneliteBufferTransformer method injectPacketFinish.

private void injectPacketFinish(ClassGroup group) {
    PacketFlushFinder pff = new PacketFlushFinder(group);
    pff.find();
    for (InstructionContext queueForWriteCtx : pff.getQueueForWrite()) {
        Instruction before = // socket
        queueForWriteCtx.getPops().get(3).getPushed().getInstruction();
        GetStatic getBuffer;
        try {
            getBuffer = (GetStatic) // buffer
            queueForWriteCtx.getPops().get(2).getPushed().getPops().get(// getstatic
            0).getPushed().getInstruction();
        } catch (ClassCastException ex) {
            continue;
        }
        Instructions instructions = before.getInstructions();
        int idx = instructions.getInstructions().indexOf(before);
        assert idx != -1;
        instructions.addInstruction(idx++, getBuffer.clone());
        net.runelite.asm.pool.Method method = new net.runelite.asm.pool.Method(new net.runelite.asm.pool.Class(getBuffer.getField().getType().getInternalName()), RUNELITE_FINISH_PACKET, new Signature("()V"));
        instructions.addInstruction(idx++, new InvokeVirtual(instructions, method));
    }
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) PacketFlushFinder(net.runelite.deob.deobfuscators.transformers.buffer.PacketFlushFinder) Instructions(net.runelite.asm.attributes.code.Instructions) Method(net.runelite.asm.Method) Instruction(net.runelite.asm.attributes.code.Instruction) GetStatic(net.runelite.asm.attributes.code.instructions.GetStatic) InvokeVirtual(net.runelite.asm.attributes.code.instructions.InvokeVirtual) Signature(net.runelite.asm.signature.Signature)

Example 82 with Instruction

use of net.runelite.asm.attributes.code.Instruction in project runelite by runelite.

the class PacketFlushFinder method find.

private void find(Method method) {
    Code code = method.getCode();
    Set<Instruction> checked = new HashSet<>();
    Execution e = new Execution(group);
    e.addMethod(method);
    e.noInvoke = true;
    e.noExceptions = true;
    e.addExecutionVisitor(ic -> {
        Instruction i = ic.getInstruction();
        if (checked.contains(i)) {
            return;
        }
        checked.add(i);
        if (i.getType() != INVOKEVIRTUAL) {
            return;
        }
        InvokeVirtual iv = (InvokeVirtual) i;
        // queueForWrite
        if (!iv.getMethod().getType().equals(new Signature("([BII)V"))) {
            return;
        }
        InstructionContext lengthCtx = ic.getPops().get(0).getPushed();
        if (lengthCtx.getInstruction().getType() != GETFIELD) {
            return;
        }
        queueForWrite.add(ic);
    });
    e.run();
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) Execution(net.runelite.asm.execution.Execution) InvokeVirtual(net.runelite.asm.attributes.code.instructions.InvokeVirtual) Signature(net.runelite.asm.signature.Signature) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) HashSet(java.util.HashSet)

Example 83 with Instruction

use of net.runelite.asm.attributes.code.Instruction in project runelite by runelite.

the class ModArith method findUses.

// find potential getters/setters for each field
private void findUses(MethodContext mctx) {
    for (InstructionContext ctx : mctx.getInstructionContexts()) {
        if (ctx.getInstruction() instanceof IMul || ctx.getInstruction() instanceof LMul) {
            Instruction one = ctx.getPops().get(0).getPushed().getInstruction();
            Instruction two = ctx.getPops().get(1).getPushed().getInstruction();
            PushConstantInstruction pc = null;
            GetFieldInstruction gf = null;
            if (one instanceof PushConstantInstruction && two instanceof GetFieldInstruction) {
                pc = (PushConstantInstruction) one;
                gf = (GetFieldInstruction) two;
            } else if (two instanceof PushConstantInstruction && one instanceof GetFieldInstruction) {
                pc = (PushConstantInstruction) two;
                gf = (GetFieldInstruction) one;
            }
            if (pc == null) {
                continue;
            }
            Field field = gf.getMyField();
            if (field == null) {
                continue;
            }
            FieldInfo fieldInfo = getFieldInfo(field);
            // parse the full multiplication expression to
            // get all associated constants
            List<InstructionContext> insInExpr = getInsInExpr(ctx, new HashSet(), true);
            for (InstructionContext ctx2 : insInExpr) {
                if (!(ctx2.getInstruction() instanceof PushConstantInstruction)) {
                    continue;
                }
                PushConstantInstruction pci3 = (PushConstantInstruction) ctx2.getInstruction();
                Number value = (Number) pci3.getConstant();
                // field * constant
                if (value instanceof Integer || value instanceof Long) {
                    fieldInfo.getters.add(value);
                }
            }
        } else if (ctx.getInstruction() instanceof SetFieldInstruction) {
            SetFieldInstruction sf = (SetFieldInstruction) ctx.getInstruction();
            Field field = sf.getMyField();
            if (field == null) {
                continue;
            }
            FieldInfo fieldInfo = getFieldInfo(field);
            // value being set
            InstructionContext pushedsfi = ctx.getPops().get(0).getPushed();
            pushedsfi = pushedsfi.resolve(ctx.getPops().get(0));
            if (!(pushedsfi.getInstruction() instanceof IMul) && !(pushedsfi.getInstruction() instanceof LMul) && !(pushedsfi.getInstruction() instanceof IAdd) && !(pushedsfi.getInstruction() instanceof LAdd) && !(pushedsfi.getInstruction() instanceof ISub) && !(pushedsfi.getInstruction() instanceof LSub)) {
                if (pushedsfi.getInstruction() instanceof LDC) {
                    PushConstantInstruction ldc = (PushConstantInstruction) pushedsfi.getInstruction();
                    if (ldc.getConstant() instanceof Integer || ldc.getConstant() instanceof Long) {
                        Number i = (Number) ldc.getConstant();
                        // field = constant
                        fieldInfo.setters.add(i);
                    }
                }
                continue;
            }
            Instruction one = pushedsfi.getPops().get(0).getPushed().getInstruction();
            Instruction two = pushedsfi.getPops().get(1).getPushed().getInstruction();
            // field = field + imul
            if (pushedsfi.getInstruction() instanceof IAdd) {
                if (one instanceof IMul && two instanceof GetFieldInstruction) {
                    one = pushedsfi.getPops().get(0).getPushed().getPops().get(0).getPushed().getInstruction();
                    two = pushedsfi.getPops().get(0).getPushed().getPops().get(1).getPushed().getInstruction();
                }
            }
            // if both one and two are constants then one of them must not be a setter
            PushConstantInstruction pc = null;
            if (one instanceof PushConstantInstruction && !(two instanceof PushConstantInstruction)) {
                pc = (PushConstantInstruction) one;
            } else if (two instanceof PushConstantInstruction && !(one instanceof PushConstantInstruction)) {
                pc = (PushConstantInstruction) two;
            }
            if (pc == null) {
                continue;
            }
            Number value2 = (Number) pc.getConstant();
            // field = something * constant
            if (value2 instanceof Integer || value2 instanceof Long) {
                fieldInfo.setters.add(value2);
            }
        }
    }
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) LDC(net.runelite.asm.attributes.code.instructions.LDC) DivisionInstruction(net.runelite.asm.attributes.code.instruction.types.DivisionInstruction) FieldInstruction(net.runelite.asm.attributes.code.instruction.types.FieldInstruction) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) ArrayStoreInstruction(net.runelite.asm.attributes.code.instruction.types.ArrayStoreInstruction) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction) Instruction(net.runelite.asm.attributes.code.Instruction) Field(net.runelite.asm.Field) ISub(net.runelite.asm.attributes.code.instructions.ISub) LAdd(net.runelite.asm.attributes.code.instructions.LAdd) LSub(net.runelite.asm.attributes.code.instructions.LSub) IMul(net.runelite.asm.attributes.code.instructions.IMul) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) LMul(net.runelite.asm.attributes.code.instructions.LMul) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction) HashSet(java.util.HashSet)

Example 84 with Instruction

use of net.runelite.asm.attributes.code.Instruction in project runelite by runelite.

the class MultiplyOneDeobfuscator method visit.

private void visit(MethodContext mctx) {
    for (InstructionContext ictx : mctx.getInstructionContexts()) {
        Instruction instruction = ictx.getInstruction();
        if (!(instruction instanceof IMul) && !(instruction instanceof LMul)) {
            continue;
        }
        Instructions ins = ictx.getInstruction().getInstructions();
        if (ins == null) {
            continue;
        }
        List<Instruction> ilist = ins.getInstructions();
        if (!ilist.contains(ictx.getInstruction())) {
            // already done
            continue;
        }
        StackContext one = ictx.getPops().get(0);
        StackContext two = ictx.getPops().get(1);
        StackContext other = null;
        int removeIdx = -1;
        if (one.getPushed().getInstruction() instanceof PushConstantInstruction && DMath.equals((Number) ((PushConstantInstruction) one.getPushed().getInstruction()).getConstant(), 1)) {
            removeIdx = 0;
            other = two;
        } else if (two.getPushed().getInstruction() instanceof PushConstantInstruction && DMath.equals((Number) ((PushConstantInstruction) two.getPushed().getInstruction()).getConstant(), 1)) {
            removeIdx = 1;
            other = one;
        }
        if (removeIdx == -1) {
            continue;
        }
        if (onlyConstants && !(other.getPushed().getInstruction() instanceof PushConstantInstruction)) {
            continue;
        }
        if (!MultiplicationDeobfuscator.isOnlyPath(ictx, removeIdx == 0 ? one : two)) {
            continue;
        }
        // remove 1
        ictx.removeStack(removeIdx);
        // remove mul
        ins.remove(instruction);
        ++count;
    }
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) StackContext(net.runelite.asm.execution.StackContext) IMul(net.runelite.asm.attributes.code.instructions.IMul) Instructions(net.runelite.asm.attributes.code.Instructions) LMul(net.runelite.asm.attributes.code.instructions.LMul) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) Instruction(net.runelite.asm.attributes.code.Instruction)

Example 85 with Instruction

use of net.runelite.asm.attributes.code.Instruction in project runelite by runelite.

the class ControlFlowDeobfuscator method run.

private void run(Code code) {
    Instructions ins = code.getInstructions();
    Exceptions exceptions = code.getExceptions();
    ControlFlowGraph graph = new ControlFlowGraph.Builder().build(code);
    for (Block block : graph.getBlocks()) {
        assert block.getFlowsFrom() == null;
        assert block.getFlowsInto() == null;
    }
    if (// graph.toString() is expensive
    logger.isDebugEnabled()) {
        logger.debug(graph.toString());
    }
    List<Exception> originalExceptions = new ArrayList<>(exceptions.getExceptions());
    // Clear existing exceptions and instructions as we are going to
    // rebuild them
    exceptions.clear();
    ins.clear();
    List<Block> done = new ArrayList<>();
    Queue<Block> queue = new PriorityQueue<>(this::compareBlock);
    // add initial code block
    queue.add(graph.getHead());
    while (!queue.isEmpty()) {
        Block block = queue.remove();
        if (done.contains(block)) {
            continue;
        }
        done.add(block);
        ++placedBlocks;
        logger.debug("Placed block {}", block.getId());
        List<Block> next = block.getNext();
        if (next.isEmpty() == false) {
            // jumps are added in order their instructions are reached by ControlFlowGraph,
            // so the last jump is the goto.
            // 
            // removing this line causes the priority queue (due to implementation detail on how
            // it handles objects with equal priority) to try to optimize for block closeness
            // (how close blocks which are neighbors are to each other in bytecode).
            // I get a jump delta of ~+14k with this on 143, vs ~-47k when priotiziing optimizing
            // out jumps. I can't tell which is better.
            next.get(next.size() - 1).setJumptarget(true);
        }
        // add next reachable blocks
        for (Block bl : next) {
            queue.add(bl);
        }
        for (Instruction i : block.getInstructions()) {
            assert i.getInstructions() == null;
            // I shouldn't have to do this here
            i.setInstructions(ins);
            ins.addInstruction(i);
        }
    }
}
Also used : Exceptions(net.runelite.asm.attributes.code.Exceptions) ArrayList(java.util.ArrayList) Instructions(net.runelite.asm.attributes.code.Instructions) PriorityQueue(java.util.PriorityQueue) Instruction(net.runelite.asm.attributes.code.Instruction) Exception(net.runelite.asm.attributes.code.Exception)

Aggregations

Instruction (net.runelite.asm.attributes.code.Instruction)109 Instructions (net.runelite.asm.attributes.code.Instructions)69 Code (net.runelite.asm.attributes.Code)48 LDC (net.runelite.asm.attributes.code.instructions.LDC)39 LVTInstruction (net.runelite.asm.attributes.code.instruction.types.LVTInstruction)32 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)32 ClassGroup (net.runelite.asm.ClassGroup)31 InvokeInstruction (net.runelite.asm.attributes.code.instruction.types.InvokeInstruction)29 IMul (net.runelite.asm.attributes.code.instructions.IMul)28 VReturn (net.runelite.asm.attributes.code.instructions.VReturn)28 Test (org.junit.Test)27 ILoad (net.runelite.asm.attributes.code.instructions.ILoad)25 Method (net.runelite.asm.Method)24 IStore (net.runelite.asm.attributes.code.instructions.IStore)24 Execution (net.runelite.asm.execution.Execution)23 Deobfuscator (net.runelite.deob.Deobfuscator)22 Label (net.runelite.asm.attributes.code.Label)19 ArrayList (java.util.ArrayList)17 InstructionContext (net.runelite.asm.execution.InstructionContext)17 Field (net.runelite.asm.Field)16