Java安全——JVM类加载器

本文详细介绍了Java中的ClassLoader,包括其加载流程、双亲委派机制、类关系及结构,以及自定义类加载器的实现。双亲委派机制确保了类加载的安全性,但在某些场景如Tomcat、OSGI和JDBC中被打破。此外,ClassLoader在网络安全领域,如冰蝎、蚁剑木马中用于加载加密字节码,以绕过静态和流量查杀。通过对ClassLoader的深入学习,可以更好地理解和应对Java安全问题。
摘要由CSDN通过智能技术生成

Java类加载机制在Java安全知识体系中有着非常重要的地位,早在之前分析Shiro反序列化漏洞利用,以及学习蚁剑Java马,都和Java ClassLoader打过交道。笔者打算从把ClassLoader的原理、使用场景、自定义方式等多个方面剖析类加载器在Java安全中设计到的知识。

0x01 ClassLoader 简介

Java语言需要把代码编译成class文件,才能用JVM加载执行,那么ClassLoader就是负责将class文件加载到内存,生成对应的类。

0x1 ClassLoader类加载流程

从上图中可以看出ClassLoader的主要职能,将字节流加载到内存,并使用defineClass加载到JVM生成可以被调用的类。Java源码编译之后生成对应的字节码,字节码的存储形式不只局限于文件,还可以使用访问数据库,URL请求的方式进行获取。存储的字节码还可以使用加密算法进行加密,提高存储安全性。

0x2 常见类加载方式

在之前的《Shiro 反序列化漏洞的一些思考》文章中有提到,两种常见的类加载方式。

1.Class.forName 不能加载原生类型,但其他类型都是支持的

2.Classloader.loadclass 不能加载原生类型和数组类型,其他类型都是支持的

这两种类加载方式虽然在实际过程中有着区别,但是其底层都是使用ClassLoader实现类加载机制的。ClassLoader的加载原理并不复杂,相对复杂的是ClassLoader逻辑父节点和真实父类概念上的理解。逻辑父节点是为了双亲委派机制设计的,这样在类加载的时候可以通过parent属性找到上级ClassLoader进行加载。

0x3 获取ClassLoader

ClassLoader loader = null;
loader = Thread.currentThread().getContextClassLoader();//通过当前线程获取
loader = ClassLoader.getSystemClassLoader();
loader = this.getClass().getClassLoader();//通过已加载class获取

大多数时候采用第一种方式获取ClassLoader,有时第三种方式会获取的值为null

0x02 ClassLoader 类关系及类结构

笔者本小节主要介绍ClassLoader的类结构以及类关系,ClassLoader在代码实现上是抽象类。这就意味着在程序中ClassLoader应该有很多的子类,那么ClassLoader及其子类中有什么关键类方法和类属性,在这一小节中进行介绍。

0x1 类关系

类关系问题第一次遇到还是在分析Shiro反序列化的时候,当时使用Tomcat容器启动的Shiro应用,在具体调试过程中发现WebappClassLoaderBase这个Classloader子类继承了URLClassLoader,一开始对于这种想象是不能够理解的。于是对ClassLoader、URLClassLoader、AppClassLoader等概念产生了混淆,笔者根据之前师傅们的研究总结了他们之间的关系,如下图所示

URLClassLoader是类加载机制双亲委托机制中最靠近子类的父类。ExtClassLoader、AppClassLoader、WebappClassLoaderBase等都继承自URLClassLoader。

public class Mytest{
    public static void main(String[] arg){
        ClassLoader classloader  = Mytest.class.getClassLoader(); 
        System.out.println(classloader); 
        ClassLoader classloader1 = classloader.getParent();   
        System.out.println(classloader1);
        ClassLoader classloader2 = classloader1.getParent();
        System.out.println(classloader2);
    }
}

运行结果如下所示,我们可以发现ExtClassLoader的父类加载器为null,原因是BootStrapClassLoader由C实现,无法载Java代码中体现其类之间的关系,但是在实际使用过程中ExtClassLoader确实会委托顶级类加载器BootStrapClassLoader进行类加载,代码实现如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值