当前位置: 首页 > news >正文

Java反序列化基础-类的动态加载

类加载器&双亲委派

什么是类加载器

  • 类加载器是一个负责加载器类的对象,用于实现类加载的过程中的加载这一步。
  • 每个Java类都有一个引用指向加载它的ClassLoader。而数组类是由JVM直接生成的(数组类没有对应的二进制字节流)

类加载器有哪些

JVM 中内置了三个重要的 ClassLoader:

  1. BootstrapClassLoader(启动类加载器):最顶层的加载类,由C++实现,通常表示为null,并且没有父级,主要用来加载JDK内部的核心类库,以及被-Xbootclasspath参数指定路径下的所有类。
  2. ExtensionClassLoader(扩展类加载器):主要负责 “%JRE_HOME%/lib/ext” 目录下的jar包和类以及被 “java.ext.dirs” 系统变量所指定路径下的所有类。
  3. AppClassLoader(应用程序类加载器):面向用户的加载器,负责加载应用类的path下的所有jar包和类。

还有一个是用户自定义类加载器:

  1. User ClassLoader

什么是双亲委派

当一个类加载器收到类加载器的请求的时候,它不会直接加载指定的类,而是把这个请求委托给自己的父加载器去加载器。只有父加载器无法加载这个类的时候,才会由当前这个加载器来负责类的加载。
双亲委派的好处就是一个类名只会被一个加载器加载
image.png

类加载不同代码的加载顺序

这里的代码块主要有以下四种:

  • 静态代码块:static{}
  • 构造代码块:{}
  • 无参构造器:ClassName()
  • 有参构造器:ClassName(String name)

实例化对象

  • Person.java:里面有静态代码块、构造代码块、无参构造器、有参构造器、静态成员变量、普通成员变量、静态方法。
  • Main.java:启动类

Person.java

package Class;public class Person {public static int statica;public int instancea;static {System.out.println("静态代码块");}Person(){System.out.println("无参构造器");}{System.out.println("构造代码块");}public Person(int instancea) {this.instancea = instancea;System.out.println("有参构造"+ this.instancea);}public static void staticAction(){System.out.println("静态方法");}
}

Main.java

package Class;public class Main {public static void main(String[] args) throws ClassNotFoundException{Person person = new Person();}
}

运行之后可以看见,调用的顺序是 :
静态代码块->构造代码块->无参构造器
image.png

调用静态方法

调用Person的静态方法
Main.java

package Class;public class Main {public static void main(String[] args) throws ClassNotFoundException{Person.staticAction();}
}

运行Main.java后,可以看见没有实例化对象会先调用:
静态代码块->静态方法
image.png

对静态成员变量赋值

Main.java

package Class;public class Main {public static void main(String[] args) throws ClassNotFoundException{Person.statica = 1;}
}

对静态成员变量赋值,也会调用静态代码块
image.png

使用class获取类

Main.java

package Class;public class Main {public static void main(String[] args) throws ClassNotFoundException{Class c = Person.class;}
}

运行后没有输出
image.png

使用forName获取类

获取类的class

需要在main方法上主动抛出异常
Main.java

package Class;public class Main {public static void main(String[] args) throws ClassNotFoundException{Class.forName("Class.Person");}
}

运行之后,可以看见调用了静态代码块
image.png

有true

Main.java

package Class;public class Main {public static void main(String[] args) throws ClassNotFoundException{Class.forName("Class.Person",true,ClassLoader.getSystemClassLoader());}
}

调用静态代码块
image.png

有false

Main.java

package Class;public class Main {public static void main(String[] args) throws ClassNotFoundException{Class.forName("Class.Person",false,ClassLoader.getSystemClassLoader());}
}

可以看见没有调用任何代码块
image.png

使用ClassLoader.loadClass() 获取类

Main.java

