Search in sources :

Example 21 with ILoad

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

the class ExprArgOrderTest method test.

@Test
public void test() {
    ClassGroup group = ClassGroupFactory.generateGroup();
    Code code = group.findClass("test").findMethod("func").getCode();
    Instructions ins = code.getInstructions();
    code.setMaxStack(2);
    // vars[0] = 3
    Instruction[] prepareVariables = { new LDC(ins, 3), new IStore(ins, 0) };
    for (Instruction i : prepareVariables) {
        ins.addInstruction(i);
    }
    Instruction[] body = { // 2
    new LDC(ins, 3), new ILoad(ins, 0), new IAdd(ins), new Pop(ins), new VReturn(ins) };
    for (Instruction i : body) {
        ins.addInstruction(i);
    }
    ExprArgOrder exprArgOrder = new ExprArgOrder();
    exprArgOrder.run(group);
    List<Instruction> instructions = ins.getInstructions();
    assertEquals(ILOAD, instructions.get(2).getType());
    assertEquals(LDC, instructions.get(3).getType());
    assertEquals(IADD, instructions.get(4).getType());
}
Also used : IStore(net.runelite.asm.attributes.code.instructions.IStore) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.InstructionType.LDC) LDC(net.runelite.asm.attributes.code.instructions.LDC) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) VReturn(net.runelite.asm.attributes.code.instructions.VReturn) Pop(net.runelite.asm.attributes.code.instructions.Pop) ClassGroup(net.runelite.asm.ClassGroup) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) Test(org.junit.Test)

Example 22 with ILoad

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

the class MixinInjector method setOwnersToTargetClass.

private void setOwnersToTargetClass(ClassFile mixinCf, ClassFile cf, Method method, Map<net.runelite.asm.pool.Field, Field> shadowFields, Map<net.runelite.asm.pool.Method, CopiedMethod> copiedMethods) throws InjectionException {
    ListIterator<Instruction> iterator = method.getCode().getInstructions().getInstructions().listIterator();
    while (iterator.hasNext()) {
        Instruction i = iterator.next();
        if (i instanceof InvokeInstruction) {
            InvokeInstruction ii = (InvokeInstruction) i;
            CopiedMethod copiedMethod = copiedMethods.get(ii.getMethod());
            if (copiedMethod != null) {
                ii.setMethod(copiedMethod.obMethod.getPoolMethod());
                // Pass through garbage value if the method has one
                if (copiedMethod.hasGarbageValue) {
                    int garbageIndex = copiedMethod.obMethod.isStatic() ? copiedMethod.obMethod.getDescriptor().size() - 1 : copiedMethod.obMethod.getDescriptor().size();
                    iterator.previous();
                    iterator.add(new ILoad(method.getCode().getInstructions(), garbageIndex));
                    iterator.next();
                }
            } else if (ii.getMethod().getClazz().getName().equals(mixinCf.getName())) {
                ii.setMethod(new net.runelite.asm.pool.Method(new net.runelite.asm.pool.Class(cf.getName()), ii.getMethod().getName(), ii.getMethod().getType()));
            }
        } else if (i instanceof FieldInstruction) {
            FieldInstruction fi = (FieldInstruction) i;
            Field shadowed = shadowFields.get(fi.getField());
            if (shadowed != null) {
                fi.setField(shadowed.getPoolField());
            } else if (fi.getField().getClazz().getName().equals(mixinCf.getName())) {
                fi.setField(new net.runelite.asm.pool.Field(new net.runelite.asm.pool.Class(cf.getName()), fi.getField().getName(), fi.getField().getType()));
            }
        } else if (i instanceof PushConstantInstruction) {
            PushConstantInstruction pi = (PushConstantInstruction) i;
            if (mixinCf.getPoolClass().equals(pi.getConstant())) {
                pi.setConstant(cf.getPoolClass());
            }
        }
        verify(mixinCf, i);
    }
}
Also used : PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) Method(net.runelite.asm.Method) FieldInstruction(net.runelite.asm.attributes.code.instruction.types.FieldInstruction) 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) ReturnInstruction(net.runelite.asm.attributes.code.instruction.types.ReturnInstruction) Instruction(net.runelite.asm.attributes.code.Instruction) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) GetField(net.runelite.asm.attributes.code.instructions.GetField) Field(net.runelite.asm.Field) PutField(net.runelite.asm.attributes.code.instructions.PutField) FieldInstruction(net.runelite.asm.attributes.code.instruction.types.FieldInstruction)

