JAVA-Reflect

Fc04dB Lv4

# Java 反射

深入理解java反射 - 知乎

JAVA 安全基础(二)-- 反射机制 - 先知社区 (aliyun.com)

反射是 Java 的特征之一,是一种间接操作目标对象的机制,核心是 JVM 在运行状态的时候才动态加载类,对于任意一个类都能够知道这个类所有的属性和方法,并且对于任意一个对象,都能够调用它的方法 / 访问属性。这种动态获取信息以及动态调用对象方法的功能成为 Java 语言的反射机制。** 通过使用反射我们不仅可以获取到任何类的成员方法 (Methods)、成员变量 (Fields)、构造方法 (Constructors) 等信息,还可以动态创建 Java 类实例、调用任意的类方法、修改任意的类成员变量值等。** 反射使原生 java 变成动态编译

反射:将类的各个组成部分封装为其他对象,这就是反射机制。

1、可以在程序运行过程中,操作这些对象。

2、可以解耦,提高程序的可扩展性。

为什么用到反射:

从官方定义中可以找到,在运行时获得程序程序集中每一个类型的成员和成员的信息,从而动态的创建、修改、调用、获取其属性,而不需要事先知道运行的对象是谁。划重点:在运行时而不是编译时。(不改变原有代码逻辑,自行运行的时候动态创建和编译即可

# 反射获取 Class 类

Java 虽不像 PHP 那么灵活,但其提供的 “反射” 功能,也是可以提供⼀些动态特性。⽐如,这样⼀段代码,在你不知道传⼊的参数值的时候,你是不知道他的作⽤是什么的:

1
2
3
4
public void execute(String className, String methodName) throws Exception {
Class clazz = Class.forName(className);
clazz.getMethod(methodName).invoke(clazz.newInstance());
}

⼏个在反射⾥极为重要的⽅法:

  • 获取类的⽅法: forName
  • 实例化类对象的⽅法: newInstance
  • 获取函数的⽅法: getMethod
  • 执⾏函数的⽅法: invoke

基本上,这⼏个⽅法包揽了 Java 安全⾥各种和反射有关的 Payload。

forName 不是获取 “类” 的唯⼀途径,通常来说我们有如下三种⽅式获取⼀个 “类”,也就是 java.lang.Class 对象:

  • obj.getClass() 如果上下⽂中存在某个类的实例 obj ,那么我们可以直接通过 obj.getClass() 来获取它的类,但使用实例化对象的 getClass() 方法,需要本身创建一个对象,本身就没有了使用反射机制意义。
  • Test.class 如果你已经加载了某个类,只是想获取到它的 java.lang.Class 对象,那么就直接拿它的 class 属性即可。这个⽅法其实不属于反射。
  • Class.forName 如果你知道某个类的名字,想获取到这个类,就可以使⽤ forName 来获取
  • 通过类加载器 ClassLoader 获取类,但极少用到

image-20240828215845252

# 获取 Field 成员变量

Class 类中用于获取成员变量的方法

  • Field[] getFields() : 返回所有公共成员变量对象的数组
  • Field[] getDeclaredFields() : 返回所有成员变量对象的数组
  • Field getField(String name) : 返回单个公共成员变量对象
  • Field getDeclaredField(Stringname) : 返回单个成员变量对象

Field 类中用于创建对象的方法

  • Object get(Object obj) 获取值
  • void set(Object obj, Object value) : 赋值

image-20240828223322539

获取成员变量是为了获取值或赋值

image-20240828224644254

# 获取 Constructor 构造方法

Class 类中用于获取构造方法的方法

  • Constructor[] getConstructors() : 返回所有公共构造方法对象的数组
  • Constructor[] getDeclaredConstructors() : 返回所有构造方法对象的数组
  • Constructor getConstructor(Class.. parameterTypes) : 返回单个公共构造方法对象
  • Constructor getDeclaredConstructor(Class.. parameterTypes) : 返回单个构造方法对象

Constructor 类中用于创建对象的方法

  • T newInstance(0bject...initargs) : 根据指定的构造方法创建对象
  • setAccessible(boolean flag) : 设置为 true, 表示取消访问检查

image-20240829134559846

newInstance 方法:

  • newInstance 方法是 java.lang.reflect.Constructor 类的一个方法,用于创建新的类实例。
  • 它通过调用类的构造方法来实例化对象。
  • newInstance 方法通常用于动态创建对象,尤其是在反射时,允许在运行时通过 Constructor 对象调用类的构造方法。

setAccessible (true) 方法:

  • setAccessible 方法是 java.lang.reflect.AccessibleObject 类的一个方法,用于启用或禁用 Java 语言访问检查。
  • 当 setAccessible (true) 被调用时,表示反射对象在使用时取消了访问权限检查,可以访问类的私有成员。
  • 这通常用于访问那些受到访问控制限制的类的私有成员(字段、方法、构造方法等)。

image-20240829140946547

# 获取 Method 成员方法

Class 类中用于获取成员方法的方法

Method[] getMethods() : 返回所有公共成员方法对象的数组,包括继承的

Method[] getDeclaredMethods() : 返回所有成员方法对象的数组,不包括继承的

Method getMethod(String name, Class... parameterTypes) : 返回单个公共成员方法对象

Method getDeclaredMethod(String name,Class..parameterTypes) : 返回单个成员方法对象

Method 类中用于创建对象的方法

Object invoke(Object obj, Object... args) : 运行方法

参数一:用 obj 对象调用该方法

参数二:调用方法的传递的参数 (如果没有就不写)

返回值:方法的返回值 (如果没有就不写)

image-20240829144743476

image-20240829151206606

# 反射 - 命令执行

原型:java 自带包含有的 java.lang 中有对于本机控制台的调用方法

image-20240829153435355

如果是第三方 jar 包呢

  • 首先使用 Class.forName 获取 java.lang.Runtime 类
  • 通过 getMethods 获取该类包括继承公共成员方法,并遍历出来
1
2
3
4
5
6
7
8
9
10
// 使用 Class.forName 获取 java.lang.Runtime 类
Class aClass = Class.forName("java.lang.Runtime");

// 获取 Runtime 类的所有公共方法
Method[] methods = aClass.getMethods();

// 遍历所有方法并打印输出方法信息
for (Method me : methods) {
System.out.println(me);
}
  • 通过查询找到对应需要的成员方法
  • 根据成员方法的名称和参数,分别对应获取所需成员方法
  • 通过使用获取的方法依次调用执行

image-20240829154936606

# 不安全的反射

应用程序使用具有反射功能的外部输入来选择要使用的类或代码,可能被攻击者利用而输入或选择不正确的类或代码

1
2
3
public void ref(String name) throws Exception {
Class.forName(name);
}

如果用户可以控制 name 的输入,就有可能构建恶意代码造成严重的漏洞

后面应该就是反序列化了

  • Title: JAVA-Reflect
  • Author: Fc04dB
  • Created at : 2024-08-28 15:00:59
  • Updated at : 2024-08-29 16:18:50
  • Link: https://redefine.ohevan.com/2024/08/28/JAVA-Reflect/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments