Search in sources :

Example 1 with InvokeStatic

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

the class ReflectionTransformer method transformInvokeVirtual.

// invokevirtual         java/lang/reflect/Method/invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
private void transformInvokeVirtual(Instructions instructions, Instruction i) {
    if (!(i instanceof InvokeVirtual)) {
        return;
    }
    InvokeVirtual iv = (InvokeVirtual) i;
    if (iv.getMethod().getClazz().getName().equals("java/lang/reflect/Method") && iv.getMethod().getName().equals("invoke")) {
        InvokeStatic is = new InvokeStatic(instructions, new net.runelite.asm.pool.Method(new net.runelite.asm.pool.Class("net/runelite/rs/Reflection"), "invoke", new Signature("(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")));
        instructions.replace(iv, is);
        logger.info("Transformed Method.invoke call");
    }
}
Also used : InvokeVirtual(net.runelite.asm.attributes.code.instructions.InvokeVirtual) Signature(net.runelite.asm.signature.Signature) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic)

Example 2 with InvokeStatic

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

the class MappingExecutorUtil method resolve.

public static InstructionContext resolve(InstructionContext ctx, // pushed from ctx
StackContext from) {
    if (ctx.getInstruction() instanceof SetFieldInstruction) {
        StackContext s = ctx.getPops().get(0);
        return resolve(s.getPushed(), s);
    }
    if (ctx.getInstruction() instanceof ConversionInstruction) {
        // assume it pops one and pushes one
        StackContext s = ctx.getPops().get(0);
        return resolve(s.getPushed(), s);
    }
    if (ctx.getInstruction() instanceof DupInstruction) {
        DupInstruction d = (DupInstruction) ctx.getInstruction();
        StackContext s = d.getOriginal(from);
        return resolve(s.getPushed(), s);
    }
    if (ctx.getInstruction() instanceof ArrayLoad) {
        // might be multidimensional array
        // the array
        StackContext s = ctx.getPops().get(1);
        return resolve(s.getPushed(), s);
    }
    if (ctx.getInstruction() instanceof LVTInstruction) {
        LVTInstruction lvt = (LVTInstruction) ctx.getInstruction();
        Variables variables = ctx.getVariables();
        if (lvt.store()) {
            // is this right?
            StackContext s = ctx.getPops().get(0);
            return resolve(s.getPushed(), s);
        } else {
            // variable being loaded
            VariableContext vctx = variables.get(lvt.getVariableIndex());
            assert vctx != null;
            InstructionContext storedCtx = vctx.getInstructionWhichStored();
            if (storedCtx == null)
                // initial parameter
                return ctx;
            if (vctx.isIsParameter()) {
                // this storedCtx is the invoke instruction which called this method.
                assert storedCtx.getInstruction() instanceof InvokeInstruction;
                // In PME non static functions are never stepped into/aren't inline obfuscated
                assert storedCtx.getInstruction() instanceof InvokeStatic;
                // Figure out parameter index from variable index.
                // signature of current method
                Signature sig = ctx.getFrame().getMethod().getDescriptor();
                int paramIndex = 0;
                for (int lvtIndex = 0; /* static */
                paramIndex < sig.size(); lvtIndex += sig.getTypeOfArg(paramIndex++).getSize()) if (lvtIndex == lvt.getVariableIndex())
                    break;
                assert paramIndex < sig.size();
                // Get stack context that was popped by the invoke
                // pops[0] is the first thing popped, which is the last parameter.
                StackContext sctx = storedCtx.getPops().get(sig.size() - 1 - paramIndex);
                return resolve(sctx.getPushed(), sctx);
            }
            return resolve(storedCtx, null);
        }
    }
    if (ctx.getInstruction() instanceof InvokeStatic) {
        if (from.returnSource != null) {
            return resolve(from.returnSource.getPushed(), from.returnSource);
        }
    }
    return ctx;
}
Also used : ArrayLoad(net.runelite.asm.attributes.code.instruction.types.ArrayLoad) InstructionContext(net.runelite.asm.execution.InstructionContext) SetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction) ConversionInstruction(net.runelite.asm.attributes.code.instruction.types.ConversionInstruction) DupInstruction(net.runelite.asm.attributes.code.instruction.types.DupInstruction) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) VariableContext(net.runelite.asm.execution.VariableContext) Variables(net.runelite.asm.execution.Variables) InvokeInstruction(net.runelite.asm.attributes.code.instruction.types.InvokeInstruction) StackContext(net.runelite.asm.execution.StackContext) Signature(net.runelite.asm.signature.Signature) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic)

