Java中动态加载字节码的那些方法
时间:2021-08-11
本文章向大家介绍Java中动态加载字节码的那些方法,主要包括Java中动态加载字节码的那些方法使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
持续补充 ...
URLCLassLoader
ClassLoader#loader(URL[])远程加载class
URLCLassLoader
实际上是我们平时默认使用的AppClassLoader
的父类,所以,我们解释URLClassLoader
的工作过程实际上就是在解释默认的Java类加载器的工作流程。
java 对路径的处理:
- URL未以斜杠 / 结尾,则认为是一个JAR文件,使用 JarLoader 来寻找类,即为在Jar包中寻 找.class文件
- URL以斜杠 / 结尾,且协议名是 file ,则使用 FileLoader 来寻找类,即为在本地文件系统中寻 找.class文件
- URL以斜杠 / 结尾,且协议名不是 file ,则使用最基础的 Loader 来寻找类
也就是协议不是file且以 / 结尾,会使用Loader寻找类,最常见的是http协议。可以通过这种方法直接加载远端的class文件,所以如果我们控制了目标Java ClassLoader的基础路径为一个http服务器,即可RCE
CLassLoader#definClass 直接加载字节码
无论加载远程class还是本地class或者jar文件,调用过程都是下面三个方法:
- loadClass 的作用是从已加载的类缓存、父加载器等位置寻找类(这里实际上是双亲委派机 制),在前面没有找到的情况下,执行 findClass
- findClass 的作用是根据基础URL指定的方式来加载类的字节码,就像上一节中说到的,可能会在 本地文件系统、jar包或远程http服务器上读取字节码,然后交给
defineClass
- defineClass 的作用是处理前面传入的字节码,将其处理成真正的Java类
核心在defineClass,决定了如何将一段字节流转变成一个Java类,Java默认的ClassLoader#defineClass
是一个native方法,逻辑在JVM的C语言代码中。
我们无法直接外部调用这些方法来加载字节码,但是有一些库中包含了部分代码完成了这个过程,我们可以利用这些库达到目的。
加载方式一: TemplatesImpl
非常常用的Java反序列化利用链组成部分,poc:
public static void main(String[] args) throws Exception {
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] code = base64Decoder.decodeBuffer("");
TemplatesImpl obj = new TemplatesImpl();
Field f1 = obj.getClass().getDeclaredField("__bytecodes");
f1.setAccessible(true);
f1.set(obj, new byte[][]{code});
Field f2 = obj.getClass().getDeclaredField("__name");
f2.setAccessible(true);
f2.set(obj, "HelloTemplatesImpl");
Field f3 = obj.getClass().getDeclaredField("__tfactory");
f3.setAccessible(true);
f3.set(obj, new TransformerFactoryImpl());
obj.newTransformer();
}
注意:
设置了三个属性: _bytecodes 、 _name 和 _tfactory 。
- _bytecodes 是由字节码组成的数组;
- _name 可以是任意字符串,只要不为null即可;
- _tfactory 需要是一个 TransformerFactoryImpl 对象,因为
emplatesImpl#defineTransletClasses()
方法里有调用到tfactory.getExternalExtensionsMap()
,如果是null会出错。
另外,TemplatesImpl 中对加载的字节码是有一定要求的:这个字节码对应的类必须是 com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet
的子类。因此需要构造一个特殊的类。
加载方式二: BCELClassLoader
BCEL Classloader去哪了
在java 8u251前可用。
使用的是com.sun.org.apache.bcel.internal.util.ClassLoader;
// 原生字节码转BCEL
JavaClass cls = Repository.lookupClass(exp.class);
String code = Utility.encode(cls.getBytes(), true);
System.out.println(code);
// 加载
new ClassLoader().loadClass("exp").newInstance();
待补充...
原文地址:https://www.cnblogs.com/chengez/p/ClassLoader.html
- DataTable排序结果的纠正
- web框架
- java:利用xpath删除xml中的空节点
- java array to list
- Python之Dijango的“坑” hostname, aliases, ipaddrs = gethostbyaddr(name) UnicodeDecodeError: 'utf-8' cod
- nGrinder 简易使用教程
- UI设计高效学习网站&工具,来自学长的收藏夹哦
- 安装git出现templates not found的问题
- 时间戳 时间
- jenkins 设置 gitlab web hooks
- 测试流程?项目管理流程?
- 学web前端开发写给新手的建议,超实用!
- 价值22万的5字母域名sanwa.com被启用
- Django admin 一些有用的设置
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释