Search in sources :

Example 1 with GetField

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

the class DupDeobfuscatorTest method test2.

// 035   aload_0               // this
// 036   dup                   // this this
// 037   getfield              class153/field2097 I // this I
// 038   ldc                   830083863
// 039   imul                                      // this I
// 040   ldc                   830083863
// 041   iadd                                      // this I
// 042   dup_x1                                    // I this I
@Test
public void test2() {
    ClassGroup group = ClassGroupFactory.generateGroup();
    Code code = group.findClass("test").findMethod("func").getCode();
    Instructions ins = code.getInstructions();
    code.setMaxStack(3);
    Instruction[] body = { // this
    new AConstNull(ins), // this this
    new Dup(ins), new GetField(ins, new Field(new Class("test"), "field", Type.INT)), // this this I I
    new LDC(ins, 830083863), // this this I
    new IMul(ins), new LDC(ins, 830083863), new IAdd(ins), new Dup_X1(ins), new LDC(ins, 636900519), // pops dup
    new IMul(ins), new VReturn(ins) };
    for (Instruction i : body) {
        ins.addInstruction(i);
    }
    Execution e = new Execution(group);
    e.populateInitialMethods();
    e.run();
    Deobfuscator d = new DupDeobfuscator();
    d.run(group);
    // assert the dup wasn't duplicated
    long dupCount = ins.getInstructions().stream().filter(i -> i instanceof Dup).count();
    Assert.assertEquals(1, dupCount);
    // assert the dup_x1 was removed
    dupCount = ins.getInstructions().stream().filter(i -> i instanceof Dup_X1).count();
    Assert.assertEquals(0, dupCount);
}
Also used : Pop2(net.runelite.asm.attributes.code.instructions.Pop2) AConstNull(net.runelite.asm.attributes.code.instructions.AConstNull) GetField(net.runelite.asm.attributes.code.instructions.GetField) IMul(net.runelite.asm.attributes.code.instructions.IMul) Dup(net.runelite.asm.attributes.code.instructions.Dup) Code(net.runelite.asm.attributes.Code) Test(org.junit.Test) Type(net.runelite.asm.Type) Deobfuscator(net.runelite.deob.Deobfuscator) Execution(net.runelite.asm.execution.Execution) ClassGroup(net.runelite.asm.ClassGroup) Class(net.runelite.asm.pool.Class) ClassGroupFactory(net.runelite.deob.ClassGroupFactory) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) LDC(net.runelite.asm.attributes.code.instructions.LDC) IStore(net.runelite.asm.attributes.code.instructions.IStore) VReturn(net.runelite.asm.attributes.code.instructions.VReturn) Instructions(net.runelite.asm.attributes.code.Instructions) Field(net.runelite.asm.pool.Field) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) Instruction(net.runelite.asm.attributes.code.Instruction) Assert(org.junit.Assert) Dup_X1(net.runelite.asm.attributes.code.instructions.Dup_X1) GetField(net.runelite.asm.attributes.code.instructions.GetField) Instructions(net.runelite.asm.attributes.code.Instructions) AConstNull(net.runelite.asm.attributes.code.instructions.AConstNull) 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) Deobfuscator(net.runelite.deob.Deobfuscator) GetField(net.runelite.asm.attributes.code.instructions.GetField) Field(net.runelite.asm.pool.Field) Execution(net.runelite.asm.execution.Execution) ClassGroup(net.runelite.asm.ClassGroup) Dup_X1(net.runelite.asm.attributes.code.instructions.Dup_X1) IMul(net.runelite.asm.attributes.code.instructions.IMul) Class(net.runelite.asm.pool.Class) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) Dup(net.runelite.asm.attributes.code.instructions.Dup) Test(org.junit.Test)

Example 2 with GetField

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

the class InjectGetter method injectGetter.

public void injectGetter(ClassFile clazz, java.lang.reflect.Method method, Field field, Number getter) {
    assert clazz.findMethod(method.getName()) == null;
    assert field.isStatic() || field.getClassFile() == clazz;
    Signature sig = new Signature.Builder().setReturnType(Inject.classToType(method.getReturnType())).build();
    Method getterMethod = new Method(clazz, method.getName(), sig);
    getterMethod.setAccessFlags(ACC_PUBLIC);
    // create code
    Code code = new Code(getterMethod);
    getterMethod.setCode(code);
    Instructions instructions = code.getInstructions();
    List<Instruction> ins = instructions.getInstructions();
    if (field.isStatic()) {
        code.setMaxStack(1);
        ins.add(new GetStatic(instructions, field.getPoolField()));
    } else {
        code.setMaxStack(2);
        ins.add(new ALoad(instructions, 0));
        ins.add(new GetField(instructions, field.getPoolField()));
    }
    if (getter != null) {
        code.setMaxStack(2);
        assert getter instanceof Integer || getter instanceof Long;
        if (getter instanceof Integer) {
            ins.add(new LDC(instructions, (int) getter));
            ins.add(new IMul(instructions));
        } else {
            ins.add(new LDC(instructions, (long) getter));
            ins.add(new LMul(instructions));
        }
    }
    InstructionType returnType;
    if (field.getType().isPrimitive() && field.getType().getDimensions() == 0) {
        switch(field.getType().toString()) {
            case "B":
            case "C":
            case "I":
            case "S":
            case "Z":
                returnType = InstructionType.IRETURN;
                break;
            case "D":
                returnType = InstructionType.DRETURN;
                break;
            case "F":
                returnType = InstructionType.FRETURN;
                break;
            case "J":
                returnType = InstructionType.LRETURN;
                break;
            default:
                throw new RuntimeException("Unknown type");
        }
    } else {
        returnType = InstructionType.ARETURN;
    }
    ins.add(new Return(instructions, returnType));
    clazz.addMethod(getterMethod);
    ++injectedGetters;
}
Also used : GetField(net.runelite.asm.attributes.code.instructions.GetField) Return(net.runelite.asm.attributes.code.instructions.Return) InstructionType(net.runelite.asm.attributes.code.InstructionType) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.instructions.LDC) Method(net.runelite.asm.Method) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) GetStatic(net.runelite.asm.attributes.code.instructions.GetStatic) Signature(net.runelite.asm.signature.Signature) IMul(net.runelite.asm.attributes.code.instructions.IMul) LMul(net.runelite.asm.attributes.code.instructions.LMul) ALoad(net.runelite.asm.attributes.code.instructions.ALoad)

Example 3 with GetField

use of net.runelite.asm.attributes.code.instructions.GetField 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)3 Instructions (net.runelite.asm.attributes.code.Instructions)3 GetField (net.runelite.asm.attributes.code.instructions.GetField)3 IMul (net.runelite.asm.attributes.code.instructions.IMul)3 Method (net.runelite.asm.Method)2 Type (net.runelite.asm.Type)2 Code (net.runelite.asm.attributes.Code)2 ALoad (net.runelite.asm.attributes.code.instructions.ALoad)2 Dup (net.runelite.asm.attributes.code.instructions.Dup)2 ILoad (net.runelite.asm.attributes.code.instructions.ILoad)2 IStore (net.runelite.asm.attributes.code.instructions.IStore)2 LDC (net.runelite.asm.attributes.code.instructions.LDC)2 Execution (net.runelite.asm.execution.Execution)2 HashSet (java.util.HashSet)1 ListIterator (java.util.ListIterator)1 Set (java.util.Set)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 ClassFile (net.runelite.asm.ClassFile)1 ClassGroup (net.runelite.asm.ClassGroup)1 Field (net.runelite.asm.Field)1