Java代码审计学习笔记之JAVA基础系列(二、反射机制)

0.什么是反射机制

Java的反射机制,意思是在运行状态中对于任意一个类都能得到他的所有属性和方法,但是前提是必须要能够得到该类的class对象。事实上,上一节学的ClassLoader就是将.class文件映射成JVM当中的class对象(java.lang.Class)。当得到class对象后,我们便可以通过该class对象去实例化目标类,调用类的方法等。

1.如何获得Class对象

获得某个目标类的Class对象的方法主要包括如下三种

  • 方法一:类名.class
public class ReflectTest {
    public  static void main(String argvs[]){
        Class myRuntime = java.lang.Runtime.class;
        System.out.println(myRuntime);
    }
}
  • 方法二:调用java.lang.Class的forName方法
public class ReflectTest {
    public  static void main(String argvs[]) throws ClassNotFoundException {
        Class myRuntime = java.lang.Class.forName("java.lang.Runtime");
        System.out.println(myRuntime);
    }
}
  • 方法三:通过classLoader加载类从而返回class对象
public class ReflectTest {
    public  static void main(String argvs[]) throws ClassNotFoundException {
        ReflectTest test = new ReflectTest();
        Class myRuntime = test.getClass().getClassLoader().loadClass("java.lang.Runtime");
        System.out.println(myRuntime);
    }
}

3.利用反射机制执行命令

通过上述操作可以获得某个想要类的class对象(java.lang.Class类)。java.lang.Class类中包含了许多方法。以下对部分常用方法进行简单罗列。

函数名 解释
getConstructor 获取类构造方法(不包含私有方法)
getDeclaredConstructor 获取类构造方法(包含私有方法)
getDeclaredConstructors 获取类的所有构造方法,返回一个Constructor数组
getDeclaredMethods 获取类所有的成员方法,返回一个Method数组
getDeclaredMethod 获取类指定的成员方法
getDeclaredFields 获取当前类的所有成员变量,返回一个Field数组
getDeclaredField 获取指定成员变量

反正只要是java代码审计教程,基本都要讲个反射机制调用Runtime类的exec方法执行命令,以下为使用反射机制调用exec方法的代码:

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

public class ReflectTest {
    public  static void main(String argvs[]) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
        Class myRuntime = java.lang.Class.forName("java.lang.Runtime"); //获取Runtime类的Class对象

        //获取构造方法
        java.lang.reflect.Constructor myRuntimeConstructor = myRuntime.getDeclaredConstructor();
        myRuntimeConstructor.setAccessible(true);

        //调用构造方法实例化一个Runtime对象
        Object myRuntimeInstance = myRuntimeConstructor.newInstance();

        //获取exec方法
        java.lang.reflect.Method myExec = myRuntime.getMethod("exec", String.class);

        //在实例化的Runtime对象中调用exec方法
        java.lang.Process process = (Process) myExec.invoke(myRuntimeInstance,"whoami");

        //读取命令执行结果
        java.io.InputStream in = process.getInputStream();
        java.io.BufferedReader br=new java.io.BufferedReader( new java.io.InputStreamReader(in,"UTF-8"));
        System.out.println(br.readLine());
    }
}

参考