Search in sources :

Example 26 with Code

use of net.runelite.asm.attributes.Code in project runelite by runelite.

the class InjectHookMethodTest method testProcess.

@Test
public void testProcess() throws IOException, InjectionException {
    InputStream in = getClass().getResourceAsStream("Actor.class");
    ClassFile cf = ClassUtil.loadClass(in);
    cf.setName("Actor");
    cf.findMethod("bar").setDescriptor(new Signature("(LActor;I)I"));
    ClassGroup deobfuscated = new ClassGroup();
    deobfuscated.addClass(cf);
    in = getClass().getResourceAsStream("Obfuscated.class");
    ClassFile obcf = ClassUtil.loadClass(in);
    obcf.setName("Obfuscated");
    obcf.findMethod("foo").setDescriptor(new Signature("(LObfuscated;I)I"));
    ClassGroup obfuscated = new ClassGroup();
    obfuscated.addClass(obcf);
    Method method = cf.findMethod("bar");
    assert method != null;
    Inject inject = new Inject(deobfuscated, obfuscated);
    InjectHookMethod injectHookMethod = new InjectHookMethod(inject);
    injectHookMethod.process(method);
    method = obcf.findMethod("foo");
    assert method != null;
    Code code = method.getCode();
    List<InvokeStatic> invokeIns = code.getInstructions().getInstructions().stream().filter(i -> i instanceof InvokeStatic).map(i -> (InvokeStatic) i).filter(i -> i.getMethod().getClazz().getName().equals(HOOKS)).collect(Collectors.toList());
    assertTrue(!invokeIns.isEmpty());
    assertEquals(2, invokeIns.size());
    InvokeStatic invokeStatic = invokeIns.get(0);
    Signature signature = invokeStatic.getMethod().getType();
    // this + patamers
    assertEquals(3, signature.size());
    Type arg = signature.getTypeOfArg(1);
    assertEquals(RL_API_PACKAGE_BASE.replace('.', '/') + "Actor", arg.getInternalName());
}
Also used : ObfuscatedName(net.runelite.mapping.ObfuscatedName) HOOKS(net.runelite.injector.InjectHookMethod.HOOKS) Assert.assertTrue(org.junit.Assert.assertTrue) IOException(java.io.IOException) Code(net.runelite.asm.attributes.Code) RL_API_PACKAGE_BASE(net.runelite.injector.Inject.RL_API_PACKAGE_BASE) Test(org.junit.Test) Type(net.runelite.asm.Type) Collectors(java.util.stream.Collectors) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic) ClassGroup(net.runelite.asm.ClassGroup) List(java.util.List) ClassFile(net.runelite.asm.ClassFile) Method(net.runelite.asm.Method) ObfuscatedSignature(net.runelite.mapping.ObfuscatedSignature) ClassUtil(net.runelite.asm.ClassUtil) Hook(net.runelite.mapping.Hook) Signature(net.runelite.asm.signature.Signature) Assert.assertEquals(org.junit.Assert.assertEquals) InputStream(java.io.InputStream) Type(net.runelite.asm.Type) ClassFile(net.runelite.asm.ClassFile) InputStream(java.io.InputStream) ClassGroup(net.runelite.asm.ClassGroup) ObfuscatedSignature(net.runelite.mapping.ObfuscatedSignature) Signature(net.runelite.asm.signature.Signature) Method(net.runelite.asm.Method) Code(net.runelite.asm.attributes.Code) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic) Test(org.junit.Test)

Example 27 with Code

use of net.runelite.asm.attributes.Code in project runelite by runelite.

the class InjectConstruct method injectConstruct.

