通常我们想用一个类的时候,首先需要先调用import,而通过反射里面的forName可以直接调用该类

获取到类后,我们可以进一步的调用其属性、方法,也可先实例化后,在进行方法的调用

使用**newInstance()**可以调用无参构造函数

**newInstance()**可能会调用失败,原因可能是

  1. 你使用的类不是无参构造函数
  2. 你使用的可能是私有构造方法

使用 java.lang.Runtime举例

Class clazz = Class.forName("java.lang.Runtime");
clazz.getMethod("exec",String.class).invoke(clazz.newInstance(),"id");

这样直接进行调用会出现报错

image-20240217172415535

报错会告诉我们这个类不能使用私有方法

这涉及到了单列模式,Runtime是一个私有方法

为了我们能安全的使用这个函数,设计出单列模式,通过为Runtime创建一个公共方法的getRuntime来是实现调用这个函数

Class<?> clazz = CLass.forName("java.lang.Runtime");
clazz.getMethod("exec",String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz),"calc.exe");

image-20240217173207132

在这次使用我们用到了getMethodinvoke方法,在调用getMethod方法的时候,我们需要传给他你需要获取的参数类型的列表

image-20240217174133863

我们使用最简单的,也就是第一个,它只有一个参数,类型是String,所以我们使用

getMethod(“exec”, String.class) 来获取 Runtime.exec 方法。

invoke 的作用是执行方法,它的第一个参数是:

  • 如果这个方法是一个普通方法,那么第一个参数是类对象
  • 如果这个方法是一个静态方法,那么第一个参数是类

将上述payload拆解为

Class<?> clazz = Class.forName("java.lang.Runtime");
Method getRuntimeMethod = clazz.getMethod("getRuntime");
Method execMethod = clazz.getMethod("exec",String.class);
Object runtime = getRuntimeMethod.invoke(clazz);
execMethod.invoke(runtime,"calc.exe");

image-20240218140548270