package Class;public class Main {public static void main(String[] args) throws Exception{ClassLoader cl = ClassLoader.getSystemClassLoader();Class<?> c = cl.loadClass("Class.Person");c.newInstance();// 初始化类}
}

添加了 c.newInstance()可以看见调用了以下,否则不调用
image.png

动态加载字节码

什么是字节码?

Java中的字节码,英文名为 “bytecode”,是Java代码编译后的中间代码格式。JVM(Java虚拟机)执行使用的一类指令,字节码通常存储在 .class文件中。

javac Hello.java

这里使用 javac命令编译我们写好的java文件,可以看见生成了一个 Hello.class文件,这个就是字节码文件
image.png
我们打开Hello.class文件看一下,可以看见都是一些看不懂的文件,这些是需要JVM去做的事情,才能执行
image.png
可以看见执行的时候,也会输出成功,因为java加载了字节码
image.png

类加载器的原理

注意:

复现的时候JDK版本不可以太高,否则会不一样

JDK下载:

https://blog.csdn.net/weixin_51959343/article/details/135921731

这里主要断点调试 loadClass 这一行
image.png
这个时候就会来到它的父类抽象类 ClassLoader,然后调用 loadClass()的两个参数
image.png
继续跟进来到了 AppClassLoader的loadClass()
image.png
走到下面是双亲委派的逻辑,调用父类的loadClass重复查询
image.png
这个时候又回到了 ClassLoader()类中
image.png
来到所属的 Launcher类中,Ctrl + H 可以看见,类的流程关系是:
ClassLoader —-> SecureClassLoader —> URLClassLoader —-> APPClassLoader
image.png
后面继续断点跟踪调试可以发现,函数调用顺序:
loadClass() -> findClass() -> defineClass()

任意类加载class文件

urlClassLoader

编译一个Calc类的字节码文件

package Class;import java.io.IOException;public class Calc {static {try {Runtime.getRuntime().exec("calc");} catch (IOException e) {throw new RuntimeException(e);}}
}

image.png
然后编写urlClassLoader的启动类

package Class;public class Main {public static void main(String[] args) throws Exception{URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file://编译后的class文件位置路径//")});Class<?> c = urlClassLoader.loadClass("Class.Calc"); c.newInstance();}
}

运行之后可以看见成功弹出了计算器
image.png
也可以使用http协议进行远程加载

package Class;public class Main {public static void main(String[] args) throws Exception{URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("http://localhost:8080")});Class<?> c = urlClassLoader.loadClass("Class.Calc"); c.newInstance();}
}

在字节码文件目录下开启http服务
image.png
运行之后可以看见弹出计算器
image.png
也可以使用jar,

  • 前面 jar:
  • 后面 xxx.jar!/
package Class;public class Main {public static void main(String[] args) throws Exception{URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("jar:http://localhost:8080/Calc.jar!/")});Class<?> c = urlClassLoader.loadClass("Class.Calc");c.newInstance();}
}

image.png
file协议同理

defineClass

也可以直接使用 defineClass方法加载恶意的class文件