Example 3 with InvokeStatic

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

the class MappingExecutorUtil method isInlineable.

public static boolean isInlineable(Instruction i) {
    if (!(i instanceof InvokeStatic))
        return false;
    ClassGroup group = i.getInstructions().getCode().getMethod().getClassFile().getGroup();
    InvokeStatic is = (InvokeStatic) i;
    net.runelite.asm.pool.Method m = is.getMethod();
    return group.findClass(m.getClazz().getName()) != null;
}
Also used : ClassGroup(net.runelite.asm.ClassGroup) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic)

Example 4 with InvokeStatic

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

the class DrawAfterWidgets method injectDrawAfterWidgets.

private void injectDrawAfterWidgets() throws InjectionException {
    /*
			This call has to be injected using raw injection because the
			drawWidgets method gets inlined in some revisions. If it wouldn't be,
			mixins would be used to add the call to the end of drawWidgets.

			--> This hook depends on the positions of "if (535573958 * kl != -1)" and "jz.db();".


			Revision 153 - client.ll():
			______________________________________________________

			if (535573958 * kl != -1) {
				me = 0;
				var1 = kl * 1593233303;
				var2 = 523525871 * q;
				var3 = -1668171507 * h.n;
				if (!bo.p(var1, (byte)111)) {
					for(var4 = 0; var4 < 100; ++var4) {
						mb[var4] = true;
					}
				} else {
					z.lj = null;
					bl.hz(fa.g[var1], -1, 0, 0, var2, var3, 0, 0, -1, 1505114436);
					if (z.lj != null) {
						bl.hz(z.lj, -1412584499, 0, 0, var2, var3, 1475313862 * bq.la, aq.lc * 1205565233, -1, 2123188146);
						z.lj = null;
					}
				}
			}

			// <-- INJECT CALL HERE

			jz.db(); <-- noClip method
			______________________________________________________
		 */
    boolean injected = false;
    Method noClip = findStaticMethod("noClip");
    if (noClip == null) {
        throw new InjectionException("Mapped method \"noClip\" could not be found.");
    }
    net.runelite.asm.pool.Method poolNoClip = noClip.getPoolMethod();
    for (ClassFile c : inject.getVanilla().getClasses()) {
        for (Method m : c.getMethods()) {
            if (m.getCode() == null) {
                continue;
            }
            Instructions instructions = m.getCode().getInstructions();
            Set<Label> labels = new HashSet<>();
            // Let's find "invokestatic <some class>.noClip()" and its label
            ListIterator<Instruction> labelIterator = instructions.getInstructions().listIterator();
            while (labelIterator.hasNext()) {
                Instruction i = labelIterator.next();
                if (!(i instanceof InvokeStatic)) {
                    continue;
                }
                InvokeStatic is = (InvokeStatic) i;
                if (!is.getMethod().equals(poolNoClip)) {
                    continue;
                }
                labelIterator.previous();
                Instruction i2 = labelIterator.previous();
                labelIterator.next();
                labelIterator.next();
                // Find the label that marks the code path for the instruction
                if (!(i2 instanceof Label)) {
                    continue;
                }
                // There can be several noClip invocations in a method, so let's catch them all
                labels.add((Label) i2);
            }
            if (labels.isEmpty()) {
                // If we get here, we're either in the wrong method
                // or Jagex has removed the "if (535573958 * kl != -1)"
                logger.debug("Could not find the label for jumping to the " + noClip + " call in " + m);
                continue;
            }
            Set<Label> labelsToInjectAfter = new HashSet<>();
            ListIterator<Instruction> jumpIterator = instructions.getInstructions().listIterator();
            while (jumpIterator.hasNext()) {
                Instruction i = jumpIterator.next();
                if (!(i instanceof JumpingInstruction)) {
                    continue;
                }
                JumpingInstruction ji = (JumpingInstruction) i;
                Label label = null;
                for (Label l : labels) {
                    if (ji.getJumps().contains(l)) {
                        label = l;
                        break;
                    }
                }
                if (label == null) {
                    continue;
                }
                jumpIterator.previous();
                Set<Instruction> insns = new HashSet<>();
                insns.add(jumpIterator.previous());
                insns.add(jumpIterator.previous());
                insns.add(jumpIterator.previous());
                insns.add(jumpIterator.previous());
                // Get the iterator back to i's position
                jumpIterator.next();
                jumpIterator.next();
                jumpIterator.next();
                jumpIterator.next();
                jumpIterator.next();
                /*
						Check that these instruction types are passed into the if-statement:

						ICONST_M1
						GETSTATIC client.kr : I
						LDC 634425425
						IMUL

						We cannot depend on the order of these because of the obfuscation,
						so let's make it easier by just checking that they are there.
					 */
                if (insns.stream().filter(i2 -> i2 instanceof PushConstantInstruction).count() != 2 || insns.stream().filter(i2 -> i2 instanceof IMul).count() != 1 || insns.stream().filter(i2 -> i2 instanceof GetStatic).count() != 1) {
                    continue;
                }
                // At this point, we have found the real injection point
                labelsToInjectAfter.add(label);
            }
            for (Label l : labelsToInjectAfter) {
                InvokeStatic invoke = new InvokeStatic(instructions, new net.runelite.asm.pool.Method(new net.runelite.asm.pool.Class(HOOKS), "drawAfterWidgets", new Signature("()V")));
                instructions.addInstruction(instructions.getInstructions().indexOf(l) + 1, invoke);
                logger.info("injectDrawAfterWidgets injected a call after " + l);
                injected = true;
            }
        }
    }
    if (!injected) {
        throw new InjectionException("injectDrawAfterWidgets failed to inject!");
    }
}
Also used : DeobAnnotations(net.runelite.deob.DeobAnnotations) Logger(org.slf4j.Logger) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) ListIterator(java.util.ListIterator) HOOKS(net.runelite.injector.InjectHookMethod.HOOKS) IMul(net.runelite.asm.attributes.code.instructions.IMul) LoggerFactory(org.slf4j.LoggerFactory) Set(java.util.Set) Inject(net.runelite.injector.Inject) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic) HashSet(java.util.HashSet) ClassFile(net.runelite.asm.ClassFile) Label(net.runelite.asm.attributes.code.Label) Method(net.runelite.asm.Method) Instructions(net.runelite.asm.attributes.code.Instructions) JumpingInstruction(net.runelite.asm.attributes.code.instruction.types.JumpingInstruction) InjectionException(net.runelite.injector.InjectionException) Signature(net.runelite.asm.signature.Signature) Instruction(net.runelite.asm.attributes.code.Instruction) GetStatic(net.runelite.asm.attributes.code.instructions.GetStatic) ClassFile(net.runelite.asm.ClassFile) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) Label(net.runelite.asm.attributes.code.Label) Instructions(net.runelite.asm.attributes.code.Instructions) Method(net.runelite.asm.Method) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) JumpingInstruction(net.runelite.asm.attributes.code.instruction.types.JumpingInstruction) Instruction(net.runelite.asm.attributes.code.Instruction) InjectionException(net.runelite.injector.InjectionException) JumpingInstruction(net.runelite.asm.attributes.code.instruction.types.JumpingInstruction) GetStatic(net.runelite.asm.attributes.code.instructions.GetStatic) Signature(net.runelite.asm.signature.Signature) IMul(net.runelite.asm.attributes.code.instructions.IMul) HashSet(java.util.HashSet) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic)

