Runtime

Runtime中可以获取到Runtime实例有三种方法:

  1. private static Runtime currentRuntime = new Runtime();
  2. public static Runtime getRuntime()
  3. private Runtime() {}

package relfectDemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectRuntime {
    public String[] cmd = new String[]{"sh", "-c", "open /System/Applications/Calculator.app"};

    public void Runtime0() throws Exception{
        //利用私有变量生成实例 private static Runtime currentRuntime = new Runtime();
        Class clazz = Class.forName("java.lang.Runtime");
        Field field = clazz.getDeclaredField("currentRuntime");
        field.setAccessible(true);
        Runtime runtime = (Runtime) field.get("Runtime");
        Method method = clazz.getDeclaredMethod("exec", String[].class);
        method.invoke(runtime, new Object[]{this.cmd});
    }

    public void Runtime1() throws Exception{
        //利用     public static Runtime getRuntime() {
        //        return currentRuntime;
        //    }
        Class clazz = Class.forName("java.lang.Runtime");
        Method method = clazz.getDeclaredMethod("getRuntime");
        Runtime runtime = (Runtime) method.invoke(null);

        Method method1 = clazz.getDeclaredMethod("exec", String[].class);
        method1.invoke(runtime, new Object[]{this.cmd});
    }


    public void Runtime2() throws Exception{
        // 利用构造函数 private Runtime() {}
        Class clazz = Class.forName("java.lang.Runtime");
        Constructor constructor = clazz.getDeclaredConstructor(null);
        constructor.setAccessible(true);
        Runtime runtime = (Runtime) constructor.newInstance(null);
        Method method = clazz.getDeclaredMethod("exec", String[].class);
        method.invoke(runtime, new Object[]{this.cmd});
    }

ProcessBuilder

使用constructor初始化对象的时候,接收的参数是一个Object数组,所以需要new Object[]强制转换:

package relfectDemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

public class ReflectProcessBuilder {
    public String[] cmd = new String[]{"sh", "-c", "open /System/Applications/Calculator.app"};

    public void ReflectPB0() throws Exception{
        Class clazz = Class.forName("java.lang.ProcessBuilder");
        Constructor constructor = clazz.getConstructor(String[].class);

        //newInstance接收的是一个Object数组,需要转化一下
        ProcessBuilder pb = (ProcessBuilder) constructor.newInstance(new Object[]{this.cmd});

        Method method1 = clazz.getDeclaredMethod("start", null);
        method1.invoke(pb, null);
    }

    public void ReflectPB1() throws Exception{
        Class clazz = Class.forName("java.lang.ProcessBuilder");
        Constructor constructor = clazz.getConstructor(List.class); //当使用List类型的构造参数

        //newInstance接收的是一个Object数组,需要转化一下
        ProcessBuilder pb = (ProcessBuilder) constructor.newInstance(new Object[]{Arrays.asList(this.cmd)});

        Method method1 = clazz.getDeclaredMethod("start", null);
        method1.invoke(pb, null);
    }

    public static void main(String[] args) throws Exception {
        ReflectProcessBuilder reflectProcessBuilder =  new ReflectProcessBuilder();
//        reflectProcessBuilder.ReflectPB0();
        reflectProcessBuilder.ReflectPB1();

    }
}

ProcessImpl

package relfectDemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class ReflectProcessImpl {
    public String[] cmd = new String[]{"sh", "-c", "open /System/Applications/Calculator.app"};

    public void ReflectPI0() throws Exception{
        Class clazz = Class.forName("java.lang.ProcessImpl");
        Method method = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);
        method.setAccessible(true);
        Map<String, String> map = null;
        ProcessBuilder.Redirect[] redirect = null;
        String dir = ".";
        //第四个参数dir不能为空,为空会失败,表示在哪个路径下执行命令
        method.invoke(null, this.cmd, map, dir, redirect, true);

    }

    public static void main(String[] args) throws Exception{
        ReflectProcessImpl reflectProcess = new ReflectProcessImpl();
        reflectProcess.ReflectPI0();
    }
}

ForkAndExec

可以使用ASM执行,参考su18师傅的JNDI

结论

  • 反射执行命令的时候,首先需要明白如何获取实例的对象,见Runtime执行命令的三种方式
  • constructor初始化对象的时候,注意参数是Object数组,使用new Object[]强制转换

参考链接

⬆︎TOP