Search in sources :

Example 66 with Instructions

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

the class ModArith method guess.

private void guess() {
    for (ClassFile cf : group.getClasses()) {
        for (Field f : cf.getFields()) {
            FieldInfo fieldInfo = getFieldInfo(f);
            // all constants in instructions associated with the field
            Collection<AssociatedConstant> col = fieldInfo.constants;
            if (col.isEmpty()) {
                continue;
            }
            Type type = f.getType();
            assert type.equals(Type.INT) || type.equals(Type.LONG);
            Class typeOfField = type.equals(Type.INT) ? Integer.class : Long.class;
            // filter collect constants of the correct type
            Collection<AssociatedConstant> col2 = col.stream().filter(i -> i.value.getClass() == typeOfField).collect(Collectors.toList());
            // filer out ones that have another field in the expression
            List<Number> noOther = col2.stream().filter(i -> !i.other && !i.constant).map(i -> i.value).distinct().collect(Collectors.toList());
            List<Number> other = col2.stream().filter(i -> i.other || i.constant).map(i -> i.value).collect(Collectors.toList());
            other.addAll(noOther);
            other = ImmutableSet.copyOf(other).asList();
            // guess with constants not associated with other fields
            Pair p = this.guess(f, noOther);
            if (p == null) {
                // fall back to all constants
                p = this.guess(f, other);
            }
            // check that this guess doesn't increase constants
            if (p != null && !fieldInfo.guessDecreasesConstants(p)) {
                continue;
            }
            if (p != null) {
                pairs.add(p);
            }
        }
    }
}
Also used : 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) IMul(net.runelite.asm.attributes.code.instructions.IMul) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) Code(net.runelite.asm.attributes.Code) ArrayList(java.util.ArrayList) ClassGroup(net.runelite.asm.ClassGroup) StackContext(net.runelite.asm.execution.StackContext) HashSet(java.util.HashSet) ArrayStoreInstruction(net.runelite.asm.attributes.code.instruction.types.ArrayStoreInstruction) DMath.modInverse(net.runelite.deob.deobfuscators.arithmetic.DMath.modInverse) Method(net.runelite.asm.Method) Map(java.util.Map) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) If(net.runelite.asm.attributes.code.instructions.If) LAdd(net.runelite.asm.attributes.code.instructions.LAdd) ISub(net.runelite.asm.attributes.code.instructions.ISub) ArrayLoad(net.runelite.asm.attributes.code.instruction.types.ArrayLoad) ImmutableSet(com.google.common.collect.ImmutableSet) DeobAnnotations(net.runelite.deob.DeobAnnotations) Logger(org.slf4j.Logger) Collection(java.util.Collection) LCmp(net.runelite.asm.attributes.code.instructions.LCmp) Field(net.runelite.asm.Field) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) Set(java.util.Set) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction) DMath.multiply(net.runelite.deob.deobfuscators.arithmetic.DMath.multiply) Type(net.runelite.asm.Type) Deobfuscator(net.runelite.deob.Deobfuscator) Collectors(java.util.stream.Collectors) InstructionContext(net.runelite.asm.execution.InstructionContext) Execution(net.runelite.asm.execution.Execution) List(java.util.List) ClassFile(net.runelite.asm.ClassFile) LDC(net.runelite.asm.attributes.code.instructions.LDC) MethodContext(net.runelite.asm.execution.MethodContext) Instructions(net.runelite.asm.attributes.code.Instructions) LMul(net.runelite.asm.attributes.code.instructions.LMul) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) Instruction(net.runelite.asm.attributes.code.Instruction) If0(net.runelite.asm.attributes.code.instructions.If0) LSub(net.runelite.asm.attributes.code.instructions.LSub) IShR(net.runelite.asm.attributes.code.instructions.IShR) Field(net.runelite.asm.Field) Type(net.runelite.asm.Type) ClassFile(net.runelite.asm.ClassFile)

Example 67 with Instructions

use of net.runelite.asm.attributes.code.Instructions 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 68 with Instructions

use of net.runelite.asm.attributes.code.Instructions 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)

Example 69 with Instructions

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

the class MultiplyZeroDeobfuscator method visit.

