动态附加Java代理不起作用

发布于 2025-01-24 23:54:42 字数 6276 浏览 5 评论 0原文

我为编码挑战编写了以下代码。该程序的目的是将程序启动后附加到另一个Java过程并加载仪器引擎。这通常是在Java中通过在您的代理JAR文件中实现AgentMain方法来完成的。我在下面的代码中生成了所有这些内容:

在运行玩具程序的JVM上看到错误,并且线索是由于某种原因认为代理类文件名是代理$ 1。我评论了我对字节带纸的使用情况,只是尝试使用内置库加载代理文件,但仍然失败。

heartbeat : 373 pid = 21992
heartbeat : 374 pid = 21992
Exception in thread "Attach Listener" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:491)
    at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:513)
Caused by: java.lang.NoClassDefFoundError: Agent$1
    at Agent.agentmain(Agent.java:8)
    ... 6 more
Caused by: java.lang.ClassNotFoundException: Agent$1
    ... 7 more
Agent failed to start!
import com.sun.tools.attach.VirtualMachine;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.implementation.FixedValue;

import java.io.*;
import java.lang.instrument.Instrumentation;

import static net.bytebuddy.matcher.ElementMatchers.named;

public class Thief {

    public static void main(String[] args) throws Exception {
        Thief thief = new Thief();

        VirtualMachine jvm = VirtualMachine.attach("21992");
        File agentFile = new File("agent.jar");
        jvm.loadAgent(agentFile.getAbsolutePath());

        //thief.guessSecurityCode("24472");
    }

    public String guessSecurityCode(final String pid) throws Exception {
        File jarFile = createAgent();
        ByteBuddyAgent.attach(jarFile, pid);
        return "0000";
    }

    private static String generateSimpleAgent2() {

        return  "import java.lang.instrument.ClassFileTransformer;" + "\n" +
                "import java.lang.instrument.Instrumentation;" + "\n" +
                "import java.security.ProtectionDomain;" + "\n" +
                "\n\n" +
                "public class Agent {" +"\n" +
                "    public static void agentmain(String argument, Instrumentation inst) {" +"\n" +
                "    }" +"\n" +
                "}" +"\n";
    }

    private static String generateSimpleAgent() {

        return  "import java.lang.instrument.ClassFileTransformer;" + "\n" +
                "import java.lang.instrument.Instrumentation;" + "\n" +
                "import java.security.ProtectionDomain;" + "\n" +
                "\n\n" +
                "public class Agent {" +"\n" +
                "    public static void agentmain(String argument, Instrumentation inst) {" +"\n" +
                "        inst.addTransformer(new ClassFileTransformer() {" +"\n" +
                "            @Override" +"\n" +
                "            public byte[] transform(" +"\n" +
                "                ClassLoader loader," +"\n" +
                "                String className," +"\n" +
                "                Class<?> classBeingRedefined," +"\n" +
                "                ProtectionDomain protectionDomain," +"\n" +
                "                byte[] classFileBuffer) {" +"\n" +
                "            System.out.println(\"transform on : \" +className);" +"\n" +
                "            return classFileBuffer;" +"\n" +
                "            }" +"\n" +
                "        });" +"\n" +
                "    }" +"\n" +
                "}" +"\n";
    }

    private static String generateAgentManifest() {
        return  String.join("\n", "Agent-Class: Agent",
                "Can-Retransform-Classes: true",
                "Can-Redefine-Classes: true",
                "Premain-Class: Agent"
        );
    }

    private static String generateAgentManifest2() {
        return  String.join("\n",
                "Manifest-Version: 1.0",
                "Agent-Class: Agent",
                "Permissions: all-permissions"
        );
    }

    private static String generateTransformer() {
        return String.join("\n",
                "import java.lang.instrument.ClassFileTransformer;",
                "import java.security.ProtectionDomain;",
                "import java.util.Arrays;",
                "public class Transformer implements ClassFileTransformer {",
                "    public byte[] transform(ClassLoader loader, String className, Class<?> cls, ProtectionDomain dom, byte[] buf) {",
                "        return null;",
                "    }",
                "}"
        );
    }