Example 23 with ILoad

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

the class ScriptVM method injectScriptVMHooks.

private void injectScriptVMHooks() throws InjectionException {
    /*
			This hooks local variable assignments in the copied version of runScript:
			 - The currently executing script > client.currentScript
			 - The currently executing script's program counter > client.currentScriptPC
			 - The currently executing opcode > client.vmExecuteOpcode(I)Z

			The currently executing script variable is located as the outermost Script local

			The PC is located by its use in PutField ScriptState::invokedFromPC

			The currently executing opcode is found by searching for iaload with the script's instruction array

			The script's instruction array is identified by looking for the getfield from script.instructions

			bn.g @ rev 163 :
			// Jump back to here if vmExecuteOpcode returns true
			aload6 // Script.instructions
			iinc 5 1 // ++PC
			iload5 // PC
			iaload
			istore8
			// <- Inject here
			iload8
			bipush 100
			if_icmpge L52

		 */
    String scriptObName = DeobAnnotations.getObfuscatedName(inject.getDeobfuscated().findClass("Script").getAnnotations());
    Method runScript = findObMethod("copy$runScript");
    Method vmExecuteOpcode = findObMethod("vmExecuteOpcode");
    Field scriptInstructions = findDeobField("instructions");
    Field scriptStatePC = findDeobField("invokedFromPc");
    Field currentScriptField = findObField("currentScript");
    Field currentScriptPCField = findObField("currentScriptPC");
    Execution e = new Execution(inject.getVanilla());
    e.addMethod(runScript);
    e.noInvoke = true;
    AtomicReference<MethodContext> pcontext = new AtomicReference<>(null);
    e.addMethodContextVisitor(pcontext::set);
    e.run();
    Instructions instrs = runScript.getCode().getInstructions();
    Set<AStore> scriptStores = new HashSet<>();
    Integer pcLocalVar = null;
    Integer instructionArrayLocalVar = null;
    IStore currentOpcodeStore = null;
    ALoad localInstructionLoad = null;
    MethodContext methodContext = pcontext.get();
    for (InstructionContext instrCtx : methodContext.getInstructionContexts()) {
        Instruction instr = instrCtx.getInstruction();
        if (instr instanceof AStore) {
            AStore store = (AStore) instr;
            StackContext storedVarCtx = instrCtx.getPops().get(0);
            // Find AStores that store a Script
            if (storedVarCtx.getType().getInternalName().equals(scriptObName)) {
                scriptStores.add(store);
            }
            // Find AStores that store the instructions
            InstructionContext pusherCtx = storedVarCtx.getPushed();
            if (pusherCtx.getInstruction() instanceof GetField) {
                GetField getField = (GetField) pusherCtx.getInstruction();
                if (getField.getMyField().equals(scriptInstructions)) {
                    instructionArrayLocalVar = store.getVariableIndex();
                }
            }
        }
        // Find the local that invokedFromPc is set from
        if (instr instanceof PutField) {
            PutField put = (PutField) instr;
            if (put.getMyField() == scriptStatePC) {
                StackContext pc = instrCtx.getPops().get(0);
                assert Type.INT.equals(pc.getType()) : pc.getType();
                InstructionContext mulctx = pc.pushed;
                assert mulctx.getInstruction() instanceof IMul;
                pcLocalVar = mulctx.getPops().stream().map(StackContext::getPushed).filter(i -> i.getInstruction() instanceof ILoad).map(i -> ((ILoad) i.getInstruction()).getVariableIndex()).findFirst().orElse(null);
            }
        }
    }
    // This has to run after the first loop because it relies on instructionArrayLocalVar being set
    if (instructionArrayLocalVar == null) {
        throw new InjectionException("Unable to find local instruction array");
    }
    for (InstructionContext instrCtx : methodContext.getInstructionContexts()) {
        Instruction instr = instrCtx.getInstruction();
        if (instr instanceof IALoad) {
            StackContext array = instrCtx.getPops().get(1);
            // Check where the array came from (looking for a getField scriptInstructions
            InstructionContext pushedCtx = array.getPushed();
            Instruction pushed = pushedCtx.getInstruction();
            if (pushed instanceof ALoad) {
                ALoad arrayLoad = (ALoad) pushed;
                if (arrayLoad.getVariableIndex() == instructionArrayLocalVar) {
                    // Find the istore
                    IStore istore = (IStore) instrCtx.getPushes().get(0).getPopped().stream().map(InstructionContext::getInstruction).filter(i -> i instanceof IStore).findFirst().orElse(null);
                    if (istore != null) {
                        currentOpcodeStore = istore;
                        localInstructionLoad = arrayLoad;
                    }
                }
            }
        }
    }
    // Add PutStatics to all Script AStores
    {
        int outerSciptIdx = scriptStores.stream().mapToInt(AStore::getVariableIndex).reduce(Math::min).orElseThrow(() -> new InjectionException("Unable to find any Script AStores in runScript"));
        log.debug("Found script index {}", outerSciptIdx);
        ListIterator<Instruction> instrIter = instrs.getInstructions().listIterator();
        while (instrIter.hasNext()) {
            Instruction instr = instrIter.next();
            if (instr instanceof AStore) {
                AStore il = (AStore) instr;
                if (il.getVariableIndex() == outerSciptIdx) {
                    instrIter.previous();
                    instrIter.add(new Dup(instrs));
                    instrIter.add(new PutStatic(instrs, currentScriptField));
                    instrIter.next();
                }
            }
        }
    }
    // Add PutStatics to all PC IStores and IIncs
    {
        if (pcLocalVar == null) {
            throw new InjectionException("Unable to find ILoad for invokedFromPc IStore");
        }
        log.debug("Found pc index {}", pcLocalVar);
        ListIterator<Instruction> instrIter = instrs.getInstructions().listIterator();
        while (instrIter.hasNext()) {
            Instruction instr = instrIter.next();
            if (instr instanceof IStore) {
                IStore il = (IStore) instr;
                if (il.getVariableIndex() == pcLocalVar) {
                    instrIter.previous();
                    instrIter.add(new Dup(instrs));
                    instrIter.add(new PutStatic(instrs, currentScriptPCField));
                    instrIter.next();
                }
            }
            if (instr instanceof IInc) {
                IInc iinc = (IInc) instr;
                if (iinc.getVariableIndex() == pcLocalVar) {
                    instrIter.add(new ILoad(instrs, pcLocalVar));
                    instrIter.add(new PutStatic(instrs, currentScriptPCField));
                }
            }
        }
    }
    // Inject call to vmExecuteOpcode
    log.debug("Found instruction array index {}", instructionArrayLocalVar);
    if (currentOpcodeStore == null) {
        throw new InjectionException("Unable to find IStore for current opcode");
    }
    int istorepc = instrs.getInstructions().indexOf(currentOpcodeStore);
    assert istorepc >= 0;
    Label nextIteration = instrs.createLabelFor(localInstructionLoad);
    instrs.addInstruction(istorepc + 1, new ILoad(instrs, currentOpcodeStore.getVariableIndex()));
    instrs.addInstruction(istorepc + 2, new InvokeStatic(instrs, vmExecuteOpcode.getPoolMethod()));
    instrs.addInstruction(istorepc + 3, new IfNe(instrs, nextIteration));
}
Also used : ListIterator(java.util.ListIterator) GetField(net.runelite.asm.attributes.code.instructions.GetField) IMul(net.runelite.asm.attributes.code.instructions.IMul) LoggerFactory(org.slf4j.LoggerFactory) Dup(net.runelite.asm.attributes.code.instructions.Dup) PutStatic(net.runelite.asm.attributes.code.instructions.PutStatic) ALoad(net.runelite.asm.attributes.code.instructions.ALoad) Inject(net.runelite.injector.Inject) AtomicReference(java.util.concurrent.atomic.AtomicReference) StackContext(net.runelite.asm.execution.StackContext) HashSet(java.util.HashSet) Method(net.runelite.asm.Method) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) IStore(net.runelite.asm.attributes.code.instructions.IStore) IALoad(net.runelite.asm.attributes.code.instructions.IALoad) DeobAnnotations(net.runelite.deob.DeobAnnotations) Logger(org.slf4j.Logger) AStore(net.runelite.asm.attributes.code.instructions.AStore) Field(net.runelite.asm.Field) Set(java.util.Set) Type(net.runelite.asm.Type) InstructionContext(net.runelite.asm.execution.InstructionContext) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic) PutField(net.runelite.asm.attributes.code.instructions.PutField) Execution(net.runelite.asm.execution.Execution) ClassFile(net.runelite.asm.ClassFile) Label(net.runelite.asm.attributes.code.Label) MethodContext(net.runelite.asm.execution.MethodContext) Instructions(net.runelite.asm.attributes.code.Instructions) IInc(net.runelite.asm.attributes.code.instructions.IInc) InjectionException(net.runelite.injector.InjectionException) Instruction(net.runelite.asm.attributes.code.Instruction) IfNe(net.runelite.asm.attributes.code.instructions.IfNe) IStore(net.runelite.asm.attributes.code.instructions.IStore) Label(net.runelite.asm.attributes.code.Label) Instruction(net.runelite.asm.attributes.code.Instruction) InjectionException(net.runelite.injector.InjectionException) GetField(net.runelite.asm.attributes.code.instructions.GetField) Field(net.runelite.asm.Field) PutField(net.runelite.asm.attributes.code.instructions.PutField) Execution(net.runelite.asm.execution.Execution) AStore(net.runelite.asm.attributes.code.instructions.AStore) IALoad(net.runelite.asm.attributes.code.instructions.IALoad) IMul(net.runelite.asm.attributes.code.instructions.IMul) Dup(net.runelite.asm.attributes.code.instructions.Dup) HashSet(java.util.HashSet) PutField(net.runelite.asm.attributes.code.instructions.PutField) InstructionContext(net.runelite.asm.execution.InstructionContext) GetField(net.runelite.asm.attributes.code.instructions.GetField) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) MethodContext(net.runelite.asm.execution.MethodContext) AtomicReference(java.util.concurrent.atomic.AtomicReference) Instructions(net.runelite.asm.attributes.code.Instructions) Method(net.runelite.asm.Method) ListIterator(java.util.ListIterator) PutStatic(net.runelite.asm.attributes.code.instructions.PutStatic) StackContext(net.runelite.asm.execution.StackContext) IfNe(net.runelite.asm.attributes.code.instructions.IfNe) IInc(net.runelite.asm.attributes.code.instructions.IInc) ALoad(net.runelite.asm.attributes.code.instructions.ALoad) IALoad(net.runelite.asm.attributes.code.instructions.IALoad) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic)

