2

Essentiellement, j'essaie d'ajouter un simple System.out.println("hey"); à la fin d'une méthode. J'ai utilisé l'API de l'arbre. Je ne garde cependant à obtenir cette erreur:Obtenir une erreur de vérification lorsque vous travaillez avec asm java

java.lang.VerifyError: Expecting a stackmap frame at branch target 38

Voici mon code:

public class MethodNodeCustom extends MethodNode { 

    public MethodNodeCustom(int paramInt, String paramString1, String paramString2, String paramString3, String[] paramArrayOfString) { 
     this(327680, paramInt, paramString1, paramString2, paramString3, paramArrayOfString); 
     return; 
    } 

    @SuppressWarnings({ "unchecked", "rawtypes" }) 
    public MethodNodeCustom(int paramInt1, int paramInt2, String paramString1, String paramString2, String paramString3, 
     String[] paramArrayOfString) { 
     super(paramInt1); 
     this.access = paramInt2; 
     this.name = paramString1; 
     this.desc = paramString2; 
     this.signature = paramString3; 
     this.exceptions = new ArrayList((paramArrayOfString == null) ? 0 : paramArrayOfString.length); 
     int i = ((paramInt2 & 0x400) != 0) ? 1 : 0; 
     if (i == 0) 
      this.localVariables = new ArrayList(5); 
     this.tryCatchBlocks = new ArrayList(); 
     if (paramArrayOfString != null) 
      this.exceptions.addAll(Arrays.asList(paramArrayOfString)); 
     this.instructions = new InsnList(); 
    } 
    @Override 
    public void visitEnd() { 
     AbstractInsnNode label = instructions.getLast(); 
     instructions.remove(instructions.getLast()); 
     instructions.remove(instructions.getLast()); 
     visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", Type.getDescriptor(PrintStream.class)); 
     visitLdcInsn("Cracked by damm ass pro skills"); 
     visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); 
     visitInsn(Opcodes.RETURN); 
     instructions.add(label); 

     super.visitEnd(); 
    } 
} 

Et voici mon nœud de classe:

public class ClassNodeCustom extends ClassNode { 
    public ClassNodeCustom() { 
     super(ASMContentHandler.ASM4); 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public MethodVisitor visitMethod(int paramInt, String paramString1, String paramString2, String paramString3, String[] paramArrayOfString) { 
     MethodNode localMethodNode = new MethodNodeCustom(paramInt, paramString1, paramString2, paramString3, paramArrayOfString); 
     this.methods.add(localMethodNode); 
     return localMethodNode; 
    } 
} 

Et voilà comment je "injecter" la code (je le charge directement du pot c'est pourquoi il utilise un zipFile)

InputStream in = zipFile.getInputStream(entry); 
ClassReader cr = new ClassReader(in); 
ClassNodeCustom node = new ClassNodeCustom(); 
cr.accept(node, 0); 
ClassWriter cw = new ClassWriter(0); 
node.accept(cw); 

Et comme je l'ai dit quand je l'ai exécuté, je reçois l'erreur de vérification, y-a-t-il un moyen pour moi de la résoudre ou une façon plus intelligente d'injecter ce code?

Répondre

5

Si vous ajoutez du code à la fin d'une méthode, vous l'ajoutez après sa dernière instruction qui est toujours une instruction goto, switch, throw ou return lors de la compilation de code Java. Même lors de la compilation d'une méthode sans une déclaration de retour explicite comme

void foo() { } 

vous compilez actully

void foo() { return; } 

où la déclaration finale est implicite. Avec vos ajouts, vous changez la méthode à

void foo() { 
    return; 
    System.out.println("hey"); 
} 

Un tel code injoignable est interdite par javac mais parfaitement légal dans le code d'octets. Pour le code inaccessible, il est cependant nécessaire que vous le préchargiez avec un stack map frame qui décrit l'état de la pile et le tableau de variables local à ce point. Il serait assez facile d'ajouter une description d'un cadre vide à ce stade, mais je suppose que vous voulez ajouter le code avant l'instruction de retour.

Pour implémenter cela, ASM offers an AdviceAdapter qui vous permet d'ajouter du code avant les instructions de retour. Autant que je sache, il n'y a rien de semblable pour l'API de l'arbre, mais vous pouvez simplement rechercher un nœud de retour dans la liste d'instructions de n'importe quelle méthode et ajouter le code avant cela.

+0

Ces lignes sont utilisées pour supprimer le retour; instruction et la dernière étiquette et que les readd AbstractInsnNode label = instructions.getLast(); instructions.remove (instructions.getLast()); instructions.remove (instructions.getLast()); – NacOJerk

+0

Je voudrais essayer que si – NacOJerk

+0

j'ai trouvé mon problème thx à votre pour une raison quelconque sur mes derniers tests je devais ajouter un code de certin à la fin de la méthode ainsi j'ai lu la dernière instruction de la méthode après l'enlever maintenant il semble comme je l'ai fait goofed et ajouté le code de retour deux fois. – NacOJerk