private void visit(MethodContext mctx) {
    for (InstructionContext ictx : mctx.getInstructionContexts()) {
        Instruction instruction = ictx.getInstruction();
        Instructions ins = instruction.getInstructions();
        if (ins == null) {
            continue;
        }
        if (!(instruction instanceof IMul) && !(instruction instanceof LMul)) {
            continue;
        }
        List<Instruction> ilist = ins.getInstructions();
        StackContext one = ictx.getPops().get(0);
        StackContext two = ictx.getPops().get(1);
        Instruction ione = one.getPushed().getInstruction(), itwo = two.getPushed().getInstruction();
        boolean remove = false;
        if (ione instanceof PushConstantInstruction) {
            PushConstantInstruction pci = (PushConstantInstruction) ione;
            Number value = (Number) pci.getConstant();
            if (DMath.equals(value, 0)) {
                remove = true;
            }
        }
        if (itwo instanceof PushConstantInstruction) {
            PushConstantInstruction pci = (PushConstantInstruction) itwo;
            Number value = (Number) pci.getConstant();
            if (DMath.equals(value, 0)) {
                remove = true;
            }
        }
        if (remove == false) {
            continue;
        }
        if (!ilist.contains(instruction)) {
            // already done
            continue;
        }
        if (!MultiplicationDeobfuscator.isOnlyPath(ictx, null)) {
            continue;
        }
        // remove both, remove imul, push 0
        ictx.removeStack(1);
        ictx.removeStack(0);
        if (instruction instanceof IMul) {
            ins.replace(instruction, new LDC(ins, 0));
        } else if (instruction instanceof LMul) {
            ins.replace(instruction, new LDC(ins, 0L));
        } else {
            throw new IllegalStateException();
        }
        ++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) LDC(net.runelite.asm.attributes.code.instructions.LDC) 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 70 with Instructions

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

the class ConstantParameter method removeDeadOperations.

// remove logically dead comparisons
private int removeDeadOperations(MethodContext mctx) {
    int count = 0;
    for (ConstantMethodParameter cmp : parameters.values()) {
        if (cmp.invalid) {
            continue;
        }
        if (!cmp.methods.contains(mctx.getMethod())) {
            continue;
        }
        // only annotate garbage value of last param
        if (cmp.paramIndex + 1 == mctx.getMethod().getDescriptor().size()) {
            annotateObfuscatedSignature(cmp);
        }
        for (// comparisons
        Instruction ins : // comparisons
        cmp.operations) {
            if (ins.getInstructions() == null || ins.getInstructions().getCode().getMethod() != mctx.getMethod()) {
                continue;
            }
            InstructionContext ctx = mctx.getInstructonContexts(ins).toArray(new InstructionContext[0])[0];
            // branch that is always taken
            boolean branch = cmp.result;
            if (ins.getInstructions() == null) {
                // ins already removed?
                continue;
            }
            Instructions instructions = ins.getInstructions();
            // remove the if
            if (ctx.getInstruction() instanceof If) {
                ctx.removeStack(1);
            }
            ctx.removeStack(0);
            int idx = instructions.getInstructions().indexOf(ins);
            if (idx == -1) {
                // already removed?
                continue;
            }
            ++count;
            Instruction to;
            if (branch) {
                JumpingInstruction jumpIns = (JumpingInstruction) ins;
                assert jumpIns.getJumps().size() == 1;
                to = jumpIns.getJumps().get(0);
            } else {
                // just go to next instruction
                to = instructions.getInstructions().get(idx + 1);
            }
            assert to.getInstructions() == instructions;
            assert ins != to;
            assert instructions.getInstructions().contains(to);
            instructions.remove(ins);
            assert instructions.getInstructions().contains(to);
            if (branch) {
                Goto gotoins = new Goto(instructions, instructions.createLabelFor(to));
                // insert goto
                instructions.getInstructions().add(idx, gotoins);
            }
        }
    }
    return count;
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) JumpingInstruction(net.runelite.asm.attributes.code.instruction.types.JumpingInstruction) Goto(net.runelite.asm.attributes.code.instructions.Goto) Instructions(net.runelite.asm.attributes.code.Instructions) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) JumpingInstruction(net.runelite.asm.attributes.code.instruction.types.JumpingInstruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) ComparisonInstruction(net.runelite.asm.attributes.code.instruction.types.ComparisonInstruction) Instruction(net.runelite.asm.attributes.code.Instruction) If(net.runelite.asm.attributes.code.instructions.If)

Aggregations

Instructions (net.runelite.asm.attributes.code.Instructions)86 Instruction (net.runelite.asm.attributes.code.Instruction)72 Code (net.runelite.asm.attributes.Code)47 LDC (net.runelite.asm.attributes.code.instructions.LDC)40 ClassGroup (net.runelite.asm.ClassGroup)32 VReturn (net.runelite.asm.attributes.code.instructions.VReturn)30 Test (org.junit.Test)30 Method (net.runelite.asm.Method)26 IMul (net.runelite.asm.attributes.code.instructions.IMul)26 ILoad (net.runelite.asm.attributes.code.instructions.ILoad)24 IStore (net.runelite.asm.attributes.code.instructions.IStore)24 Execution (net.runelite.asm.execution.Execution)22 Deobfuscator (net.runelite.deob.Deobfuscator)22 ClassFile (net.runelite.asm.ClassFile)17 Field (net.runelite.asm.Field)17 Type (net.runelite.asm.Type)17 Label (net.runelite.asm.attributes.code.Label)17 PushConstantInstruction (net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction)16 Signature (net.runelite.asm.signature.Signature)16 Pop (net.runelite.asm.attributes.code.instructions.Pop)14