JavaSec基础 反射修改Final修饰的属性及绕过高版本反射限制

反射重拾

半年没碰java了

先写点基础回忆一下

反射弹计算器

public class Test {public static void main(String[] args) throws Exception {Class<?> clazz = Class.forName("java.lang.Runtime");clazz.getDeclaredMethod("exec", String.class).invoke(clazz.getDeclaredMethod("getRuntime").invoke(clazz),"calc");}
}
public class Test {public static void main(String[] args) throws Exception {Class.forName("java.lang.ProcessBuilder").getDeclaredMethod("start").invoke(Class.forName("java.lang.ProcessBuilder").getConstructor(String[].class).newInstance(new String[][]{{"calc"}}));}
}
import java.lang.reflect.Method;
import java.util.Map;public class Test {public static void main(String[] args) throws Exception {Class clazz = Class.forName("java.lang.ProcessImpl");Method start = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);start.setAccessible(true);start.invoke(clazz, new String[]{"calc"}, null, null, null, false);}
}

修改Final

步骤如下

获取字段 -> 修改修饰符 -> 修改值

MyClass

public class MyClass {private final int password = 114514;@Overridepublic String toString() {return "MyClass{" +"password='" + password + '\'' +'}';}
}

Test

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;public class Test {public static void main(String[] args) throws Exception {Class<?> clazz = Class.forName("MyClass");Field fieldPassword = clazz.getDeclaredField("password");fieldPassword.setAccessible(true);Field modifiers = Field.class.getDeclaredField("modifiers");modifiers.setAccessible(true);modifiers.setInt(fieldPassword,fieldPassword.getModifiers() & ~Modifier.FINAL);MyClass myClass = new MyClass();fieldPassword.set(myClass,1919810);System.out.println(myClass);// MyClass{password='114514'}System.out.println(fieldPassword.get(myClass)); // 1919810}
}

为什么修改了之后我们输出的仍然是原先的值呢?

这是因为java编译器对final修饰属性进行的内联优化 即编译时将final的值直接放到了引用他的地方,即使通过反射修改了该属性 也没啥用

java会对如下final修饰的类型进行优化

byte short int long float double boolean char LiteralString(直接双引号括起来的字符串)

new 的String比较特殊 可以被有效修改 其余类型的包装类也是如此

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;public class Test {public static void main(String[] args) throws Exception {Field fieldPassword = Class.forName("MyClass").getDeclaredField("password");Method getDeclaredFields0 = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);getDeclaredFields0.setAccessible(true);Field modifiers = null;Field[] fields = (Field[]) getDeclaredFields0.invoke(Field.class, false);for (Field f: fields){if (f.toString().contains("modifiers")) {modifiers = f;break;}}modifiers.setAccessible(true);int recoverNum = fieldPassword.getModifiers();modifiers.setInt(fieldPassword,0);MyClass myClass = new MyClass();System.out.println(myClass);fieldPassword.set(myClass,"1919810");modifiers.set(fieldPassword,recoverNum);System.out.println(myClass);System.out.println(fieldPassword.get(myClass));}
}

高版本下不能通过getDeclaredFiled获取Field的属性

但是可以通过getDeclaredFileds0来获得

这里没有考虑高版本绕过反射限制 采用的添加启动参数

--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED

后面学完绕过高版本反射限制之后会补充

绕过高版本反射限制

jdk 17 下运行

import java.lang.reflect.Method;
import java.util.Map;public class HighVersionBypass {public static void main(String[] args) throws Exception {Class clazz = Class.forName("java.lang.ProcessImpl");Method start = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);start.setAccessible(true);start.invoke(clazz, new String[]{"calc"}, null, null, null, false);}
}

Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make static java.lang.Process java.lang.ProcessImpl.start(java.lang.String[],java.util.Map,java.lang.String,java.lang.ProcessBuilder$Redirect[],boolean) throws java.io.IOException accessible: module java.base does not "opens java.lang" to unnamed module @3b07d329

可以通过Unsafe类进行反射

Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。但由于Unsafe类使Java语言拥有了类似C语言指针一样操作内存空间的能力,这无疑也增加了程序发生相关指针问题的风险。在程序中过度、不正确使用Unsafe类会使得程序出错的概率变大,使得Java这种安全的语言变得不再“安全”,因此对Unsafe的使用一定要慎重。

那么如何获得一个Unsafe对象呢

Unsafe提供静态方法getUnsafe获取Unsafe实例,当且仅当调用getUnsafe方法的类为引导类加载器所加载时才合法,否则抛出SecurityException异常

那么从getUnsafe方法的使用限制条件出发,通过Java命令行命令-Xbootclasspath/a把调用Unsafe相关方法的类A所在jar包路径追加到默认的bootstrap路径中,使得A被引导类加载器加载,从而通过Unsafe.getUnsafe方法安全的获取Unsafe实例。

挺麻烦 一般用反射

image-20240108230806895

Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe)field.get(null);

再看看setAccessible的实现

image-20240108224820204

传入true的时候会调用checkCanSetAccessible