public void injectConstruct(ClassFile targetClass, java.lang.reflect.Method apiMethod) throws InjectionException {
    logger.info("Injecting construct for {}", apiMethod);
    assert targetClass.findMethod(apiMethod.getName()) == null;
    Class<?> typeToConstruct = apiMethod.getReturnType();
    ClassFile vanillaClass = inject.findVanillaForInterface(typeToConstruct);
    if (vanillaClass == null) {
        throw new InjectionException("Unable to find vanilla class which implements interface " + typeToConstruct);
    }
    Signature sig = inject.javaMethodToSignature(apiMethod);
    Signature constructorSig = new Signature.Builder().addArguments(Stream.of(apiMethod.getParameterTypes()).map(arg -> {
        ClassFile vanilla = inject.findVanillaForInterface(arg);
        if (vanilla != null) {
            return new Type("L" + vanilla.getName() + ";");
        }
        return Inject.classToType(arg);
    }).collect(Collectors.toList())).setReturnType(Type.VOID).build();
    Method vanillaConstructor = vanillaClass.findMethod("<init>", constructorSig);
    if (vanillaConstructor == null) {
        throw new InjectionException("Unable to find constructor for " + vanillaClass.getName() + ".<init>" + constructorSig);
    }
    Method setterMethod = new Method(targetClass, apiMethod.getName(), sig);
    setterMethod.setAccessFlags(ACC_PUBLIC);
    targetClass.addMethod(setterMethod);
    Code code = new Code(setterMethod);
    setterMethod.setCode(code);
    Instructions instructions = code.getInstructions();
    List<Instruction> ins = instructions.getInstructions();
    ins.add(new New(instructions, vanillaClass.getPoolClass()));
    ins.add(new Dup(instructions));
    int idx = 1;
    int parameter = 0;
    for (Type type : vanillaConstructor.getDescriptor().getArguments()) {
        Instruction load = inject.createLoadForTypeIndex(instructions, type, idx);
        idx += type.getSize();
        ins.add(load);
        Type paramType = sig.getTypeOfArg(parameter);
        if (!type.equals(paramType)) {
            CheckCast checkCast = new CheckCast(instructions);
            checkCast.setType(type);
            ins.add(checkCast);
        }
        ++parameter;
    }
    ins.add(new InvokeSpecial(instructions, vanillaConstructor.getPoolMethod()));
    ins.add(new Return(instructions));
}
Also used : New(net.runelite.asm.attributes.code.instructions.New) ClassFile(net.runelite.asm.ClassFile) Return(net.runelite.asm.attributes.code.instructions.Return) InvokeSpecial(net.runelite.asm.attributes.code.instructions.InvokeSpecial) Instructions(net.runelite.asm.attributes.code.Instructions) Method(net.runelite.asm.Method) CheckCast(net.runelite.asm.attributes.code.instructions.CheckCast) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) Type(net.runelite.asm.Type) Signature(net.runelite.asm.signature.Signature) Dup(net.runelite.asm.attributes.code.instructions.Dup)

Example 28 with Code

use of net.runelite.asm.attributes.Code in project runelite by runelite.

the class InjectHook method run.

public void run() {
    Execution e = new Execution(inject.getVanilla());
    e.populateInitialMethods();
    Set<Instruction> done = new HashSet<>();
    Set<Instruction> doneIh = new HashSet<>();
    e.addExecutionVisitor((InstructionContext ic) -> {
        Instruction i = ic.getInstruction();
        Instructions ins = i.getInstructions();
        Code code = ins.getCode();
        Method method = code.getMethod();
        if (method.getName().equals(CLINIT)) {
            return;
        }
        if (!(i instanceof SetFieldInstruction)) {
            return;
        }
        if (!done.add(i)) {
            return;
        }
        SetFieldInstruction sfi = (SetFieldInstruction) i;
        Field fieldBeingSet = sfi.getMyField();
        if (fieldBeingSet == null) {
            return;
        }
        HookInfo hookInfo = hooked.get(fieldBeingSet);
        if (hookInfo == null) {
            return;
        }
        String hookName = hookInfo.fieldName;
        assert hookName != null;
        logger.trace("Found injection location for hook {} at instruction {}", hookName, sfi);
        ++injectedHooks;
        Instruction objectInstruction = new AConstNull(ins);
        StackContext objectStackContext = null;
        if (sfi instanceof PutField) {
            // Object being set on
            StackContext objectStack = ic.getPops().get(1);
            objectStackContext = objectStack;
        }
        int idx = ins.getInstructions().indexOf(sfi);
        assert idx != -1;
        try {
            // idx + 1 to insert after the set
            injectCallback(ins, idx + 1, hookInfo, null, objectStackContext);
        } catch (InjectionException ex) {
            throw new RuntimeException(ex);
        }
    });
    // these look like:
    // getfield
    // iload_0
    // iconst_0
    // iastore
    e.addExecutionVisitor((InstructionContext ic) -> {
        Instruction i = ic.getInstruction();
        Instructions ins = i.getInstructions();
        Code code = ins.getCode();
        Method method = code.getMethod();
        if (method.getName().equals(CLINIT)) {
            return;
        }
        if (!(i instanceof ArrayStore)) {
            return;
        }
        if (!doneIh.add(i)) {
            return;
        }
        ArrayStore as = (ArrayStore) i;
        Field fieldBeingSet = as.getMyField(ic);
        if (fieldBeingSet == null) {
            return;
        }
        HookInfo hookInfo = hooked.get(fieldBeingSet);
        if (hookInfo == null) {
            return;
        }
        String hookName = hookInfo.fieldName;
        // assume this is always at index 1
        StackContext index = ic.getPops().get(1);
        StackContext arrayReference = ic.getPops().get(2);
        InstructionContext arrayReferencePushed = arrayReference.getPushed();
        StackContext objectStackContext = null;
        if (arrayReferencePushed.getInstruction().getType() == InstructionType.GETFIELD) {
            StackContext objectReference = arrayReferencePushed.getPops().get(0);
            objectStackContext = objectReference;
        }
        // inject hook after 'i'
        logger.info("Found array injection location for hook {} at instruction {}", hookName, i);
        ++injectedHooks;
        int idx = ins.getInstructions().indexOf(i);
        assert idx != -1;
        try {
            injectCallback(ins, idx + 1, hookInfo, index, objectStackContext);
        } catch (InjectionException ex) {
            throw new RuntimeException(ex);
        }
    });
    e.run();
}
Also used : InstructionContext(net.runelite.asm.execution.InstructionContext) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) Instructions(net.runelite.asm.attributes.code.Instructions) AConstNull(net.runelite.asm.attributes.code.instructions.AConstNull) Method(net.runelite.asm.Method) DupInstruction(net.runelite.asm.attributes.code.instruction.types.DupInstruction) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) Instruction(net.runelite.asm.attributes.code.Instruction) ArrayStore(net.runelite.asm.attributes.code.instructions.ArrayStore) Code(net.runelite.asm.attributes.Code) Field(net.runelite.asm.Field) PutField(net.runelite.asm.attributes.code.instructions.PutField) Execution(net.runelite.asm.execution.Execution) StackContext(net.runelite.asm.execution.StackContext) HashSet(java.util.HashSet) PutField(net.runelite.asm.attributes.code.instructions.PutField)

