基础概念
Java是一个依赖于JVM(Java虚拟机)实现的跨平台的开发语言。
Java程序在运行前需要先编译成.class文件,Java类初始化的时候会调用java.lang.ClassLoader加载类字节码。
Java类加载器(Java Classloader)是Java运行时环境(Java Runtime Environment)的一部分,负责动态加载Java类到Java虚拟机的内存空间中,用于加载系统、网络或者其他来源的类文件。
Java源代码通过javac编译器编译成类文件,然后JVM来执行类文件中的字节码来执行程序。
ClassLoader
ClassLoader的主要作用就是Java类文件的加载 。
ClassLoader顾名思义就是类加载器,它的作用是:
- 负责将Class加载到JVM中
- 审查每个类由谁加载(父优先的等级加载基址)
- 将Class字节码重新解析成JVM统一要求的格式对象
类的动态加载
动态加载类基础理解
Class.forName理解
显式加载(类的动态加载)
java反射
ClassLoader
隐式加载
类名.方法名()
new
常用的类动态加载方式:
// 反射加载TestHelloWorld示例
Class.forName("com.anbai.sec.classloader.TestHelloWorld");
// ClassLoader加载TestHelloWorld示例
this.getClass().getClassLoader().loadClass("com.anbai.sec.classloader.TestHelloWorld");
Class.forName(“类名”)默认会初始化被加载类的静态属性和方法,如果不希望初始化类可以使用Class.forName(“类名”, 是否初始化类, 类加载器),
而ClassLoader.loadClass默认不会初始化类方法。
自定义ClassLoader
总体流程就是:
1、继承ClassLoader类
2、覆盖findClass()方法
3、在findClass()方法中调用defineClass()方法
URLClassLoader
URLClassLoader继承了ClassLoader,URLClassLoader提供了加载远程资源的能力,在写漏洞利用的payload或者webshell的时候我们可以使用这个特性来加载远程的jar来实现远程的类方法调用。
URLClassLoader示例
EzClassLoader
@RequestMapping("/")
@ResponseBody
public String abc(@RequestParam(value = "name") String name) throws MalformedURLException, ClassNotFoundException {
if (checkExt(name)){
URL url = new URL(name);
URLClassLoader ucl = new URLClassLoader(new URL[]{url});
Class.forName("com.yyds.y4tacker",true,ucl);
}else {
return "Hacker?";
}}
这里checkExt会检查是否为jar的扩展,有两种方法绕过。一是是利用.war,二只只传根目录,它会自动寻找,本地测试如下: