@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (transformedName.equals("net.minecraft.block.BlockDynamicLiquid") && CoreLoadingPlugin.util.getBoolean("FiniteWater", false)) { ClassReader reader = new ClassReader(bytes); ClassNode node = new ClassNode(); reader.accept(node, 0); InsnList getSmallestFlowDecay = new InsnList(); getSmallestFlowDecay.add(new VarInsnNode(ALOAD, 0)); getSmallestFlowDecay.add(new InsnNode(ICONST_0)); getSmallestFlowDecay.add( new FieldInsnNode( PUTFIELD, "net/minecraft/block/BlockDynamicLiquid", "field_149815_a", "I")); for (MethodNode method : node.methods) if ("func_149810_a" .equals( FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(name, method.name, method.desc))) method.instructions.insertBefore(method.instructions.getFirst(), getSmallestFlowDecay); ClassWriter writer = new ClassWriter(0); node.accept(writer); return writer.toByteArray(); } return bytes; }
private InsnList generateInvokeDynamicStatic(String name, String owner, String desc) { InsnList insnList = new InsnList(); Handle methodHandle = new Handle(Opcodes.H_INVOKESTATIC, BOOTSTRAP_CLASS, "dynvokeStatic", BOOTSTRAP_SIGNATURE); insnList.add(new InvokeDynamicInsnNode(owner + "." + name, desc, methodHandle, "")); return insnList; }
private void hookSendMessage(ClassNode cn) { Pattern p = new PatternBuilder() .add( new InstructionElement(INVOKESTATIC), new AnyElement(), new LdcElement(new LdcInsnNode("Chat")), new InstructionElement(INVOKEVIRTUAL)) .build(); for (MethodNode mn : cn.methods) { if (!p.contains(mn.instructions)) continue; int offset = p.getOffset(mn.instructions) + 4; InsnList inject = new InsnList(); inject.add(new VarInsnNode(ALOAD, 2)); inject.add( new MethodInsnNode( INVOKESTATIC, "me/themallard/bitmmo/impl/plugin/chathook/ChatHookManager", "onChatMessage", "(Ljava/lang/String;)V", false)); mn.instructions.insert(mn.instructions.get(offset), inject); } }
private boolean scanDecrypter(MethodNode decryptermethodnode, int newHashCode) { InsnList iList = decryptermethodnode.instructions; AbstractInsnNode insn = null, removeInsn = null; for (AbstractInsnNode i : iList.toArray()) { if (i instanceof MethodInsnNode) { MethodInsnNode methodi = ((MethodInsnNode) i); if ("currentThread".equals(methodi.name)) { // find code form this instruction insn = i; break; } } } if (insn == null) { return false; } while (insn != null) { if (insn instanceof MethodInsnNode) { MethodInsnNode methodi = ((MethodInsnNode) insn); if ("hashCode".equals(methodi.name)) { // to this instruction break; } } removeInsn = insn; insn = insn.getNext(); iList.remove(removeInsn); // and remove it } if (insn == null) return false; iList.set(insn, new LdcInsnNode(newHashCode)); // then replace it with pre-computed key LDC return true; }
private void hookRecieveMessage(ClassNode cn) { Pattern p = new PatternBuilder() .add( new InstructionElement(DUP), new InstructionElement(INVOKESPECIAL), new LdcElement(new LdcInsnNode("\n"))) .build(); for (MethodNode mn : cn.methods) { if (!p.contains(mn.instructions)) continue; int offset = p.getOffset(mn.instructions); MethodInsnNode getMsgInsn = (MethodInsnNode) mn.instructions.get(offset + 5); InsnList inject = new InsnList(); inject.add(new VarInsnNode(ALOAD, 1)); inject.add( new MethodInsnNode( INVOKEVIRTUAL, getMsgInsn.owner, getMsgInsn.name, "()Ljava/lang/String;", false)); inject.add( new MethodInsnNode( INVOKESTATIC, "me/themallard/bitmmo/impl/plugin/chathook/ChatHookManager", "onReceiveMessage", "(Ljava/lang/String;)V", false)); mn.instructions.insertBefore(mn.instructions.get(offset), inject); } }
private int firePeacefulRegenEventAndStoreEventBefore( MethodNode method, AbstractInsnNode injectPoint, LabelNode endLabel) { // create variable LabelNode peacefulRegenEventStart = new LabelNode(); LocalVariableNode peacefulRegenEvent = new LocalVariableNode( "peacefulRegenEvent", Type.getDescriptor(HealthRegenEvent.PeacefulRegen.class), null, peacefulRegenEventStart, endLabel, method.maxLocals); method.maxLocals += 1; method.localVariables.add(peacefulRegenEvent); InsnList toInject = new InsnList(); // HealthRegenEvent.PeacefulRegen peacefulRegenEvent = Hooks.firePeacefulRegenEvent(this); toInject.add(new VarInsnNode(ALOAD, 0)); toInject.add( new MethodInsnNode( INVOKESTATIC, Type.getInternalName(Hooks.class), "firePeacefulRegenEvent", "(Lnet/minecraft/entity/player/EntityPlayer;)Lsqueek/applecore/api/hunger/HealthRegenEvent$PeacefulRegen;", false)); toInject.add(new VarInsnNode(ASTORE, peacefulRegenEvent.index)); toInject.add(peacefulRegenEventStart); method.instructions.insertBefore(injectPoint, toInject); return peacefulRegenEvent.index; }
/** {@inheritDoc} */ @Override public List<Mutation> apply( MethodNode mn, String className, String methodName, BytecodeInstruction instruction, Frame frame) { List<Mutation> mutations = new LinkedList<Mutation>(); FieldInsnNode node = (FieldInsnNode) instruction.getASMNode(); Type fieldType = Type.getType(node.desc); // insert mutation into bytecode with conditional InsnList mutation = new InsnList(); logger.debug("Mutation deletefield for statement " + node.name + node.desc); if (node.getOpcode() == Opcodes.GETFIELD) { logger.debug("Deleting source of type " + node.owner); mutation.add(new InsnNode(Opcodes.POP)); } mutation.add(getDefault(fieldType)); // insert mutation into pool Mutation mutationObject = MutationPool.addMutation( className, methodName, NAME + " " + node.name + node.desc, instruction, mutation, getInfectionDistance(node, mutation)); mutations.add(mutationObject); return mutations; }
@Override public void checkCall( @NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method, @NonNull MethodInsnNode call) { String owner = call.owner; String desc = call.desc; if (owner.equals(OWNER_SECURE_RANDOM)) { if (desc.startsWith(LONG_ARG)) { checkValidSetSeed(context, call); } else if (desc.startsWith("([B)")) { // $NON-NLS-1$ // setSeed(byte[]) ... // We could do some flow analysis here to see whether the byte array getting // passed in appears to be fixed. // However, people calling this constructor rather than the simpler one // with a fixed integer are probably less likely to make that mistake... right? } } else if (owner.equals(OWNER_RANDOM) && desc.startsWith(LONG_ARG)) { // Called setSeed(long) on an instanceof a Random object. Flag this if the instance // is likely a SecureRandom. // Track allocations such that we know whether the type of the call // is on a SecureRandom rather than a Random Analyzer analyzer = new Analyzer( new BasicInterpreter() { @Override public BasicValue newValue(Type type) { if (type != null && type.getDescriptor().equals(VM_SECURE_RANDOM)) { return new BasicValue(type); } return super.newValue(type); } }); try { Frame[] frames = analyzer.analyze(classNode.name, method); InsnList instructions = method.instructions; Frame frame = frames[instructions.indexOf(call)]; int stackSlot = frame.getStackSize(); for (Type type : Type.getArgumentTypes(desc)) { stackSlot -= type.getSize(); } BasicValue stackValue = (BasicValue) frame.getStack(stackSlot); Type type = stackValue.getType(); if (type != null && type.getDescriptor().equals(VM_SECURE_RANDOM)) { checkValidSetSeed(context, call); } } catch (AnalyzerException e) { context.log(e, null); } } else if (owner.equals(OWNER_RANDOM) && desc.startsWith(LONG_ARG)) { // Called setSeed(long) on an instanceof a Random object. Flag this if the instance // is likely a SecureRandom. // TODO } }
/** * analysis and data structure per method * * @param method */ private void flowMethod(final MethodNode method) { final InsnList instructions = method.instructions; ControlFlowGraphDataStructure controlFlow = new ControlFlowGraphDataStructure(instructions); for (int idx = 0; idx < instructions.size(); ++idx) { final AbstractInsnNode instruction = instructions.get(idx); controlFlow.appendInstruction(instruction, idx); } controlFlow.dottyPrint(); }
public static InsnList createArgumentLoaders(String methodDescriptor) { checkArgNotNull(methodDescriptor, "methodDescriptor"); InsnList instructions = new InsnList(); Type[] types = Type.getArgumentTypes(methodDescriptor); for (int i = 0; i < types.length; i++) { instructions.add(new VarInsnNode(getLoadingOpcode(types[i]), i + 1)); } return instructions; }
private InsnList generateInvokeDynamicConstructor(String name, String owner, String desc) { InsnList insnList = new InsnList(); Handle methodHandle = new Handle( Opcodes.H_INVOKESTATIC, BOOTSTRAP_CLASS, "dynvokeConstructor", BOOTSTRAP_SIGNATURE); String descReceiver = Type.getMethodDescriptor(Type.getObjectType(owner), Type.getArgumentTypes(desc)); insnList.add(new InvokeDynamicInsnNode(owner + "." + name, descReceiver, methodHandle, "")); return insnList; }
/** visit end method for intrumentation */ @Override public void visitEnd() { for (Object o : methods) { MethodNode mn = (MethodNode) o; // filtering the methods if (!(validateMapReduceClinitMethod(mn.name, MAP_METHOD, REDUCE_METHOD, CLINIT_METHOD) || checkMethodNameAndArgumentLength(mn) || (mn.access & Opcodes.ACC_SYNTHETIC) == Opcodes.ACC_SYNTHETIC)) { InsnList insnList = mn.instructions; AbstractInsnNode[] insnArr = insnList.toArray(); // adding entry logging logger.info( MessageFormat.format( InstrumentationMessageLoader.getMessage(MessageConstants.LOG_METHOD_ENTRY), getClassName() + "##" + mn.name + "##" + mn.desc)); String logMsg = InstrumentationMessageLoader.getMessage(MessageConstants.ENTERED_METHOD); String cSymbol = env.getClassSymbol(getClassName()); String mSymbol = env.getMethodSymbol(getClassName(), cSymbol, mn.name); InsnList il = InstrumentUtil.addLogMessage(cSymbol, mSymbol, logMsg); insnList.insertBefore(insnList.getFirst(), il); for (AbstractInsnNode abstractInsnNode : insnArr) { if (Opcodes.RETURN >= abstractInsnNode.getOpcode() && Opcodes.IRETURN <= abstractInsnNode.getOpcode()) { // adding exit logging logger.info( MessageFormat.format( InstrumentationMessageLoader.getMessage(MessageConstants.LOG_METHOD_EXIT), getClassName() + "##" + mn.name)); logMsg = InstrumentationMessageLoader.getMessage(MessageConstants.EXITING_METHOD); cSymbol = env.getClassSymbol(getClassName()); mSymbol = env.getMethodSymbol(getClassName(), cSymbol, mn.name); il = InstrumentUtil.addLogMessage(cSymbol, mSymbol, logMsg); // inserting the list at the associated label node AbstractInsnNode prevNode = abstractInsnNode.getPrevious(); while (!(prevNode instanceof LabelNode)) { prevNode = prevNode.getPrevious(); } insnList.insert(prevNode, il); } } } mn.visitMaxs(0, 0); } accept(cv); }
private InsnList generateInvokeDynamicVirtualInterfaceSpecial( String name, String owner, String desc, String bootstrapMethod) { InsnList insnList = new InsnList(); Handle methodHandle = new Handle(Opcodes.H_INVOKESTATIC, BOOTSTRAP_CLASS, bootstrapMethod, BOOTSTRAP_SIGNATURE); List<Type> argsList = new ArrayList<Type>(Arrays.asList(new Type[] {Type.getObjectType(owner)})); argsList.addAll(Arrays.asList(Type.getArgumentTypes(desc))); String descReceiver = Type.getMethodDescriptor( Type.getReturnType(desc), argsList.toArray(new Type[argsList.size()])); insnList.add(new InvokeDynamicInsnNode(owner + "." + name, descReceiver, methodHandle, "")); return insnList; }
public void addTinkersDrawHoveringTextHook( MethodNode method, Class<?> hookClass, String hookMethod, String hookDesc, boolean isObfuscated) { AbstractInsnNode targetNode = null; // get last drawGradientRect call for (AbstractInsnNode instruction : method.instructions.toArray()) { if (instruction.getOpcode() == INVOKEVIRTUAL) { MethodInsnNode methodInsn = (MethodInsnNode) instruction; if (methodInsn.desc.equals("(IIIIII)V")) targetNode = instruction; } } if (targetNode == null) { AppleCore.Log.warn("Could not patch " + method.name + "; target node not found"); return; } LocalVariableNode x = ASMHelper.findLocalVariableOfMethod(method, "i1", "I"); LocalVariableNode y = ASMHelper.findLocalVariableOfMethod(method, "j1", "I"); LocalVariableNode w = ASMHelper.findLocalVariableOfMethod(method, "k", "I"); LocalVariableNode h = ASMHelper.findLocalVariableOfMethod(method, "k1", "I"); if (x == null || y == null || w == null || h == null) { AppleCore.Log.warn("Could not patch " + method.name + "; local variables not found"); return; } InsnList toInject = new InsnList(); /* // equivalent to: Hooks.onDrawHoveringText(0, 0, 0, 0); */ toInject.add(new VarInsnNode(ILOAD, x.index)); toInject.add(new VarInsnNode(ILOAD, y.index)); toInject.add(new VarInsnNode(ILOAD, w.index)); toInject.add(new VarInsnNode(ILOAD, h.index)); toInject.add( new MethodInsnNode( INVOKESTATIC, hookClass.getName().replace('.', '/'), hookMethod, hookDesc, false)); method.instructions.insert(targetNode, toInject); }
public void appendInstruction(final AbstractInsnNode ins, final int idx) { final int opcode = ins.getOpcode(); String mnemonic = (opcode == -1 ? "" : Printer.OPCODES[this.instructions.get(idx).getOpcode()]); switch (ins.getType()) { case AbstractInsnNode.JUMP_INSN: final LabelNode targetInstruction = ((JumpInsnNode) ins).label; final int dest = instructions.indexOf(targetInstruction); if (idx < dest) { append(mnemonic, idx); forward(new String(idx + "> " + mnemonic), dest); return; // already appended } else { append(mnemonic, idx); backward(new String(idx + "> " + mnemonic), dest); return; } case AbstractInsnNode.LABEL: // pseudo-instruction (branch or exception target) mnemonic = "label"; break; case AbstractInsnNode.FRAME: // pseudo-instruction (stack frame map) return; case AbstractInsnNode.LINE: // pseudo-instruction (line number information) return; } // append other type of instructions -1 append(mnemonic, idx); }
private void append(final String mnemonic, final int idx) { // a former forward link connected to this instruction, so we provoke starting a new block if (null != ptr) { if (1 < ptr.size() && null != srctable.get(String.valueOf(idx))) { ptr = null; } } if (null == ptr) { // handle int dst to sz dst mapping, for dotty dstResolvMap.put(Integer.valueOf(idx), String.valueOf(idx + "> " + mnemonic)); // start a new block list ptr = new ArrayList<String>(); content.add(ptr); if (0 < idx && !fallthruOpcodes.contains(instructions.get(idx - 1).getOpcode())) { String src = String.valueOf( idx - 1 + "> " + Printer.OPCODES[this.instructions.get(idx - 1).getOpcode()]); String dst = String.valueOf(idx + "> " + mnemonic); fallthruList.add(src + "->" + dst); } } // append current item ptr.add(String.valueOf(idx) + "> " + mnemonic); }
private byte[] transformEntitySheep(byte[] bytes) { System.out.println("Transforming EntitySheep..."); ClassNode cn = new ClassNode(); ClassReader cr = new ClassReader(bytes); cr.accept(cn, 0); Iterator<MethodNode> methods = cn.methods.iterator(); while (methods.hasNext()) { MethodNode m = methods.next(); if (m.name.equals(names.get("entitySheep_setColour_func")) && m.desc.equals(names.get("entitySheep_setColour_desc"))) { System.out.println("Found target method: " + m.name + m.desc + "! Inserting call..."); for (int idx = 0; idx < m.instructions.size(); idx++) { if (m.instructions.get(idx).getOpcode() == Opcodes.ISTORE) { System.out.println("Found ISTORE at index " + idx + ", inserting code afterwards..."); idx++; // AFTERwards, not before ;) InsnList toAdd = new InsnList(); // to mark the end of the code LabelNode lmmnode = new LabelNode(new Label()); // load this toAdd.add(new VarInsnNode(Opcodes.ALOAD, 0)); // new fleece colour toAdd.add(new VarInsnNode(Opcodes.ILOAD, 1)); // old fleece colour toAdd.add(new VarInsnNode(Opcodes.ILOAD, 2)); toAdd.add( new MethodInsnNode( Opcodes.INVOKESTATIC, "keepcalm/mods/events/ForgeEventHelper", "onSheepDye", "(L" + names.get("entitySheep_javaName") + ";II)Z")); LabelNode endIf = new LabelNode(new Label()); toAdd.add(new JumpInsnNode(Opcodes.IFEQ, endIf)); toAdd.add(new InsnNode(Opcodes.RETURN)); toAdd.add(endIf); toAdd.add(lmmnode); m.instructions.insertBefore(m.instructions.get(idx), toAdd); break; } } } } ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cn.accept(cw); return cw.toByteArray(); }
/* (non-Javadoc) * @see ch.usi.inf.gustarim.apt.analysis.SpecificAnalyzer#analyzeMethod(org.objectweb.asm.tree.MethodNode) */ @Override protected Collection<Problem> analyzeMethod(final MethodNode methodNode) { final LinkedList<Problem> problems = new LinkedList<Problem>(); final InsnList instructions = methodNode.instructions; for (int i = 0; i < instructions.size(); i++) { final AbstractInsnNode insnNode = instructions.get(i); if (insnNode.getOpcode() == Opcodes.PUTSTATIC) { final FieldInsnNode field = (FieldInsnNode) insnNode; final String fieldName = field.name; if (!isFinal(fieldName)) { final Problem problem = new Problem(insnNode); problems.add(problem); } } } return problems; }
/** * getInfectionDistance * * @param opcodeOrig a int. * @param opcodeNew a int. * @return a {@link org.objectweb.asm.tree.InsnList} object. */ public InsnList getInfectionDistance(int opcodeOrig, int opcodeNew) { InsnList distance = new InsnList(); switch (opcodeOrig) { case Opcodes.IF_ICMPEQ: case Opcodes.IF_ICMPNE: case Opcodes.IF_ICMPLE: case Opcodes.IF_ICMPLT: case Opcodes.IF_ICMPGE: case Opcodes.IF_ICMPGT: distance.add(new InsnNode(Opcodes.DUP2)); distance.add(new LdcInsnNode(opcodeOrig)); distance.add(new LdcInsnNode(opcodeNew)); distance.add( new MethodInsnNode( Opcodes.INVOKESTATIC, "org/evosuite/instrumentation/mutation/ReplaceComparisonOperator", "getInfectionDistance", "(IIII)D", false)); break; case Opcodes.IFEQ: case Opcodes.IFNE: case Opcodes.IFLE: case Opcodes.IFLT: case Opcodes.IFGE: case Opcodes.IFGT: distance.add(new InsnNode(Opcodes.DUP)); distance.add(new LdcInsnNode(opcodeOrig)); distance.add(new LdcInsnNode(opcodeNew)); distance.add( new MethodInsnNode( Opcodes.INVOKESTATIC, "org/evosuite/instrumentation/mutation/ReplaceComparisonOperator", "getInfectionDistance", "(III)D", false)); break; default: distance.add(new LdcInsnNode(0.0)); } return distance; }
@Override protected void apply(ClassNode cn) { MethodNode m = ReikaASMHelper.getMethodByName( cn, "func_77943_a", "tryPlaceItemIntoWorld", "(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/world/World;IIIIFFF)Z"); AbstractInsnNode ain = ReikaASMHelper.getLastOpcode(m.instructions, Opcodes.INVOKEVIRTUAL); InsnList li = new InsnList(); li.add(new VarInsnNode(Opcodes.ALOAD, 0)); li.add(new VarInsnNode(Opcodes.ALOAD, 1)); li.add(new VarInsnNode(Opcodes.ALOAD, 2)); li.add(new VarInsnNode(Opcodes.ILOAD, 3)); li.add(new VarInsnNode(Opcodes.ILOAD, 4)); li.add(new VarInsnNode(Opcodes.ILOAD, 5)); li.add(new VarInsnNode(Opcodes.ILOAD, 6)); li.add(new VarInsnNode(Opcodes.FLOAD, 7)); li.add(new VarInsnNode(Opcodes.FLOAD, 8)); li.add(new VarInsnNode(Opcodes.FLOAD, 9)); li.add( new MethodInsnNode( Opcodes.INVOKESTATIC, "Reika/DragonAPI/Instantiable/Event/PostItemUseEvent", "fire", "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/world/World;IIIIFFF)V", false)); m.instructions.insert(ain, li); // ReikaJavaLibrary.pConsole(ReikaASMHelper.clearString(m.instructions)); }
/** * getInfectionDistance * * @param original a {@link org.objectweb.asm.tree.FieldInsnNode} object. * @param mutant a {@link org.objectweb.asm.tree.InsnList} object. * @return a {@link org.objectweb.asm.tree.InsnList} object. */ public InsnList getInfectionDistance(FieldInsnNode original, InsnList mutant) { InsnList distance = new InsnList(); if (original.getOpcode() == Opcodes.GETFIELD) distance.add(new InsnNode(Opcodes.DUP)); // make sure to re-load this for GETFIELD distance.add( new FieldInsnNode(original.getOpcode(), original.owner, original.name, original.desc)); Type type = Type.getType(original.desc); if (type.getDescriptor().startsWith("L") || type.getDescriptor().startsWith("[")) { ReplaceVariable.addReferenceDistanceCheck(distance, type, mutant); } else { ReplaceVariable.addPrimitiveDistanceCheck(distance, type, mutant); } return distance; }
@SuppressWarnings("unchecked") private static void processReflection(Remapper remapper, ClassNode node) { for (MethodNode mn : (List<MethodNode>) node.methods) { InsnList insns = mn.instructions; ListIterator<AbstractInsnNode> iterator = insns.iterator(); while (iterator.hasNext()) { AbstractInsnNode insn = iterator.next(); if (insn.getOpcode() == Opcodes.INVOKESTATIC) { MethodInsnNode min = (MethodInsnNode) insn; if (min.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) { AbstractInsnNode push = insn.getPrevious(); if (push.getOpcode() == Opcodes.LDC) { LdcInsnNode lin = (LdcInsnNode) push; lin.cst = remapper.map(((String) lin.cst).replace('.', '/')).replace('/', '.'); } } } } } }
public void addCodeChickenDrawHoveringTextHook( MethodNode method, Class<?> hookClass, String hookMethod, String hookDesc) { AbstractInsnNode targetNode = ASMHelper.findFirstInstruction(method); InsnList toInject = new InsnList(); /* // equivalent to: Hooks.onDrawHoveringText(0, 0, 0, 0); */ toInject.add(new VarInsnNode(ILOAD, 0)); // x toInject.add(new VarInsnNode(ILOAD, 1)); // y toInject.add(new VarInsnNode(ILOAD, 2)); // w toInject.add(new VarInsnNode(ILOAD, 3)); // h toInject.add( new MethodInsnNode( INVOKESTATIC, hookClass.getName().replace('.', '/'), hookMethod, hookDesc, false)); method.instructions.insertBefore(targetNode, toInject); }
@Override public boolean find( String desc, InsnList insns, Collection<AbstractInsnNode> nodes, Event event) { List<AbstractInsnNode> list = (nodes instanceof List) ? (List<AbstractInsnNode>) nodes : new ArrayList<AbstractInsnNode>(nodes); this.input.find(desc, insns, nodes, event); for (int i = 0; i < list.size(); i++) { list.set(i, insns.get(insns.indexOf(list.get(i)) + this.shift)); } if (nodes != list) { nodes.clear(); nodes.addAll(list); } return nodes.size() > 0; }
public void addPeacefulRegenHook(ClassNode classNode, MethodNode method) { AbstractInsnNode relevantConditional = ASMHelper.find(method.instructions, new LdcInsnNode("naturalRegeneration")); JumpInsnNode ifNode = (JumpInsnNode) ASMHelper.find(relevantConditional, new JumpInsnNode(IFEQ, new LabelNode())); LabelNode ifBlockEndLabel = ifNode.label; AbstractInsnNode targetNode = ASMHelper.find(ifNode, new InsnNode(FCONST_1)).getPrevious(); int peacefulRegenEventIndex = firePeacefulRegenEventAndStoreEventBefore(method, targetNode, ifBlockEndLabel); InsnList healAmountNeedle = new InsnList(); healAmountNeedle.add(new InsnNode(FCONST_1)); InsnList healAmountReplacement = new InsnList(); healAmountReplacement.add(new VarInsnNode(ALOAD, peacefulRegenEventIndex)); healAmountReplacement.add( new FieldInsnNode( GETFIELD, Type.getInternalName(HealthRegenEvent.PeacefulRegen.class), "deltaHealth", "F")); ASMHelper.findAndReplace( method.instructions, healAmountNeedle, healAmountReplacement, targetNode); InsnList ifNotCanceledBlock = new InsnList(); LabelNode ifNotCanceled = new LabelNode(); ifNotCanceledBlock.add(new VarInsnNode(ALOAD, peacefulRegenEventIndex)); ifNotCanceledBlock.add( new MethodInsnNode( INVOKEVIRTUAL, Type.getInternalName(HealthRegenEvent.PeacefulRegen.class), "isCanceled", "()Z", false)); ifNotCanceledBlock.add(new JumpInsnNode(IFNE, ifNotCanceled)); method.instructions.insertBefore(targetNode, ifNotCanceledBlock); method.instructions.insertBefore(ifBlockEndLabel, ifNotCanceled); }
/** {@inheritDoc} */ @Override public List<Mutation> apply( MethodNode mn, String className, String methodName, BytecodeInstruction instruction, Frame frame) { JumpInsnNode node = (JumpInsnNode) instruction.getASMNode(); List<Mutation> mutations = new LinkedList<Mutation>(); LabelNode target = node.label; boolean isBoolean = frame.getStack(frame.getStackSize() - 1) == BooleanValueInterpreter.BOOLEAN_VALUE; for (Integer op : getOperators(node.getOpcode(), isBoolean)) { logger.debug("Adding replacement " + op); if (op >= 0) { // insert mutation into bytecode with conditional JumpInsnNode mutation = new JumpInsnNode(op, target); // insert mutation into pool Mutation mutationObject = MutationPool.addMutation( className, methodName, "ReplaceComparisonOperator " + getOp(node.getOpcode()) + " -> " + getOp(op), instruction, mutation, getInfectionDistance(node.getOpcode(), op)); mutations.add(mutationObject); } else { // Replace relational operator with TRUE/FALSE InsnList mutation = new InsnList(); if (opcodesInt.contains(node.getOpcode())) mutation.add(new InsnNode(Opcodes.POP)); else mutation.add(new InsnNode(Opcodes.POP2)); if (op == TRUE) { mutation.add(new LdcInsnNode(1)); } else { mutation.add(new LdcInsnNode(0)); } mutation.add(new JumpInsnNode(Opcodes.IFNE, target)); Mutation mutationObject = MutationPool.addMutation( className, methodName, "ReplaceComparisonOperator " + getOp(node.getOpcode()) + " -> " + op, instruction, mutation, getInfectionDistance(node.getOpcode(), op)); mutations.add(mutationObject); } } return mutations; }
@Override public void transform(ClassNode cnode) { System.out.println("[NOVA] Transforming Chunk class for chunkModified event."); ObfMapping obfMap = new ObfMapping("apx", "a", "(IIILaji;I)Z"); ObfMapping srgMap = new ObfMapping( "net/minecraft/world/chunk/Chunk", "func_150807_a", "(IIILnet/minecraft/block/Block;I)Z"); MethodNode method = ASMHelper.findMethod(obfMap, cnode); if (method == null) { System.out.println( "[NOVA] Lookup " + obfMap + " failed. You are probably in a deobf environment."); method = ASMHelper.findMethod(srgMap, cnode); if (method == null) { System.out.println("[NOVA] Lookup " + srgMap + " failed!"); } } System.out.println("[NOVA] Found method " + method.name); InsnList list = new InsnList(); list.add(new VarInsnNode(ALOAD, 0)); list.add(new VarInsnNode(ILOAD, 1)); list.add(new VarInsnNode(ILOAD, 2)); list.add(new VarInsnNode(ILOAD, 3)); list.add(new VarInsnNode(ALOAD, 8)); list.add(new VarInsnNode(ILOAD, 9)); list.add(new VarInsnNode(ALOAD, 4)); list.add(new VarInsnNode(ILOAD, 5)); list.add( new MethodInsnNode( INVOKESTATIC, "nova/wrapper/mc1710/asm/StaticForwarder", "chunkSetBlockEvent", "(Lnet/minecraft/world/chunk/Chunk;IIILnet/minecraft/block/Block;ILnet/minecraft/block/Block;I)V", false)); AbstractInsnNode lastInsn = method.instructions.getLast(); while (lastInsn instanceof LabelNode || lastInsn instanceof LineNumberNode) { lastInsn = lastInsn.getPrevious(); } if (ASMHelper.isReturn(lastInsn)) { method.instructions.insertBefore(lastInsn, list); } else { method.instructions.insert(list); } System.out.println("[NOVA] Injected instruction to method: " + method.name); }
public byte[] transformCreeper(byte[] bytes) { ClassNode cn = new ClassNode(); ClassReader cr = new ClassReader(bytes); cr.accept(cn, 0); // System.out.println("Transforming EntityCreeper..."); Iterator<MethodNode> methods = cn.methods.iterator(); while (methods.hasNext()) { MethodNode m = methods.next(); // System.out.println(m.name + m.desc + " vs " + names.get("entityCreeper_onUpdate_func") + // names.get("entityCreeper_onUpdate_desc")); if (m.name.equals(names.get("entityCreeper_onUpdate_func")) && m.desc.equals(names.get("entityCreeper_onUpdate_desc"))) { for (int i = m.instructions.size() - 1; i >= 0; i--) { if (m.instructions.get(i).getOpcode() == Opcodes.IFNE) { System.out.println("Found insertion point! inserting code!"); i++; InsnList insns = new InsnList(); insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); insns.add( new MethodInsnNode( Opcodes.INVOKESTATIC, "keepcalm/mods/events/ForgeEventHelper", "onCreeperExplode", "(L" + names.get("entityCreeper_javaName") + ";)Z")); LabelNode endIf = new LabelNode(new Label()); insns.add(new JumpInsnNode(Opcodes.IFEQ, endIf)); // insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); // insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, // names.get("entityCreeper_javaName"), names.get("entityCreeper_setDead_func"), // names.get("entityCreeper_setDead_desc"))); insns.add(new InsnNode(Opcodes.RETURN)); insns.add(endIf); insns.add(new LabelNode(new Label())); m.instructions.insertBefore(m.instructions.get(i), insns); break; } } } } ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cn.accept(cw); return cw.toByteArray(); }
private byte[] transformNetServerHandler(byte[] bytes) { ClassNode cn = new ClassNode(); ClassReader cr = new ClassReader(bytes); cr.accept(cn, 0); Iterator<MethodNode> methods = cn.methods.iterator(); while (methods.hasNext()) { MethodNode m = methods.next(); if (m.name.equals(names.get("netServerHandler_handleFlying_func")) && m.desc.equals(names.get("netServerHandler_handleFlying_desc"))) { System.out.println("Found target method: " + m.name + m.desc + "! Inserting code..."); InsnList toInsert = new InsnList(); toInsert.add(new VarInsnNode(Opcodes.ALOAD, 1)); toInsert.add(new VarInsnNode(Opcodes.ALOAD, 0)); toInsert.add( new MethodInsnNode( Opcodes.INVOKESTATIC, "keepcalm/mods/events/ForgeEventHelper", "onPlayerMove", "(L" + names.get("packet10Flying_javaName") + ";L" + names.get("netServerHandler_javaName") + ";)Z")); LabelNode endIf = new LabelNode(new Label()); toInsert.add(new JumpInsnNode(Opcodes.IFEQ, endIf)); toInsert.add(new InsnNode(Opcodes.RETURN)); toInsert.add(endIf); toInsert.add(new LabelNode(new Label())); m.instructions.insert(toInsert); } } ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cn.accept(cw); return cw.toByteArray(); }
private void addInitializationLogicToConstructors() { if (!classMetadata.hasManagedFieldsWithFieldGranularity()) { return; } for (MethodNode methodNode : (List<MethodNode>) classNode.methods) { MethodMetadata methodMetadata = classMetadata.getMethodMetadata(methodNode.name, methodNode.desc); if (methodMetadata.isTransactional() && methodMetadata.isConstructor()) { int firstAfterSuper = firstIndexAfterSuper(methodNode, classNode.superName); if (firstAfterSuper >= 0) { InsnList extraInstructions = new InsnList(); for (FieldNode fieldNode : (List<FieldNode>) classNode.fields) { FieldMetadata fieldMetadata = classMetadata.getFieldMetadata(fieldNode.name); if (fieldMetadata.hasFieldGranularity()) { extraInstructions.add(new VarInsnNode(ALOAD, 0)); String referenceDesc = findReferenceDesc(fieldMetadata.getDesc()); String referenceName = Type.getType(referenceDesc).getInternalName(); extraInstructions.add(new TypeInsnNode(NEW, referenceName)); extraInstructions.add(new InsnNode(DUP)); extraInstructions.add( new MethodInsnNode(INVOKESPECIAL, referenceName, "<init>", "()V")); extraInstructions.add( new FieldInsnNode(PUTFIELD, classNode.name, fieldNode.name, referenceDesc)); } AbstractInsnNode first = methodNode.instructions.get(firstAfterSuper); methodNode.instructions.insert(first, extraInstructions); } } } } }