ASM代码未注入正确的位置

时间:2014-02-26 05:40:41

标签: java code-injection bytecode

我试图在一个类中注入两行代码。我曾经设法让它工作一次,但我无法让它再次工作。出于某种原因,无论我做什么,我都无法让代码在运行时运行,即使它应该成功注入。这是我的注射方法:

 public byte[] patchBlockRotatedPillarASM(String name, byte[] bytes, boolean obfuscated)
 {
        String targetMethodName = "";
        if(obfuscated == true)
        {
            targetMethodName ="a";
            System.out.println("******** Using obfuscated method");
        }
        else
        {
            targetMethodName ="onBlockPlaced";
            System.out.println("******** Using unobfuscated method");
        }
        //set up ASM class manipulation stuff. Consult the ASM docs for details
        ClassNode classNode = new ClassNode();
        ClassReader classReader = new ClassReader(bytes);
        classReader.accept(classNode, 0);
        //Now we loop over all of the methods declared inside the Block class until we get to the targetMethodName "onBlockPlaced" 
        @SuppressWarnings("unchecked")
        Iterator<MethodNode> methods = classNode.methods.iterator();
        while(methods.hasNext())
        {
            MethodNode m = methods.next();
            System.out.println("********* Method Name: "+m.name + " Desc:" + m.desc);
            int fdiv_index = -1;
            //Check if this is onBlockPlaced and it's method signature is (Lnet/minecraft/world/World;IIIIFFFI)I
            if ((m.name.equals(targetMethodName) && m.desc.equals("(Lnet/minecraft/world/World;IIIIFFFI)I")))
            {
                System.out.println("********* Inside target method!");

                AbstractInsnNode currentNode = null;
                AbstractInsnNode targetNode = null;

                @SuppressWarnings("unchecked")
                Iterator<AbstractInsnNode> iter = m.instructions.iterator();
                int index = -1;

                //Loop over the instruction set and find the instruction 21 which does the line before the ILOAD
                while (iter.hasNext())
                {
                    index++;
                    currentNode = iter.next();
                    System.out.println("********* index : " + index + " currentNode.getOpcode() = " + currentNode.getOpcode());
                    System.out.println(currentNode);

                    //Found it! save the index location of instruction ILOAD and the node for this instruction
                    if (currentNode.getOpcode() == 21)
                    {
                        targetNode = currentNode;
                        fdiv_index = index;

                    }
                }
                System.out.println("********* fdiv_index should be 2 -> " + fdiv_index);
                if (targetNode == null)
                {
                    System.out.println("Did not find all necessary target nodes! ABANDON CLASS!");
                    return bytes;
                }
                if (fdiv_index == -1)
                {
                    System.out.println("Did not find all necessary target nodes! ABANDON CLASS!");
                    return bytes;
                }
                InsnList toInject = new InsnList();
                this.addPlaceEvent(toInject, m, targetNode);
                /*toInject.add(new VarInsnNode(Opcodes.ALOAD, 0));//ALOAD 0
                toInject.add(new VarInsnNode(Opcodes.ALOAD, 1));//ALOAD 1
                toInject.add(new VarInsnNode(Opcodes.ILOAD, 2));//ILOAD 2
                toInject.add(new VarInsnNode(Opcodes.ILOAD, 3));//ILOAD 3
                toInject.add(new VarInsnNode(Opcodes.ILOAD, 4));//ILOAD 4
                toInject.add(new VarInsnNode(Opcodes.ILOAD, 5));//ILOAD 5
                toInject.add(new VarInsnNode(Opcodes.FLOAD, 6));//FLOAD 6
                toInject.add(new VarInsnNode(Opcodes.FLOAD, 7));//FLOAD 7
                toInject.add(new VarInsnNode(Opcodes.FLOAD, 8));//FLOAD 8
                toInject.add(new VarInsnNode(Opcodes.ILOAD, 9));//ILOAD 9
                toInject.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "net/minecraft/block/Block", "onBlockPlaced", "(Lnet/minecraft/world/World;IIIIFFFI)I"));//INVOKESPECIAL net/minecraft/block/Block.onBlockPlaced (Lnet/minecraft/world/World;IIIIFFFI)I

                m.instructions.insert(toInject);*/

                System.out.println("Patching Complete!");
                break;
            }
        }
        //ASM specific for cleaning up and returning the final bytes for JVM processing.
        ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
        classNode.accept(writer);
        return writer.toByteArray();
  }

以下是我尝试注入的方法:

public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
{
    int j1 = par9 & 3;
    byte b0 = 0;

    switch (par5)
    {
        case 0:
        case 1:
            b0 = 0;
            break;
        case 2:
        case 3:
            b0 = 8;
            break;
        case 4:
        case 5:
            b0 = 4;
    }

    return j1 | b0;
}

这是上述方法的字节码:

  // access flags 0x1
  public onBlockPlaced(Lnet/minecraft/world/World;IIIIFFFI)I
   L0
    LINENUMBER 33 L0
    ILOAD 9
    ICONST_3
    IAND
    ISTORE 10
   L1
    LINENUMBER 34 L1
    ICONST_0
    ISTORE 11
   L2
    LINENUMBER 36 L2
    ILOAD 5
    TABLESWITCH
      0: L3
      1: L3
      2: L4
      3: L4
      4: L5
      5: L5
      default: L6
   L3
    LINENUMBER 40 L3
   FRAME APPEND [I I]
    ICONST_0
    ISTORE 11
   L7
    LINENUMBER 41 L7
    GOTO L6
   L4
    LINENUMBER 44 L4
   FRAME SAME
    BIPUSH 8
    ISTORE 11
   L8
    LINENUMBER 45 L8
    GOTO L6
   L5
    LINENUMBER 48 L5
   FRAME SAME
    ICONST_4
    ISTORE 11
   L6
    LINENUMBER 51 L6
   FRAME SAME
    ILOAD 10
    ILOAD 11
    IOR
    IRETURN
   L9
    LOCALVARIABLE this Lnet/minecraft/block/BlockRotatedPillar; L0 L9 0
    LOCALVARIABLE par1World Lnet/minecraft/world/World; L0 L9 1
    LOCALVARIABLE par2 I L0 L9 2
    LOCALVARIABLE par3 I L0 L9 3
    LOCALVARIABLE par4 I L0 L9 4
    LOCALVARIABLE par5 I L0 L9 5
    LOCALVARIABLE par6 F L0 L9 6
    LOCALVARIABLE par7 F L0 L9 7
    LOCALVARIABLE par8 F L0 L9 8
    LOCALVARIABLE par9 I L0 L9 9
    LOCALVARIABLE j1 I L1 L9 10
    LOCALVARIABLE b0 B L2 L9 11
    MAXSTACK = 2
    MAXLOCALS = 12

我需要的行的说明:

     public void addPlaceEvent(InsnList iList, MethodNode mNode, AbstractInsnNode tNode)
     {
         //LINENUMBER 87 L0 (possibly unneeded)
         iList.add(new TypeInsnNode(Opcodes.NEW, "timeTraveler/mechanics/BlockPlaceEvent"));//NEW timeTraveler/mechanics/BlockPlaceEvent
         iList.add(new InsnNode(Opcodes.DUP));//DUP
         iList.add(new VarInsnNode(Opcodes.ALOAD, 0));//ALOAD 0
         iList.add(new VarInsnNode(Opcodes.ILOAD, 2));//ILOAD 2
         iList.add(new VarInsnNode(Opcodes.ILOAD, 3));//ILOAD 3
         iList.add(new VarInsnNode(Opcodes.ILOAD, 4));//ILOAD 4
         iList.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "timeTraveler/mechanics/BlockPlaceEvent", "<init>", "(Lnet/minecraft/block/Block;III)V"));//INVOKESPECIAL timeTraveler/mechanics/BlockPlaceEvent.<init> (Lnet/minecraft/block/Block;III)V
         iList.add(new VarInsnNode(Opcodes.ASTORE, 5));//ASTORE 5
         //L1 (possibly unneeded)
         //LINENUMBER 88 L1 (possibly unneeded)
         iList.add(new FieldInsnNode(Opcodes.GETSTATIC, "net/minecraftforge/common/MinecraftForge", "EVENT_BUS", "Lnet/minecraftforge/event/EventBus;"));//GETSTATIC net/minecraftforge/common/MinecraftForge.EVENT_BUS : Lnet/minecraftforge/event/EventBus;
         iList.add(new VarInsnNode(Opcodes.ALOAD, 5));//ALOAD 5
         iList.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraftforge/event/EventBus", "post", "(Lnet/minecraftforge/event/Event;)Z"));//INVOKEVIRTUAL net/minecraftforge/event/EventBus.post (Lnet/minecraftforge/event/Event;)Z
         mNode.instructions.insert(tNode, iList);
         //POP (possibly unneeded)
         //L2 (possibly unneeded)
     }
}

有关如何解决此问题的任何想法?

0 个答案:

没有答案