Example 29 with Code

use of net.runelite.asm.attributes.Code in project runelite by runelite.

the class InjectInvoker method injectInvoker.

private void injectInvoker(ClassFile clazz, java.lang.reflect.Method method, Method deobfuscatedMethod, Method invokeMethod, String garbage) {
    if (clazz.findMethod(method.getName(), deobfuscatedMethod.getDescriptor()) != null) {
        logger.warn("Not injecting method {} because it already exists!", method);
        // this can happen from exporting a field and method with the same name
        return;
    }
    assert invokeMethod.isStatic() == deobfuscatedMethod.isStatic();
    assert invokeMethod.isStatic() || invokeMethod.getClassFile() == clazz;
    Type lastGarbageArgumentType = null;
    if (deobfuscatedMethod.getDescriptor().getArguments().size() != invokeMethod.getDescriptor().getArguments().size()) {
        // allow for obfuscated method to have a single bogus signature at the end
        assert deobfuscatedMethod.getDescriptor().size() + 1 == invokeMethod.getDescriptor().size();
        List<Type> arguments = invokeMethod.getDescriptor().getArguments();
        lastGarbageArgumentType = arguments.get(arguments.size() - 1);
    }
    // Injected method signature is always the same as the API
    Signature apiSignature = inject.javaMethodToSignature(method);
    Method invokerMethodSignature = new Method(clazz, method.getName(), apiSignature);
    invokerMethodSignature.setAccessFlags(ACC_PUBLIC);
    // create code attribute
    Code code = new Code(invokerMethodSignature);
    invokerMethodSignature.setCode(code);
    Instructions instructions = code.getInstructions();
    List<Instruction> ins = instructions.getInstructions();
    // this + arguments
    code.setMaxStack(1 + invokeMethod.getDescriptor().size());
    // load function arguments onto the stack.
    int index = 0;
    if (!invokeMethod.isStatic()) {
        // this
        ins.add(new ALoad(instructions, index++));
    } else {
        // this method is always non static
        ++index;
    }
    for (int i = 0; i < deobfuscatedMethod.getDescriptor().size(); ++i) {
        Type type = deobfuscatedMethod.getDescriptor().getTypeOfArg(i);
        Instruction loadInstruction = inject.createLoadForTypeIndex(instructions, type, index);
        ins.add(loadInstruction);
        Signature invokeDesc = invokeMethod.getDescriptor();
        Type obType = invokeDesc.getTypeOfArg(i);
        if (!type.equals(obType)) {
            CheckCast checkCast = new CheckCast(instructions);
            checkCast.setType(obType);
            ins.add(checkCast);
        }
        if (loadInstruction instanceof DLoad || loadInstruction instanceof LLoad) {
            index += 2;
        } else {
            index += 1;
        }
    }
    if (lastGarbageArgumentType != null) {
        // if garbage is null here it might just be an unused parameter, not part of the obfuscation
        if (garbage == null) {
            garbage = "0";
        }
        switch(lastGarbageArgumentType.toString()) {
            case "Z":
            case "B":
            case "C":
                ins.add(new BiPush(instructions, Byte.parseByte(garbage)));
                break;
            case "S":
                ins.add(new SiPush(instructions, Short.parseShort(garbage)));
                break;
            case "I":
                ins.add(new LDC(instructions, Integer.parseInt(garbage)));
                break;
            case "D":
                ins.add(new LDC(instructions, Double.parseDouble(garbage)));
                break;
            case "F":
                ins.add(new LDC(instructions, Float.parseFloat(garbage)));
                break;
            case "J":
                ins.add(new LDC(instructions, Long.parseLong(garbage)));
                break;
            default:
                throw new RuntimeException("Unknown type");
        }
    }
    if (invokeMethod.isStatic()) {
        ins.add(new InvokeStatic(instructions, invokeMethod.getPoolMethod()));
    } else {
        ins.add(new InvokeVirtual(instructions, invokeMethod.getPoolMethod()));
    }
    Type returnValue = invokeMethod.getDescriptor().getReturnValue();
    InstructionType returnType;
    if (returnValue.isPrimitive() && returnValue.getDimensions() == 0) {
        switch(returnValue.toString()) {
            case "Z":
            case "I":
                returnType = InstructionType.IRETURN;
                break;
            case "J":
                returnType = InstructionType.LRETURN;
                break;
            case "F":
                returnType = InstructionType.FRETURN;
                break;
            case "D":
                returnType = InstructionType.DRETURN;
                break;
            case "V":
                returnType = InstructionType.RETURN;
                break;
            default:
                assert false;
                return;
        }
    } else {
        returnType = InstructionType.ARETURN;
    }
    ins.add(new Return(instructions, returnType));
    clazz.addMethod(invokerMethodSignature);
}
Also used : SiPush(net.runelite.asm.attributes.code.instructions.SiPush) LLoad(net.runelite.asm.attributes.code.instructions.LLoad) Return(net.runelite.asm.attributes.code.instructions.Return) InstructionType(net.runelite.asm.attributes.code.InstructionType) DLoad(net.runelite.asm.attributes.code.instructions.DLoad) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.instructions.LDC) Method(net.runelite.asm.Method) CheckCast(net.runelite.asm.attributes.code.instructions.CheckCast) Instruction(net.runelite.asm.attributes.code.Instruction) BiPush(net.runelite.asm.attributes.code.instructions.BiPush) Code(net.runelite.asm.attributes.Code) InstructionType(net.runelite.asm.attributes.code.InstructionType) Type(net.runelite.asm.Type) InvokeVirtual(net.runelite.asm.attributes.code.instructions.InvokeVirtual) Signature(net.runelite.asm.signature.Signature) ALoad(net.runelite.asm.attributes.code.instructions.ALoad) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic)