package Class;public class Main {public static void main(String[] args) throws Exception{//获取ClassLoader类的系统类加载器赋值到c1变量ClassLoader cl = ClassLoader.getSystemClassLoader();//使用反射机制获取 ClassLoader 类的 defineClass 方法中的一些一些参数Method defineClassCalc = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);//设置权限为可访问defineClassCalc.setAccessible(true);//byte[]数组存储了,这个目录下的Calc.class字节码文件byte[] code = Files.readAllBytes(Paths.get(("E:\\语言学习\\java\\code\\Serialize1\\Serialize1\\out\\production\\Serialize1\\Class\\Calc.class")));//反射调用了之前获取到的 defineClass 方法,将字节码数组转换为 Class 对象赋值给cClass c = (Class) defineClassCalc.invoke(cl,"Class.Calc",code,0,code.length);//初始化 Class对象 cc.newInstance();}
}

image.png
缺点就是 defineClass方法是protected受保护的成员,在反序列化中难以反射调用

Unsafe

Unsafe 方法,是采用单例模式进行设计的,无法直接调用,所以需要反射

package Class;public class Main {public static void main(String[] args) throws Exception{//获取ClassLoader类的系统类加载器赋值到c1变量ClassLoader cl = ClassLoader.getSystemClassLoader();//获取 Unsafe的类Class<Unsafe> unsafeClass = Unsafe.class;//通过反射 获取 Unsafe类的 theUnsafe字段Field theUnsafeField = unsafeClass.getDeclaredField("theUnsafe");//设置访问权限为true,theUnsafe是prvate成员theUnsafeField.setAccessible(true);byte[] code = Files.readAllBytes(Paths.get(("E:\\语言学习\\java\\code\\Serialize1\\Serialize1\\out\\production\\Serialize1\\Class\\Calc.class")));//获取 Unsafe对象theUnsafeField方法静态的字段的值Unsafe unsafe = (Unsafe) theUnsafeField.get(null);Class c2 = unsafe.defineClass("Class.Calc", code, 0, code.length, cl, null);c2.newInstance();}
}

image.png

总结

总的来说就是加载器字节码之间怎么构造一条链子,底层之间产生的漏洞

相关文章:

Java反序列化基础-类的动态加载

类加载器&双亲委派 什么是类加载器 类加载器是一个负责加载器类的对象&#xff0c;用于实现类加载的过程中的加载这一步。每个Java类都有一个引用指向加载它的ClassLoader。而数组类是由JVM直接生成的&#xff08;数组类没有对应的二进制字节流&#xff09; 类加载器有哪…...

课堂行为动作识别数据集

一共8884张图片 xml .txt格式都有 Yolo可直接训练 已跑通 动作类别一共8类。 全部为教室监控真实照片&#xff0c;没有网络爬虫滥竽充数的图片&#xff0c;可直接用来训练。以上图片均一一手工标注&#xff0c;标签格式为VOC格式。适用于YOLO算法、SSD算法等各种目标检测算法…...

【数据库】MVCC

MVCC是一种用来解决读写冲突的无锁并发控制&#xff0c;也就是为事务分配单项增长的时间戳&#xff0c;为每个修改保存一个版本&#xff0c;版本与事务时间戳关联&#xff0c;读操作只读该事务开始前的数据库的快照 MVCC&#xff0c;全称Multi-Version Concurrency Control&am…...

快速排序题目SelectK问题

力扣75.颜色分类 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序排列。 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置的 sor…...

es6解构赋值

ES6解构赋值是一种简洁的为变量赋值的方式&#xff0c;它允许我们从数组或对象中提取值并赋给对应的变量。 解构赋值在ES6中被引入&#xff0c;主要目的是为了简化代码&#xff0c;提高代码的可读性。以下是解构赋值的基本用法&#xff1a; 数组解构&#xff1a;当我们需要从数…...

Jenkins上面使用pnpm打包

问题 前端也想用Jenkins的CI/CD工作流。 步骤 Jenkins安装NodeJS插件 安装完成&#xff0c;记得重启Jenkins。 全局配置nodejs Jenksinfile pipeline {agent anytools {nodejs "18.15.0"}stages {stage(Check tool version) {steps {sh node -vnpm -vnpm config…...

设计编程网站集:动物,昆虫,蚂蚁养殖笔记

入门指南 区分白蚁与蚂蚁 日常生活中&#xff0c;人们常常会把白蚁与蚂蚁搞混淆&#xff0c;其实这两者是有很大区别的&#xff0c;养殖方式差别也很大。白蚁主要食用木质纤维&#xff0c;会给家庭房屋带来较大危害&#xff0c;而蚂蚁主要采食甜食和蛋白质类食物&#xff0c;不…...

面经学习(众智宏图实习)

个人评价 难度还是有的&#xff0c;中等难度吧&#xff0c;可能是因为项目使用的是物流项目&#xff0c;该项目本来就比较庞大难度比较高&#xff0c;流的八股文我真的是一点不会&#xff0c;还需要加强&#xff0c;reidis的多路io复用模型没有深问&#xff0c;要是问了就寄了&…...

DataGrip2024安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 DataGrip是由JetBrains公司开发的一款强大的关系数据库集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为数据库开发人员和数据库管理员设计。它提供了一个统一的界面&#xff0c;用于管理和开发各种关系型数据库&#x…...

【InternLM 实战营第二期-笔记4】XTuner 微调个人小助手认知

书生浦语是上海人工智能实验室和商汤科技联合研发的一款大模型,很高兴能参与本次第二期训练营&#xff0c;我也将会通过笔记博客的方式记录学习的过程与遇到的问题&#xff0c;并为代码添加注释&#xff0c;希望可以帮助到你们。 记得点赞哟(๑ゝω╹๑) XTuner 微调个人小助手…...

<计算机网络自顶向下> CDN

视频服务挑战 规模性异构性&#xff1a;不同用户有不同的能力&#xff08;比如有线接入和移动用户&#xff1b;贷款丰富和受限用户&#xff09;解决方法是&#xff1a;分布式的应用层面的基础设施CDN 多媒体&#xff1a;视频 视频是固定速度显示的一系列图像的序列&#xff…...

【Git教程】(十二)工作流之项目设置 — 何时使用工作流,工作流的结构,项目设置概述、执行过程及其实现 ~

Git教程 工作流之项目设置 1️⃣ 何时使用工作流2️⃣ 工作流的结构3️⃣ 概述4️⃣ 使用要求5️⃣ 执行过程及其实现5.1 基于项目目录创建一个新的版本库5.2 以文件访问的方式共享版本库5.3 用 Git daemon 来共享版本库5.4 用 HTTP 协议来共享版本库5.5 用 SSH 协议来共享版…...

Java 排序算法

冒泡排序 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法&#xff0c;它通过重复地遍历要排序的数列&#xff0c;比较相邻元素的大小并交换位置&#xff0c;使得较大的元素逐渐向数列的末尾移动。 以下是Java实现的冒泡排序代码&#xff1a; public stat…...

【重磅更新】开源表单系统填鸭表单v5版发布!

亲爱的TDucker&#xff0c;你们好。 真诚感谢您对填鸭表单的关注与支持。今天我们将为您带来新版本的更新说明&#xff0c;以便您更好的使用我们的产品。 社区版版V5更新概览&#xff1a; ✅ 增加WebHook数据推送功能&#xff0c;集成TReport实现数据大屏展示。 ✅ 增加主题…...

保姆级教程 | Adobe Illustrator 中插入数学符号

背景 鉴于Adobe Illustrator作为比较专业的绘图/组图软件&#xff0c;我的论文数据作图都会选择先在origin中把原始数据绘制好&#xff0c;后都放入AI中细修。由于在作图过程中需要插入数学符号&#xff0c;但仿佛没有PowerPoint用起来那么熟悉&#xff0c;遂记录下。 步骤 …...

数据结构——双向循环链表

目录 前言 一、链表的分类 二、双向循环链表 2.1 开辟新的节点 2.2 链表初始化 2.3 打印链表 2.4 链表的尾插 2.5 链表的头插 2.6 链表的尾删 2.7 链表的头删 2.8 查找链表 2.9 在pos位置之后插入数据 2.10 删除pos位置的数据 三、完整代码实现 四、顺序表和双向…...

使用ZLMediaKit搭建服务器实现推流拉流

源码&#xff1a;https://gitee.com/xia-chu/ZLMediaKit?utm_sourcealading&utm_campaignrepo 文档&#xff1a;https://docs.zlmediakit.com/zh/tutorial/ 检查gcc版本gcc -v检查cmake是否安装cmake --version安装gitsudo apt-get install git按照文档进行克隆 # 国内用…...

【拦截器Interceptor】springboot拦截器的使用和原理

【拦截器Interceptor】springboot拦截器的使用和原理 【一】拦截器简介&#xff08;1&#xff09;简介【2】作用 【二】实现步骤【1】自定义拦截器&#xff0c;实现拦截器接口HandlerInterceptor【2】将拦截器添加到容器当中【3】配置拦截器的拦截规则【4】拦截器的执行顺序 【…...

Android12 user版本无法进入recovery问题

1.前言 之前Android9的时候公司自己写了一个简单的OTA在线升级&#xff0c;调用Recovery升级系统。后来Android12的时候想使用AB升级&#xff0c;发现我这套代码AB升级完成了之后&#xff0c;重启却无法切到B&#xff0c;所以造成升级一直是失败的。后来想着要不还是把AB关掉直…...

Android沙盒机制

Android沙盒机制 Android Q文件存储机制修改成了沙盒模式&#xff0c;应用只能访问自己沙盒下的文件和公共媒体文件 存储&#xff08;也就是write&#xff09;私有目录和公共媒体文件都不需要WRITE_EXTERNAL_STORAGE权限读取&#xff08;也就是read&#xff09;私有目录不需要…...

从癌症研究到企业风控:用Python实战Cox比例风险模型(附完整代码与数据)

从医学到商业&#xff1a;Python实战Cox风险模型的企业级应用 在医疗领域&#xff0c;我们关心患者存活时间&#xff1b;在商业世界&#xff0c;我们关注客户生命周期。看似迥异的场景背后&#xff0c;都隐藏着同一个数学工具的身影——Cox比例风险模型。这个诞生于1972年的生存…...

策略梯度定理实战解析:从蒙特卡洛回报到PyTorch梯度实现

1. 这不是数学课&#xff0c;是写给实战者的政策梯度定理手记你打开这篇文字的时候&#xff0c;大概率正卡在某个强化学习项目里&#xff1a;模型跑不通、梯度爆炸、训练曲线像心电图一样乱跳&#xff0c;或者更糟——明明代码和论文一模一样&#xff0c;但 reward 就是上不去。…...

开放-构建-创新-连接:AMD AI开发者日即将登陆上海

近日&#xff0c;AMD宣布其面向AI 开发者的年度技术盛会2026年AMD AI 开发者日 (AMD AI DevDay 2026) 将于 5 月 19 日在上海前滩香格里拉酒店举行&#xff0c;AMD 董事会主席兼首席执行官 Lisa Su 博士也将出席并发表演讲。 本着“开放-构建-创新-连接”的理念&#xff0c;本…...

Tinke完整技术指南:NDS游戏资源提取与逆向工程深度解析

Tinke完整技术指南&#xff1a;NDS游戏资源提取与逆向工程深度解析 【免费下载链接】tinke Viewer and editor for files of NDS games 项目地址: https://gitcode.com/gh_mirrors/ti/tinke Tinke是一款专业的任天堂DS&#xff08;NDS&#xff09;游戏资源提取与逆向工程…...

BrowserClaw:容器化浏览器自动化平台部署与爬虫实战指南

1. 项目概述&#xff1a;一个浏览器自动化与数据抓取的瑞士军刀最近在折腾一些数据采集和自动化测试的活儿&#xff0c;发现一个挺有意思的开源项目&#xff0c;叫BrowserClaw。这名字起得挺形象&#xff0c;“浏览器之爪”&#xff0c;一听就知道是跟浏览器自动化、网页抓取相…...

告别GUI!用RTKLIB的rnx2rtkp命令行工具批量处理GNSS数据(附VS2019编译避坑指南)

从GUI到命令行&#xff1a;RTKLIB高效数据处理全攻略 在GNSS数据处理领域&#xff0c;RTKLIB作为开源工具链的标杆&#xff0c;其图形界面rtkpost虽然直观易用&#xff0c;但在处理大批量数据时效率低下。本文将带您深入探索命令行工具rnx2rtkp的完整工作流&#xff0c;从编译避…...

告别信号失真!手把手教你理解5G基站RRU里的DPD黑科技(附FPGA实现思路)

告别信号失真&#xff01;手把手教你理解5G基站RRU里的DPD黑科技&#xff08;附FPGA实现思路&#xff09; 在5G基站射频单元&#xff08;RRU&#xff09;的调试现场&#xff0c;工程师们最常遇到的"拦路虎"之一就是功率放大器&#xff08;PA&#xff09;的非线性失真…...

国家中小学智慧教育平台电子课本下载工具:教育资源获取的完整解决方案

国家中小学智慧教育平台电子课本下载工具&#xff1a;教育资源获取的完整解决方案 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具&#xff0c;帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载&#xff0c;让您更方便地获取课本内…...

Token Plan 套餐怎么选,Taotoken 预付费模式下的成本控制实践

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Token Plan 套餐怎么选&#xff0c;Taotoken 预付费模式下的成本控制实践 对于有稳定大模型调用需求的开发者或团队而言&#xff0…...

HiveWE:基于C++20模块化架构的下一代魔兽争霸III地图创作引擎

HiveWE&#xff1a;基于C20模块化架构的下一代魔兽争霸III地图创作引擎 【免费下载链接】HiveWE A Warcraft III world editor. 项目地址: https://gitcode.com/gh_mirrors/hi/HiveWE HiveWE作为开源社区驱动的魔兽争霸III地图编辑器&#xff0c;通过现代C20模块化架构重…...