    private static void writeFile(String path, String data) throws IOException {
        final PrintWriter out = new PrintWriter(path);
        out.print(data);
        out.close();
    }

    private static void runCommand(String cmd) throws Exception {
        System.out.println("[commmand] " + cmd);
        String s;
        Process p = Runtime.getRuntime().exec(cmd);
        BufferedReader out = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while ((s = out.readLine()) != null) {
            System.out.println("[out] " + s);
        }
        out = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        while ((s = out.readLine()) != null) {
            System.out.println("[err] " + s);
        }
        p.waitFor();
        System.out.println("[exit status] " + p.exitValue());
        p.destroy();
    }

    private static File createAgent() throws Exception {
        writeFile("Agent.java", generateSimpleAgent2());
        writeFile("Transformer.java", generateTransformer());
        writeFile("manifest.mf", generateAgentManifest2());
        runCommand("javac Agent.java Transformer.java");
        runCommand("jar -cfm agent.jar manifest.mf Agent.class Transformer.class");
        return new File("agent.jar");
    }
}

有人知道我在这里做错了吗?

I wrote the following code for a coding challenge. The purpose of the program is to attach to another java process and load an instrumentation engine after the program has been started. This is usually done in Java by implementing an agentmain method in your agent jar file. I generate this all in the code below:

The error is seen on the JVM running the toy program and the clue is it thinks the Agent class file name is Agent$1 for some reason. I comment out my usage of ByteBuddy and just try to load the agent file using the built in libraries and it still fails.

heartbeat : 373 pid = 21992
heartbeat : 374 pid = 21992
Exception in thread "Attach Listener" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:491)
    at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:513)
Caused by: java.lang.NoClassDefFoundError: Agent$1
    at Agent.agentmain(Agent.java:8)
    ... 6 more
Caused by: java.lang.ClassNotFoundException: Agent$1
    ... 7 more
Agent failed to start!
import com.sun.tools.attach.VirtualMachine;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.implementation.FixedValue;

import java.io.*;
import java.lang.instrument.Instrumentation;

import static net.bytebuddy.matcher.ElementMatchers.named;

public class Thief {

    public static void main(String[] args) throws Exception {
        Thief thief = new Thief();

        VirtualMachine jvm = VirtualMachine.attach("21992");
        File agentFile = new File("agent.jar");
        jvm.loadAgent(agentFile.getAbsolutePath());

        //thief.guessSecurityCode("24472");
    }

    public String guessSecurityCode(final String pid) throws Exception {
        File jarFile = createAgent();
        ByteBuddyAgent.attach(jarFile, pid);
        return "0000";
    }

    private static String generateSimpleAgent2() {

        return  "import java.lang.instrument.ClassFileTransformer;" + "\n" +
                "import java.lang.instrument.Instrumentation;" + "\n" +
                "import java.security.ProtectionDomain;" + "\n" +
                "\n\n" +
                "public class Agent {" +"\n" +
                "    public static void agentmain(String argument, Instrumentation inst) {" +"\n" +
                "    }" +"\n" +
                "}" +"\n";
    }

    private static String generateSimpleAgent() {

        return  "import java.lang.instrument.ClassFileTransformer;" + "\n" +
                "import java.lang.instrument.Instrumentation;" + "\n" +
                "import java.security.ProtectionDomain;" + "\n" +
                "\n\n" +
                "public class Agent {" +"\n" +
                "    public static void agentmain(String argument, Instrumentation inst) {" +"\n" +
                "        inst.addTransformer(new ClassFileTransformer() {" +"\n" +
                "            @Override" +"\n" +
                "            public byte[] transform(" +"\n" +
                "                ClassLoader loader," +"\n" +
                "                String className," +"\n" +
                "                Class<?> classBeingRedefined," +"\n" +
                "                ProtectionDomain protectionDomain," +"\n" +
                "                byte[] classFileBuffer) {" +"\n" +
                "            System.out.println(\"transform on : \" +className);" +"\n" +
                "            return classFileBuffer;" +"\n" +
                "            }" +"\n" +
                "        });" +"\n" +
                "    }" +"\n" +
                "}" +"\n";
    }