Example 30 with Code

use of net.runelite.asm.attributes.Code 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

Code (net.runelite.asm.attributes.Code)62 Instruction (net.runelite.asm.attributes.code.Instruction)49 Instructions (net.runelite.asm.attributes.code.Instructions)45 LDC (net.runelite.asm.attributes.code.instructions.LDC)31 ClassGroup (net.runelite.asm.ClassGroup)30 VReturn (net.runelite.asm.attributes.code.instructions.VReturn)30 Test (org.junit.Test)29 Method (net.runelite.asm.Method)26 IStore (net.runelite.asm.attributes.code.instructions.IStore)23 ILoad (net.runelite.asm.attributes.code.instructions.ILoad)22 IMul (net.runelite.asm.attributes.code.instructions.IMul)21 Execution (net.runelite.asm.execution.Execution)21 Deobfuscator (net.runelite.deob.Deobfuscator)19 ClassFile (net.runelite.asm.ClassFile)18 Signature (net.runelite.asm.signature.Signature)15 Type (net.runelite.asm.Type)12 Pop (net.runelite.asm.attributes.code.instructions.Pop)12 IAdd (net.runelite.asm.attributes.code.instructions.IAdd)11 Label (net.runelite.asm.attributes.code.Label)10 Field (net.runelite.asm.Field)8