【问题标题】:Overriding the classloader to get every loaded class bytes and name覆盖类加载器以获取每个加载的类字节和名称
【发布时间】:2015-01-22 18:53:20
【问题描述】:

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

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

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

非常感谢!

【问题讨论】:

  • 有人有想法吗?
  • 如果在命令行中指定了代理时ClassLoader 拒绝工作,只需稍后附加代理即可。 ClassLoaders 不被问是否喜欢Instrumentation,因此无法阻止。

标签: java runtime classloader reverse-engineering


【解决方案1】:

您可以使用 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. 小心逆向工程,在某些国家,这可能被认为是非法的。

巴里

【讨论】:

  • 不想粗鲁,但我在上面说过,仪器在这里不起作用。我也已经这样做了:gist.github.com/MalikDz/18e410aa4e30a3379603。但是感谢您尝试
  • 您是否尝试过反编译正在执行解密的ClassLoader?也许你可以反编译类,添加一个方法来转储明文字节码?
  • 当你说'doesnt work here'时,你的意思是你不能使用代理,还是ClassFileTransformer仍然接收到加密的字节?
  • 您是否要在 Windows 上转储类?这可能会失败,因为 Windows 无法处理某些文件名,例如 CON、PRN、AUX、NUL 等。一些混淆器在像“auX”这样的包中创建类,Windows 无法保存这些类。要么在 Unix 上运行,要么在 ClassDumpTransformer 中添加一些转义逻辑...
  • 如果我没记错的话,您的课程受到 Allatori 混淆器的保护。在引导过程中,它会检查是否存在“-javaagent:”命令行参数,如果存在,它就会停止。要解决此问题,您可以反编译 Boot 类,找到“-javaagent:”的(加密)字符串,然后将 .class 文件中的该字符串替换为一些随机字符。还要删除 MANIFEST 中的“Sealed: true”,以便您可以从修改后的类开始。最后你应该可以从'java -javaagent:cldumpagent.jar -jar modified.jar -restarted'开始
猜你喜欢
  • 1970-01-01
  • 2016-05-04
  • 1970-01-01
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
  • 1970-01-01
相关资源
最近更新 更多