    private static String generateAgentManifest() {
        return  String.join("\n", "Agent-Class: Agent",
                "Can-Retransform-Classes: true",
                "Can-Redefine-Classes: true",
                "Premain-Class: Agent"
        );
    }

    private static String generateAgentManifest2() {
        return  String.join("\n",
                "Manifest-Version: 1.0",
                "Agent-Class: Agent",
                "Permissions: all-permissions"
        );
    }

    private static String generateTransformer() {
        return String.join("\n",
                "import java.lang.instrument.ClassFileTransformer;",
                "import java.security.ProtectionDomain;",
                "import java.util.Arrays;",
                "public class Transformer implements ClassFileTransformer {",
                "    public byte[] transform(ClassLoader loader, String className, Class<?> cls, ProtectionDomain dom, byte[] buf) {",
                "        return null;",
                "    }",
                "}"
        );
    }

    private static void writeFile(String path, String data) throws IOException {
        final PrintWriter out = new PrintWriter(path);
        out.print(data);
        out.close();
    }

    private static void runCommand(String cmd) throws Exception {
        System.out.println("[commmand] " + cmd);
        String s;
        Process p = Runtime.getRuntime().exec(cmd);
        BufferedReader out = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while ((s = out.readLine()) != null) {
            System.out.println("[out] " + s);
        }
        out = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        while ((s = out.readLine()) != null) {
            System.out.println("[err] " + s);
        }
        p.waitFor();
        System.out.println("[exit status] " + p.exitValue());
        p.destroy();
    }

    private static File createAgent() throws Exception {
        writeFile("Agent.java", generateSimpleAgent2());
        writeFile("Transformer.java", generateTransformer());
        writeFile("manifest.mf", generateAgentManifest2());
        runCommand("javac Agent.java Transformer.java");
        runCommand("jar -cfm agent.jar manifest.mf Agent.class Transformer.class");
        return new File("agent.jar");
    }
}

Does anyone know what I'm doing wrong here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

痞味浪人 2025-01-31 23:54:42

使用generatesImpleagent2(),它起作用。它不会以相同的方式失败,就像您在 ewramner 的答案下的评论中所说的那样。那应该给你一个线索。此外,如果您只是阅读异常并相信它告诉您的内容,那么您就会知道该怎么做。再次:

java.lang.ClassNotFoundException: Agent$1

ie,generatesImpleagent()创建两个类文件,一个用于代理本身,一个用于匿名类。这正是 javac 有望做的。只需检查输出目录,您就会看到它。只需将丢失的类文件添加到JAR上并感到高兴:

runCommand("jar -cfm agent.jar manifest.mf Agent.class Agent$1.class Transformer.class");

现在,具有匿名变压器类的代理也可以工作。我测试了它。

With generateSimpleAgent2(), it works. It does not fail the same way, like you said in your comment under ewramner's answer. That should give you a clue. Furthermore, if you simply read the exception and believe what it is telling you, you know what to do. Again:

java.lang.ClassNotFoundException: Agent$1

I.e., generateSimpleAgent() creates two class files, one for the agent itself and one for its anonymous class. That is exactly what javac is expected to do. Just inspect the output directory, and you will see it. Simply add the missing class file to the JAR and be happy:

runCommand("jar -cfm agent.jar manifest.mf Agent.class Agent$1.class Transformer.class");

Now the agent with the anonymous transformer class also works. I tested it.

乖不如嘢 2025-01-31 23:54:42

代理$ 1是一个匿名类,因此它必须是您在这里创建的一个:

new ClassFileTransformer() { ... }

关于为什么找不到它以及如何修复它我不知道,也许您可​​以生成一个真实的名字命名在引用之前,上课?

Agent$1 is an anonymous class, so it must be the one you create here:

new ClassFileTransformer() { ... }

As for why it is not found and how you can fix it I don't know, perhaps you can generate a real named class for it before it is referenced?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文