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

标签 java runtime classloader reverse-engineering

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

这是我的尝试:https://gist.github.com/MalikDz/944cae9c168fa05fbd0a

这里的输出(错误):https://gist.github.com/MalikDz/fdf20df16b951d41cb78

非常感谢!

最佳答案

您可以使用 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;
    }
}

要打包此类转储代理,您需要将这两个类打包并包含此代理的 MANIFEST.MF:

Manifest-Version: 1.0
PreMain-Class: ClassDumpAgent

要使用此代理运行应用程序,请使用如下命令行:

java -javaagent:cldumpagent.jar MyApplication

关于解决方案的一些评论:

  1. 这些类被转储到硬编码文件夹 (C:\TEMP\DUMP) 中,您可以 可能想改变这一点。
  2. 转换器将转储所有类,包括 JDK 运行时。您可能想要过滤转储哪些包。
  3. 小心逆向工程,在某些国家/地区这可能被视为非法。

巴里

关于java - 重写类加载器以获取每个加载的类字节和名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27115371/

相关文章:

java - 与用户创建一个集合 - 我的 javacode 可以吗?

java - 将数据 append 到同一文件

c# - 如何在没有JIT的情况下运行程序?

c# - 什么是 Type.GUID,它与 Type.Equals() 有什么关系?

java - 在 Java 中加载已编译的类并从文件反序列化它的实例

java - 用按钮替换 fragment

java - java中使用Graphics绘制线条

r - 使用 alpha 来减少 R 包 ggplot2 中的过度绘图时会出现显着的运行时膨胀

java - 配置 JBOss 缓存以在 JBoss 服务器 4.2.3.GA 上运行

java - Tomcat6 忽略 web-inf/lib