概述
前置
首先需要对Java中的反射机制有着基本的掌握
Class.forName("java.lang.Runtime")
获取对应类的构造方法 对于获取类的构造方法,主要可以通过getConstructor或者getDeclaredConstructor这两种方法来进行实现 两者的区别主要是前者不能够反射获取private修饰的构造方法,而后者能够获取 所以通常使用后者进行构造函数的获取,传入的参数就是对应构造方法的参数类 clazz.getDeclaredConstructor(type.class)
clazz.getConstructor(type.class)
反射获取成员变量 和构造方法类似的,存在有getField和getDeclaredField两个不同的获取方法,区别和构造函数类似 clazz.getField(name)
clazz.getDeclaredField(name)
反射获取类方法 同样具有getMethod和getDeclaredMethod两种 ............... 一个普通的命令执行是 Runtime.getRuntime().exec("calc");
如果使用反射机制 可以是
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(runtime, "calc");
或者是其他的一些使用反射机制的变形
command
跟踪Runtime
首先我们跟踪Runtime执行命令的过程 在这里接收一个String类型的参数,调用exec的另一个重在方法对参数进行处理,将其通过分隔符,将其封装成了数组对象(这里就是一个字符串) 之后通过参数是String[]类型的另一个重载方法,通过调用ProcessBuilder类的方法进行执行 在ProcessBuilder#start方法中,将命令传递给了ProcessImpl#start方法进行处理
windows
在windows中主要是在ProcessImpl的构造方法中调用了create方法 这个create方法是通过win32的方式创建了一个进程
linux
在linux下,在ProcessImpl#start的调用中将会创建一个UNIXProcess对象并返回 在UNIXProcess类的构造方法中,调用了forkAndExec这个native方法 创建了一个一个进程,并返回了对应进程的pid
构造命令执行
ProcessBuilder#start
在上面的流程分析中,知道了在Runtime.getRuntime().exec()方法调用的下一层就是使用ProcessBuilder#start方法 如果hook掉了我们可以通过使用ProcessBuilder类来进行命令执行的构造 new ProcessBuilder("calc").start();
或者使用反射的思路构造
//method_1
Class pro = Class.forName("java.lang.ProcessBuilder");
((ProcessBuilder) pro.getConstructor(List.class).newInstance(Arrays.asList("calc.exe"))).start();
//method_2
Class pro = Class.forName("java.lang.ProcessBuilder");
pro.getMethod("start").invoke(pro.getConstructor(List.class).newInstance(Arrays.asList("calc.exe")));
//method_3
Class pro = Class.forName("java.lang.ProcessBuilder");
((ProcessBuilder) pro.getConstructor(String[].class).newInstance(new String[][]{{"calc.exe"}})).start();
//method_4
Class pro = Class.forName("java.lang.ProcessBuilder");
pro.getMethod("start").invoke(pro.getConstructor(String[].class).newInstance(new String[][]{{"calc.exe"}}));
ProcessImpl
从上面的分析可以知道,在windows环境下的JDK ProcessImpl类的构造方法将会调用create方法执行native方法进行命令执行 所以我们只需要反射获取ProcessImpl类的构造方法并实例化就会执行我们的恶意逻辑 UNIXProcess
上面是针对windows的方式 针对linux,在前面的分析中知道主要是在其start方法中调用了UNIXProcess类的构造方法 执行forkAndExec这个native方法进行命令执行
other
甚至于,我们知道最后主要是在create方法(windows)、forkAndExec方法(linux)中执行命令,我们同样可以通过反射这两个方法进行命令执行。 精彩推荐
原文始发于微信公众号(FreeBuf):从Java源码来看Native命令执行方法
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论