0x00 java反射的定义

java反射是java中的一个动态特性

反射可以用来干什么?

可以用来获取任何类的成员方法(Methods)、成员变量(Fields)、构造方法(Constructors)

可以动态创建java类实例、调用任意类方法、修改任意的类成员变量值。

综上反射体现了java语言的动态性。

0x01 具体实现

java.lang.Class(用来实现反射操作的对象),因而要想使用反射机制必须先获取到Class对象。

有以下几种获取一个类的Class对象:

  1. 类名.class 例如com.Security.class
  2. Class.forName(“com.Security”)
  3. classLoader.loadClass(“com.Security”)

获取数组类型的Class对象:

Class<?> doubleArray = Class.forName("[D");//相当于double[].class
Class<?> cStringArray = Class.forName("[[Ljava.lang.String;");// 相当于String[][].class

获取Runtime类Class对象代码片段

String className = "java.lang.Runtime";
Class runtimeClass1 = Class.forName(className);
Class runtimeClass2 = java.lang.Runtime.class;
Class runtimeClass3 = ClassLoader.getSystemClassLoader().loadClass(className);

反射调用内部类需要使用$代替.例如com.Security有一个Test的内部类那么就是com.Security$Test.

0x02 拓展利用

平常看到很多恶意类都使用java.lang.Runtime来执行系统命令。

因为这个类中存在exec方法可以执行本地命令。

然后在利用过程中就使用了反射调用Runtime类来执行命令。

如果不使用反射,执行本地命令:

// 输出命令执行结果
System.out.println(IOUtils.toString(Runtime.getRuntime().exec("whoami").getInputStream(), "UTF-8"));

在java中执行系统命令:

public class ExecTest {
    public static void main(String[] args) throws Exception{
        Runtime.getRuntime().exec("calc");
    }
}

对应的反射代码:

public class ExecTest {
    public static void main(String[] args) throws Exception{
        Object runtime = Class.forName("java.lang.Runtime").getMethod("getRuntime", new Class[]{}).invoke(null);
        //System.out.println(runtime.getClass().getName());
    Class.forName("java.lang.Runtime").getMethod("exec",String.class).invoke(runtime,"notepad.exe");
    }
}

对上面分解以下:

获取Runtime类对象
Class runtimeClass1 = Class.forName("java.lang.Runtime");
获取构造方法
Constructor constructor = runtimeClass1.getDeclaredConstructor();
constructor.setAccessible(true);
创建Runtime类示例
Object runtimeInstance = constructor.newInstance();
获取Runtime的exec(string cmd)方法
Method runtimeMethod = runtimeClass1.getMethod("exec",String.class);

具体实现流程如下:

反射获取Runtime类对象(Class.forName(“java.lang.Runtime”))

使用Runtime类的Class对象获取Runtime类的无参数构造方法getDeclaredConstructor()

参考链接

知识盒子java安全