@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;
 }
Exemple #3
0
  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;
  }
Exemple #5
0
  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();
 }
Exemple #10
0
 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;
  }
Exemple #22
0
 @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);
          }
        }
      }
    }
  }