Example 5 with InvokeStatic

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

the class InjectHookMethod method injectHookMethod.

private void injectHookMethod(Annotation hook, Method deobMethod, Method vanillaMethod) throws InjectionException {
    String hookName = hook.getElement().getString();
    Instructions instructions = vanillaMethod.getCode().getInstructions();
    Signature.Builder builder = new Signature.Builder().setReturnType(// Hooks always return void
    Type.VOID);
    for (Type type : deobMethod.getDescriptor().getArguments()) {
        builder.addArgument(inject.deobfuscatedTypeToApiType(type));
    }
    assert deobMethod.isStatic() == vanillaMethod.isStatic();
    if (!deobMethod.isStatic()) {
        // Add variable to signature
        builder.addArgument(0, inject.deobfuscatedTypeToApiType(new Type(deobMethod.getClassFile().getName())));
    }
    Signature signature = builder.build();
    List<Integer> insertIndexes = findHookLocations(hook, vanillaMethod);
    insertIndexes.sort((a, b) -> Integer.compare(b, a));
    for (int insertPos : insertIndexes) {
        if (!deobMethod.isStatic()) {
            instructions.addInstruction(insertPos++, new ALoad(instructions, 0));
        }
        // current variable index
        int index = deobMethod.isStatic() ? 0 : 1;
        for (int i = index; i < signature.size(); ++i) {
            Type type = signature.getTypeOfArg(i);
            Instruction load = inject.createLoadForTypeIndex(instructions, type, index);
            instructions.addInstruction(insertPos++, load);
            index += type.getSize();
        }
        // Invoke callback
        InvokeStatic invoke = new InvokeStatic(instructions, new net.runelite.asm.pool.Method(new net.runelite.asm.pool.Class(HOOKS), hookName, signature));
        instructions.addInstruction(insertPos++, invoke);
    }
    logger.info("Injected method hook {} in {} with {} args: {}", hookName, vanillaMethod, signature.size(), signature.getArguments());
}
Also used : Instructions(net.runelite.asm.attributes.code.Instructions) ReturnInstruction(net.runelite.asm.attributes.code.instruction.types.ReturnInstruction) Instruction(net.runelite.asm.attributes.code.Instruction) InstructionType(net.runelite.asm.attributes.code.InstructionType) Type(net.runelite.asm.Type) Signature(net.runelite.asm.signature.Signature) ALoad(net.runelite.asm.attributes.code.instructions.ALoad) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic)

Aggregations

InvokeStatic (net.runelite.asm.attributes.code.instructions.InvokeStatic)19 Signature (net.runelite.asm.signature.Signature)14 InvokeVirtual (net.runelite.asm.attributes.code.instructions.InvokeVirtual)8 Method (net.runelite.asm.Method)6 Instruction (net.runelite.asm.attributes.code.Instruction)6 Instructions (net.runelite.asm.attributes.code.Instructions)6 Type (net.runelite.asm.Type)5 Code (net.runelite.asm.attributes.Code)5 ClassFile (net.runelite.asm.ClassFile)4 ALoad (net.runelite.asm.attributes.code.instructions.ALoad)4 ListIterator (java.util.ListIterator)3 ClassGroup (net.runelite.asm.ClassGroup)3 Label (net.runelite.asm.attributes.code.Label)3 InvokeInstruction (net.runelite.asm.attributes.code.instruction.types.InvokeInstruction)3 LDC (net.runelite.asm.attributes.code.instructions.LDC)3 DeobAnnotations (net.runelite.deob.DeobAnnotations)3 IOException (java.io.IOException)2 InputStream (java.io.InputStream)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2