类加载机制
类加载
基本术语
类加载器
类加载器:通过一个类全限定名称来获取其二进制文件(.class)流的工具。
类加载器都是抽象类ClassLoader的子类
java类编译后的.class文件开头字节码是cafe babe ,字节码被ClassLoder加载到JVM中
Bootstrap ClassLoader 最顶层ClassLoader
即使一个ClassLoader继承了ClassLoader其父类也是AppClassLoader
JVM框架图
编译
1 javac TestHelloWorld.java反汇编生成字节码
1 javap -c TestHelloWorldJVM在执行
TestHelloWorld
之前会先解析class二进制内容,JVM执行的其实就是如上javap
命令生成的字节码。
ClassLoder
一切的Java类都必须经过JVM加载后才能运行,而ClassLoader
的主要作用就是Java类文件的加载。在JVM类加载器中最顶层的是Bootstrap ClassLoader(引导类加载器)
、Extension ClassLoader(扩展类加载器)
、App ClassLoader(系统类加载器)
,AppClassLoader
是默认的类加载器,如果类加载时我们不指定类加载器的情况下,默认会使用AppClassLoader
加载类,ClassLoader.getSystemClassLoader()
返回的系统类加载器也是AppClassLoader
。
获取类加载器时有时会返回一个null对象,可能是该类被JVM初始化是被
Bootstrap ClassLoader(引导类加载器)
加载(该类加载器实现于JVM层,采用C++编写,获取该类加载器加载的类的ClassLoader时会返回null
ClassLoader
类有如下核心方法:
loadClass
(加载指定的Java类)findClass
(查找指定的Java类)findLoadedClass
(查找JVM已经加载过的类)defineClass
(定义一个Java类)resolveClass
(链接指定的Java类)
类加载流程
ClassLoader
加载com.anbai.sec.classloader.TestHelloWorld
类重要流程如下:
- ClassLoader调用
public Class<?> loadClass(String name)
方法加载com.anbai.sec.classloader.TestHelloWorld
类。 - 调用
findLoadedClass
方法检查TestHelloWorld
类是否已经初始化,如果JVM已初始化过该类则直接返回类对象。 - 如果创建当前
ClassLoader
时传入了父类加载器(new ClassLoader(父类加载器)
)就使用父类加载器加载TestHelloWorld
类,否则使用JVM的Bootstrap ClassLoader
加载。 - 如果上一步无法加载
TestHelloWorld
类,那么调用自身的findClass
方法尝试加载TestHelloWorld
类。 - 如果当前的
ClassLoader
没有重写了findClass
方法,那么直接返回类加载失败异常。如果当前类重写了findClass
方法并通过传入的com.anbai.sec.classloader.TestHelloWorld
类名找到了对应的类字节码,那么应该调用defineClass
方法去JVM中注册该类。 - 如果调用loadClass的时候传入的
resolve
参数为true,那么还需要调用resolveClass
方法链接类,默认为false。 - 返回一个被JVM加载后的
java.lang.Class
类对象。
自定义ClassLoader
java.lang.ClassLoader
是所有的类加载器的父类,其子类加载器通过继承其并重写了findClass
方法实现了新的功能
因此我们也可以通过重写findClass
方法来自定义一个类加载器
自定义类demo.ClassloaderDemo.TestHelloWorld
1 | package demo.ClassLoaderDemo; |
自定义类加载器
1 | package demo.ClassLoaderDemo; |
利用自定义类加载器我们可以在webshell中实现加载并调用自己编译的类对象,比如本地命令执行漏洞调用自定义类字节码的native方法绕过RASP检测,也可以用于加密重要的Java类字节码(只能算弱加密了)。
URLClassLoader
URLClassLoader
继承了ClassLoader
,URLClassLoader
提供了加载远程资源的能力,在写漏洞利用的payload
或者webshell
的时候我们可以使用这个特性来加载远程的jar来实现远程的类方法调用。
TODO….
- 标题: 类加载机制
- 作者: Sl0th
- 创建于 : 2022-07-02 00:04:37
- 更新于 : 2024-11-11 18:23:06
- 链接: http://sl0th.top/2022/07/02/类加载机制/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。