Java 重写类加载器以获取每个加载的类字节和名称

Java 重写类加载器以获取每个加载的类字节和名称,java,runtime,classloader,reverse-engineering,Java,Runtime,Classloader,Reverse Engineering,是的,所以我要做的是获取jvm在运行时加载的每个类的类字节。插装在这种情况下不起作用,因为我试图加载的程序已经加密了他的类文件,并使用自己的类加载器加载它 以下是我的尝试: 此处显示输出(错误): 非常感谢 您可以使用Java代理来完成以下任务: 代理非常简单:它注册一个类转换器,可以访问字节码: import java.lang.instrument.Instrumentation; import java.lang.instrument.ClassFileTransformer; publ

是的,所以我要做的是获取jvm在运行时加载的每个类的类字节。插装在这种情况下不起作用,因为我试图加载的程序已经加密了他的类文件,并使用自己的类加载器加载它

以下是我的尝试:

此处显示输出(错误):


非常感谢

您可以使用Java代理来完成以下任务:

代理非常简单:它注册一个类转换器,可以访问字节码:

import java.lang.instrument.Instrumentation;
import java.lang.instrument.ClassFileTransformer;

public class ClassDumpAgent
{
    /**
     * This method is called before the application’s main-method is called, when
     * this agent is specified to the Java VM.
     **/
    public static void premain(String agentArgs, Instrumentation inst)
    {
        ClassFileTransformer trans = new ClassDumpTransformer();
        inst.addTransformer(trans);
    }
}
使用的ClassFileTransformer只是将包含字节码的字节数组转储到文件系统:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class ClassDumpTransformer implements ClassFileTransformer
{
    private File rootFolder = new File("C:\\temp\\dump");

    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, 
                            ProtectionDomain protectionDomain, byte[] classfileBuffer)
            throws IllegalClassFormatException
    {
        File dumpFile = new File(rootFolder,className+".class");
        dumpFile.getParentFile().mkdirs();
        try {
            FileOutputStream out = new FileOutputStream(dumpFile);
            try {
                out.write(classfileBuffer);
            } finally {
                out.close();
            }
        } catch (IOException e) {
            throw new IllegalClassFormatException(e.getMessage());
        }
        return classfileBuffer;
    }
}
要使用此代理运行应用程序,请使用如下命令行:

java -javaagent:cldumpagent.jar MyApplication
关于解决方案的一些评论:

  • 这些类被转储到硬编码文件夹(C:\TEMP\DUMP)中,您可以 我可能想改变这个
  • 转换器将转储所有类,包括JDK运行时。您可能需要筛选哪些包被转储
  • 小心逆向工程,在某些国家,这可能被视为非法

  • Barry

    有人知道吗?如果在命令行上指定了代理后,
    ClassLoader
    拒绝工作,只需稍后附加代理即可<代码>类加载器不会被询问他们是否喜欢
    指令插入
    ,因此他们无法阻止它。我不是故意粗鲁,但我在上面说过指令插入在这里不起作用。我也已经这样做了:。但是感谢您的尝试,您是否尝试过对正在执行解密的类加载器进行反编译?也许您可以反编译该类,添加一个方法来转储明文字节码?当您说“此处不起作用”时,您的意思是您不能使用代理,还是ClassFileTransformer仍然接收加密的字节?您是否尝试在Windows上转储该类?这可能会失败,因为Windows无法处理某些文件名,如CON、PRN、AUX、NUL等。一些模糊处理程序在诸如“AUX”之类的包中创建类,Windows无法保存这些类。要么在Unix上运行,要么在ClassDumpTransformer中添加一些转义逻辑……如果我没有弄错的话,您的类受到Allatori模糊器的保护。在引导过程中,它会检查是否有“-javaagent:”命令行参数,如果存在,它会简单地停止。为了解决这个问题,您可以反编译引导类,找到“-javaagent:”的(加密)字符串,并用一些随机字符替换.class文件中的该字符串。还要删除清单中的“Sealed:true”,以便可以从修改的类开始。最后,您应该能够从“java-javaagent:cldumpagent.jar-jar modified.jar-restarted”开始
    java -javaagent:cldumpagent.jar MyApplication