跟进去 一路跟到

private boolean checkCanSetAccessible(Class<?> caller,Class<?> declaringClass,boolean throwExceptionIfDenied) {if (caller == MethodHandle.class) {throw new IllegalCallerException();   // should not happen}Module callerModule = caller.getModule();Module declaringModule = declaringClass.getModule();if (callerModule == declaringModule) return true;if (callerModule == Object.class.getModule()) return true;if (!declaringModule.isNamed()) return true;String pn = declaringClass.getPackageName();int modifiers;if (this instanceof Executable) {modifiers = ((Executable) this).getModifiers();} else {modifiers = ((Field) this).getModifiers();}// class is public and package is exported to callerboolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());if (isClassPublic && declaringModule.isExported(pn, callerModule)) {// member is publicif (Modifier.isPublic(modifiers)) {return true;}// member is protected-staticif (Modifier.isProtected(modifiers)&& Modifier.isStatic(modifiers)&& isSubclassOf(caller, declaringClass)) {return true;}}// package is open to callerif (declaringModule.isOpen(pn, callerModule)) {return true;}if (throwExceptionIfDenied) {// not accessibleString msg = "Unable to make ";if (this instanceof Field)msg += "field ";msg += this + " accessible: " + declaringModule + " does not \"";if (isClassPublic && Modifier.isPublic(modifiers))msg += "exports";elsemsg += "opens";msg += " " + pn + "\" to " + callerModule;InaccessibleObjectException e = new InaccessibleObjectException(msg);if (printStackTraceWhenAccessFails()) {e.printStackTrace(System.err);}throw e;}return false;}

image-20240108225324126

如果调用类和目标类是同一个module 则可以修改

我们可以通过Unsafe#getAndSetObject来修改module

image-20240108225609564

三个参数对应 操作对象 偏移 值

image-20240108230223185

也就是要修改当前的module 为java.base

我们可以通过Unsafe的staticFieldOffset 或 objectFieldOffset来查找偏移量

在此 我们需要将HighVersionBypass类的module属性改为java.base

此处的getAndSetObject可以用putObject替换

image-20240108233434581

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/609075.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springBoot-自动配置原理

以下笔记内容&#xff0c; 整理自B站黑马springBoot视频&#xff0c;抖音Holis 1、自动配置原理 1.收集Spring开发者的编程习惯&#xff0c;整理开发过程使用的常用技术列表一>(技术集A) 2.收集常用技术(技术集A)的使用参数&#xff0c;整理开发过程中每个技术的常用设置列表…

灵活轻巧的java接口自动化测试实战

前言 无论是自动化测试还是自动化部署&#xff0c;撸码肯定少不了&#xff0c;所以下面的基于java语言的接口自动化测试&#xff0c;要想在业务上实现接口自动化&#xff0c;前提是要有一定的java基础。 如果没有java基础&#xff0c;也没关系。这里小编也为大家提供了一套jav…

U盘、硬盘无法打开,修复RAW磁盘或分区,硬盘变成raw格式如何恢复,数据恢复

本文持续更新&#xff0c;针对遇到的数据丢失问题进行详细记录 磁盘变成RAW的可能原因 突然断电或关机文件系统丢失或损坏病毒或恶意软件感染坏扇区磁盘损坏 以下解决方案针对非病毒损坏 通过Windows自带的工具进行恢复&#xff08;CHKDSK命令&#xff09; 1.连接硬盘 2.…

springcloud bus消息总线

简介 Spring Cloud Bus 配合Spring Cloud Config 使用可以实现配置的动态刷新。 Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架&#xff0c;它整合了Java的事件处理机制和消息中间件的功能。Spring Clud Bus目前支持RabbitMQ和Kafka。 Spring C…

TDengine 被 Frost Sullivan 评为全球最佳工业数据管理解决方案

近日&#xff0c;TDengine 被国际知名咨询公司沙利文&#xff08;Frost & Sullivan&#xff09;评为全球最佳工业数据管理解决方案&#xff0c;赢得了 2023 年客户价值领导力奖&#xff08;Frost & Sullivan duoxie&#xff09;&#xff0c;该奖项重点关注引领行业创新…

这些开源自动化测试框架,会用等于白嫖一个w

作者&#xff1a;黑马测试 链接&#xff1a;https://www.zhihu.com/question/19923336/answer/2585952461 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 随着计算机技术人员的大量增加&#xff0c;通过编写代码来…

设计模式——工厂方法模式(Factory Method Pattern)

简单工厂模式 概述 说工厂方法模式之前&#xff0c;先说下简单工厂模式&#xff0c;简单工厂模式并不属于GoF 23个经典设计模式&#xff0c;但通常将它作为学习其他工厂模式的基础&#xff0c;它的设计思想很简单&#xff0c;其基本流程如下&#xff1a;首先将需要创建的各种不…

顺序栈之共享栈实现——C语言

参考书&#xff1a;数据结构教程 第5版 李葆春 P83 #include <stdio.h> #include <string.h> #include <stdlib.h>#define MaxSize 10/*共享栈*/ typedef struct {char data[MaxSize];int top1,top2,len; }DStack;/*初始化*/ void InitStack(DStack *s){s-…

【Huggingface】如何访问Huggingface,Huggingface镜像

镜像站&#xff1a; https://hf-mirror.com/本站域名 hf-mirror.com&#xff0c;用于镜像 huggingface.co 域名。 更多用法&#xff08;多线程加速等&#xff09;详见这篇文章。简介&#xff1a; 方法一&#xff1a;使用huggingface 官方提供的 huggingface-cli 命令行工具。…

解决不同请求需要的同一实体类参数不同(分组校验validation)

问题概述 新增目录是自动生成id&#xff0c;不需要id参数&#xff1b;更新目录需要id&#xff0c;不能为空 pom.xml中已有spring-boot-starter-validation依赖 <!--validation(完成属性限制&#xff0c;参数校验)--><dependency><groupId>org.springframew…

“揭秘性能测试工具:优化软件性能的关键秘籍“

性能测试工具的设计宗旨是为了模拟用户对软件应用程序或系统的各种操作&#xff0c;旨在评估关键的性能指标&#xff0c;包括响应时间、吞吐量、并发能力和资源利用率。 通过这些工具模拟的多用户环境&#xff0c;我们能够产生与实际工作负载相似的条件&#xff0c;并监测系统…

业界首款PCIe 4.0/5.0多通道融合接口SSD技术解读

之前小编写过一篇文章劝大家不要碰PCIe 5.0 SSD&#xff0c;详细内容&#xff0c;可以再回顾下&#xff1a; 扩展阅读&#xff1a;当下最好不要入坑PCIe 5.0 SSD 如果想要进一步了解PCIe 6.0&#xff0c;欢迎点击阅读&#xff1a; 浅析PCIe 6.0功能更新与实现的挑战 PCIe 6.…

pyqt调用UI和开启子进程

UI制作 qrc 注意调用UI前把样式表里绑定的资源(qrc)转换成py导入进去 xxx.qrc转xxx.py 两种方法 1命令 pyrcc5 -o icons_rc.py icons.qrc 2外部工具pyrcc 实参 -o $FileNameWithoutExtension$.py $FileNameWithoutExtension$.qrcsdz.qrc→→sdaz.py 在代码里写 import…

Influxdb2修改管理员密码

通过恢复管理员令牌来重置InfluxDB2管理员的密码 1.找到数据库的配置文件 一般为config.json 2.配置文件的的blod文件配置 3.在这个混合文本和二进制json文件中搜索已知的用户名或token之类的字符串。 例如&#xff1a; "id":"0bd73badf2941000","…

AI-数学-高中-3.二次函数的根的分布问题的解题方法

原作者学习视频&#xff1a;二次】3二次函数根分布问题&#xff08;中档&#xff09;_哔哩哔哩_bilibili 一、伟达定理&#xff08;根与0比较的二次函数&#xff09; 示例&#xff1a; 二、画图法&#xff1a; 1.开口方向的确定&#xff0c;有的示例可能存在向上、下两种情况…

Centos7 手动更改系统时间

文章目录 1.更改系统时间2.写入系统时间3.查看是否写入成功 1.更改系统时间 date -s "2017-12-18 09:40:00"2.写入系统时间 hwclock -w3.查看是否写入成功 timedatectl

初识硬件之三极管

1 什么是三极管 概述 三极管全称是“晶体三极管”&#xff0c;也被称作“晶体管”&#xff0c;是一种具有放大功能的半导体器件。通常指本征半导体三极管&#xff0c;即BJT管。 三极管封装 有插件和贴片之分 如下图左一和左二就是插件形式&#xff0c;上面的金属片和洞孔是…

服务器中了DevicData勒索病毒怎么处理

DevicData勒索病毒是最近一段时间非常流行的勒索病毒类型&#xff0c;有很多企业都不幸中招&#xff0c;给生产和经营带来了很大的影响。所以云天数据恢复中心决定就这种类型的勒索病毒&#xff0c;来和各位讲讲当服务器中了DevicData勒索病毒怎么处理。 特征 1&#xff0c;文件…

【C语言题解】 | 101. 对称二叉树

101. 对称二叉树 101. 对称二叉树代码 101. 对称二叉树 这个题目要求判断该二叉树是否为对称二叉树&#xff0c;此题与上一题&#xff0c;即 100. 相同的树 这个题有异曲同工之妙&#xff0c;故此题可借鉴上题。 我们先传入需要判断二叉树的根节点&#xff0c;通过isSameTree()…

EI级 | Matlab实现VMD-TCN-GRU变分模态分解结合时间卷积门控循环单元多变量光伏功率时间序列预测

EI级 | Matlab实现VMD-TCN-GRU变分模态分解结合时间卷积门控循环单元多变量光伏功率时间序列预测 目录 EI级 | Matlab实现VMD-TCN-GRU变分模态分解结合时间卷积门控循环单元多变量光伏功率时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.【EI级】Matlab实现…