是的,所以我试图做的是在运行时获取jvm加载的每个加载类的类字节。检测不适用于这种情况,因为 im 尝试加载的程序已加密了他的类文件并使用自己的类加载器加载它。
这是我的尝试: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;
}
}
若要打包此类转储代理,需要对这两个类进行 JAR 并包含一个 MANIFEST。此代理的 MF
:Manifest-Version: 1.0
PreMain-Class: ClassDumpAgent
若要使用此代理运行应用程序,请使用如下所示的命令行:
java -javaagent:cldumpagent.jar MyApplication
关于解决方案的一些评论:
- 这些类被转储到硬编码文件夹 (C:\TEMP\DUMP) 中,你可能想要更改此设置。
- 转换器将转储所有类,包括 JDK 运行时。您可能希望筛选转储的包。
- 小心逆向工程,在某些国家/地区,这可能被视为非法。
巴里