Как найти имя вызова функции в файле класса с помощью ASM? - PullRequest
0 голосов
/ 22 мая 2018

Здесь у меня есть простая программа добавления Java

import java.util.Scanner;
public class Main {
    public static int add(int a, int b)
    {
        return a+b;
    }
    public static void main(String [] argv)
    {
        String a="Hello world";
    int b=499,c=599;
    int v= add(b,c);
    }
}

Теперь я использую программу манипуляции для манипулирования файлом класса программы Java.

package com.seriouscompany.program;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodNode;

public class Manipulator {

    //!!Change this to the path to your application's path!!
    public static final File PROGRAM_APPLICATION_JAR = new File("C:\\Users\\jayarasr\\Desktop\\SeriousProgram.jar");    
    private static List<ClassNode> classNodes = new ArrayList<>();

    public static void main(String[] args) throws FileNotFoundException {
        PrintStream o = new PrintStream(new File("A.txt"));
        System.setOut(o);
        classNodes = load(PROGRAM_APPLICATION_JAR);

        for(ClassNode classNode : classNodes) {
            System.out.println("------------------");
            System.out.println("Class Node :"+classNode.name);
            for(Object methodNodeObj : classNode.methods) {
                MethodNode methodNode = (MethodNode)methodNodeObj;
                System.out.println("Method Node  :"+methodNode.name);
             //   if(methodNode.name.toString()=="main") {}
                for(AbstractInsnNode abstractInsnNode : methodNode.instructions.toArray()) {
                    System.out.println("Abstract : "+abstractInsnNode.getOpcode());
                     if(abstractInsnNode instanceof LdcInsnNode) {
                        LdcInsnNode ldcInsn = (LdcInsnNode)abstractInsnNode;
                        System.out.println("Value :"+ldcInsn.cst);
                    }
                }
            }
        }

        save(new File(PROGRAM_APPLICATION_JAR.getAbsolutePath().replace(".jar", "dumped.jar")), classNodes);
    }

    public static void save(File jar, final List<ClassNode> nodes) {
        try {
            try(final JarOutputStream output = new JarOutputStream(new FileOutputStream(jar))) {
                for(ClassNode element : nodes) {
                    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                    output.putNextEntry(new JarEntry(element.name.replaceAll("\\.", "/") + ".class"));
                    output.write(writer.toByteArray());
                    output.closeEntry();
                }
            }
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    public static List<ClassNode> load(File file) {
        try {
            JarFile jar = new JarFile(file);
            List<ClassNode> list = new ArrayList<>();
            Enumeration<JarEntry> enumeration = jar.entries();
            while(enumeration.hasMoreElements()) {
                JarEntry next = enumeration.nextElement();
                if(next.getName().endsWith(".class")) {
                    ClassReader reader = new ClassReader(jar.getInputStream(next));
                    ClassNode node = new ClassNode();
                    reader.accept(node, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
                    list.add(node);
                }
            }
            jar.close();
            return list;
        } catch(IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Здесь я могунапечатать имя класса и имена методов и постоянные значения.Теперь мой вопрос заключается в том, как напечатать имена переменных, которые называются функциями name (вызвано одно) (я могу только найти коды операций). Я прочитал документацию ASM и попытался разобраться в этом, помогите мне найти вышеупомянутый запрос.

1 Ответ

0 голосов
/ 23 мая 2018

Чтобы получить имя вызываемого метода, вы должны проверить свойства MethodNodeInsn, который определяет владельца, имя метода и дескриптор любого вызываемого метода.Чтобы получить имена переменных, вам нужно прочитать таблицу локальных переменных что такое отладочная информация, которая не обязательно присутствует во всех классах.

...