Aggregations

Instruction (net.runelite.asm.attributes.code.Instruction)23 ILoad (net.runelite.asm.attributes.code.instructions.ILoad)23 Instructions (net.runelite.asm.attributes.code.Instructions)22 IStore (net.runelite.asm.attributes.code.instructions.IStore)21 LDC (net.runelite.asm.attributes.code.instructions.LDC)21 ClassGroup (net.runelite.asm.ClassGroup)20 Code (net.runelite.asm.attributes.Code)20 VReturn (net.runelite.asm.attributes.code.instructions.VReturn)20 Test (org.junit.Test)20 IMul (net.runelite.asm.attributes.code.instructions.IMul)16 Execution (net.runelite.asm.execution.Execution)15 Deobfuscator (net.runelite.deob.Deobfuscator)14 Label (net.runelite.asm.attributes.code.Label)9 IAdd (net.runelite.asm.attributes.code.instructions.IAdd)9 Pop (net.runelite.asm.attributes.code.instructions.Pop)9 LDC (net.runelite.asm.attributes.code.InstructionType.LDC)6 Dup_X1 (net.runelite.asm.attributes.code.instructions.Dup_X1)5 IfEq (net.runelite.asm.attributes.code.instructions.IfEq)5 SiPush (net.runelite.asm.attributes.code.instructions.SiPush)4 Field (net.runelite.asm.Field)3