Java 8 中使用反射进行命令执行的 5 个方法

这篇具有很好参考价值的文章主要介绍了Java 8 中使用反射进行命令执行的 5 个方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

今天在逛先知的时候看到了一篇文章:《探究使用反射进行除Runtime的命令执行方法》https://xz.aliyun.com/t/12446 其中大概讲了下命令执行的其他构造方式,但最后没有给出实例,所以我这里就简单研究了一下。

概述

在RASP等安全产品防护严密的现在,普通的寻找Runtime.getRuntime().exec(cmds)的调用已经成为了一件不现实的事情
同样的,在Java中盛行的反序列化漏洞中,如果将RCE的功能简单的通过Runtime.getRuntime().exec(cmds)这种结构来进行实现可能大概率也不能达到我们的目的,所以探索一下Runtime的底层实现,使用更加底层且复杂的调用来进行RCE功能的实现相对来说更加的可行

命令执行

文章接下里要用到反射技术,这里就不细讲了,可以看看其他的文章学习一下:https://www.yuque.com/sanqiushu-dsz56/efe3vx/hchx1p

命令执行 1:Runtime.getRuntime().exec()

// 命令执行 1 Runtime.getRuntime().exec()
Runtime.getRuntime().exec("open -a Calculator");

这个是大家所熟知的 java 中执行外部命令的方法。
首先我们跟踪Runtime执行命令的过程
Java 8 中使用反射进行命令执行的 5 个方法
exec() 函数在这里接收一个String类型的参数,调用 exec() 的另一个重载方法对参数进行处理,将其通过分隔符(默认为空格),将其封装成了数组对象
Java 8 中使用反射进行命令执行的 5 个方法
然后继续调用 exec() 重载方法,执行字符串数组类型的命令。
Java 8 中使用反射进行命令执行的 5 个方法
然后通过 ProcessBuilder()....start() 去执行命令了。那么我们自己也是可以通过反射去手动调用这个方法的,构造一下。

命令执行 2:ProcessBuilder().start()

// 命令执行 2 ProcessBuilder().start()
String[] cmd_array = new String[] {"open","-a","Calculator"};
Process process = new ProcessBuilder(cmd_array).start();

// 或者
new ProcessBuilder("calc.exe").start();  // 不能有参数

//当然还可以有其他的变体(通过反射):
Class pro = Class.forName("java.lang.ProcessBuilder");
((ProcessBuilder) pro.getConstructor(List.class).newInstance(Arrays.asList("calc.exe"))).start();

Class pro = Class.forName("java.lang.ProcessBuilder");
pro.getMethod("start").invoke(pro.getConstructor(List.class).newInstance(Arrays.asList("calc.exe")));

Class pro = Class.forName("java.lang.ProcessBuilder");
((ProcessBuilder) pro.getConstructor(String[].class).newInstance(new String[][]{{"calc.exe"}})).start();

Class pro = Class.forName("java.lang.ProcessBuilder");
pro.getMethod("start").invoke(pro.getConstructor(String[].class).newInstance(new String[][]{{"calc.exe"}}));

environment() 是设置环境遍历的函数,directory() 是设置执行目录的函数,然而我们都没传值,所以直接可以忽略。继续看 start() 函数
Java 8 中使用反射进行命令执行的 5 个方法

继续跟进,系统先进行了一番检查,然后新建了一个 SecurityManager 进行检测命令是否允许,但默认情况下 SecurityManager 是 null ,不进行检查。

Java 8 中使用反射进行命令执行的 5 个方法

然后就发现了系统调用的是 ProcessImpl.start() 进行命令执行。
Java 8 中使用反射进行命令执行的 5 个方法

那么到这里我们又可以自己构造了

命令执行 3 ProcessImpl.start()

// 命令执行 3 ProcessImpl.start()
String[] cmd_array = new String[] {"open","-a","Calculator"};
Method method_start = Class.forName("java.lang.ProcessImpl").getDeclaredMethod("start",String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);
method_start.setAccessible(true);
method_start.invoke(null, cmd_array, null, null, null, false);  // 静态方法不需要传入实例

继续跟踪 ProcessImpl.start() 方法,在经过一番准备之后,系统来到了 UNIXProcess() 构造方法(我是 linux 系统)(Windows 系统是调用 create() 方法)
Java 8 中使用反射进行命令执行的 5 个方法

那么是不是意味着我们又可以构造了

命令执行 4 UNIXProcess()

// 命令执行 4 UNIXProcess()
String[] cmd_array = new String[] {"open","-a","Calculator"};
Class<?> clazz = Class.forName("java.lang.UNIXProcess");
Method method_toCString = clazz.getDeclaredMethod("toCString", String.class);
method_toCString.setAccessible(true);
Constructor<?> constructor = clazz.getDeclaredConstructor(byte[].class, byte[].class, int.class, byte[].class,
        int.class, byte[].class, int[].class, boolean.class);
constructor.setAccessible(true);
constructor.newInstance((byte[])method_toCString.invoke(null, cmd_array[0]),
        new byte[] {45, 97, 0, 67, 97, 108, 99, 117, 108, 97, 116, 111, 114, 0} , 2, null, 0, null,
        new int[]{-1,-1,-1}, false);

Java 8 中使用反射进行命令执行的 5 个方法

那么继续往下看 UNIXProcess() 构造函数里面的代码
Java 8 中使用反射进行命令执行的 5 个方法

这里就一句话,调用 forkAndExec() 函数,那么我们可以手动调用这个函数,开始构造

命令执行 5: forkAndExec()

命令执行 5: forkAndExec()
String[] cmd_array = new String[] {"ls"};
Class<?> clazz = Class.forName("java.lang.UNIXProcess");
Method method_toCString = clazz.getDeclaredMethod("toCString", String.class);
method_toCString.setAccessible(true);
Constructor<?> constructor = clazz.getDeclaredConstructor(byte[].class, byte[].class, int.class, byte[].class,
        int.class, byte[].class, int[].class, boolean.class);
constructor.setAccessible(true);
Method method_forkAndExec = clazz.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class,
        byte[].class, int.class, byte[].class, int.class, byte[].class, int[].class, boolean.class);
method_forkAndExec.setAccessible(true);
Object o = constructor.newInstance((byte[])method_toCString.invoke(null, cmd_array[0]),
        new byte[] {} , 0, null, 0, null, new int[]{-1,-1,-1}, false);
int pid = (int)method_forkAndExec.invoke(o, 2, new byte[]{47, 76, 105, 98, 114, 97, 114, 121, 47, 74,
                97, 118, 97, 47, 74, 97, 118, 97, 86, 105, 114, 116, 117, 97, 108, 77, 97, 99, 104, 105, 110,
                101, 115, 47, 106, 100, 107, 49, 46, 56, 46, 48, 95, 49, 48, 49, 46, 106, 100, 107, 47, 67,
                111, 110, 116, 101, 110, 116, 115, 47, 72, 111, 109, 101, 47, 106, 114, 101, 47, 108, 105,
                98, 47, 106, 115, 112, 97, 119, 110, 104, 101, 108, 112, 101, 114, 0},
        new byte[]{111, 112, 101, 110, 0},
        new byte[]{45, 97, 0, 67, 97, 108, 99, 117, 108, 97, 116, 111, 114, 0}, 2, null, 0, null,
        new int[]{-1, -1, -1}, false);

不过这个有点牵强,因为需要先构造一个 UNIXProcess 的实例才行。
当然,我这传入的都是 byte[] ,只能用于验证,后续需要对照源码,将每个参数的生成给自动化才行。

Windows 的最后面的代码执行途径不太一样,但是同理构造即可。文章来源地址https://www.toymoban.com/news/detail-419154.html

到了这里,关于Java 8 中使用反射进行命令执行的 5 个方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 找不到mfc110.dll,无法执行代码,可以使用这3种方法进行修复

    Mfc110.dll是Microsoft Visual Studio 2012应用程序中使用的一个动态链接库,也称为Microsoft Foundation Classes应用程序框架库。这个库提供了一组可以用来创建Windows桌面应用程序的类和函数。当我们打开运行软件的时候出现找不到mfc110.dll,无法执行代码,可以使用这3种方法进行修复。  

    2024年02月11日
    浏览(36)
  • Java进程ProcessBuilder类的介绍及使用,ProcessBuilder调用外部程序执行shell命令Linux命令

    目录 ProcessBuilder类的介绍及使用 【前言】 【正文】 --构造方法-- --常用方法-- --使用技巧-- --调用本地Shell命令,实例-- 【总结】 【注意】         在做一个项目的时候需要用到运行时动态执行JAVA命令,一开始的思路是运行时生成bat脚本,然后通过Runtime类的exec方法之行

    2024年02月09日
    浏览(35)
  • java通过反射创建反射对象三种的方法

    目录 前言: 代码部分: computer类: 1.类名.class创建反射对象: 2.对象.getclass创建反射对象: 3.Class.forName(\\\"\\\")创建反射对象: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态

    2024年02月14日
    浏览(31)
  • 【Java】反射简介,利用反射打印一个类当中的构造函数,方法和属性。

       📝个人主页:哈__ 期待您的关注  我想要通过反射来打印如下效果的类信息。 Student类如下代码所示。  你是否有思路?如果你不了解反射的话,我来给大家简单的介绍一下反射的使用方法。 1、Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操

    2024年04月10日
    浏览(33)
  • Java中的反射(通过反射获取类的结构、invoke方法、获取注解)

    创建运行时类的对象是反射机制应用最多的地方。创建运行时类的对象有两种方式: 方式1:直接调用Class对象的newInstance()方法 要求: 1)类必须有一个无参数的构造器。 2)类的构造器的访问权限需要足够。 方式一的步骤 : 1)获取该类型的Class对象 2)调用Class对象的 new

    2024年02月04日
    浏览(35)
  • Linux:screen命令——命令行的窗口操作

    功能:管理命令行终端切换的软件,常用于远程连接Linux过程中,同时使用多个命令行窗口。在窗口运行中的程序, 即使断开ssh连接,程序也可以继续运行 。 1、 安装screen 2、 创建screen窗口 ,可以自取窗口名字,这里窗口被命名为demo 3、创建成功后,可以 在窗口中执行指令

    2024年02月02日
    浏览(41)
  • 使用Java的stream().filter方法进行数据筛选

    在Java中,Stream是一个非常强大的工具,用于处理集合数据。Stream提供了一系列的操作,使我们能够轻松地对数据进行筛选、转换和处理。其中, filter 方法是Stream中的一个关键操作,它允许我们根据给定的条件筛选出符合条件的元素。 在本文中,我们将深入探讨Java中 Stream

    2024年02月07日
    浏览(41)
  • Linux命令小技巧:显示文件指定行的内容

    工作中会有很多千奇百怪的需求,比如:如何在 Linux 命令行中快速找到某个文件的第 n 行?如何显示从第 x 行到第 y 行之间的内容? 想要实现以上效果,其实有很多办法可以实现。 比如,假如要显示第 13 行内容,可以使用 head 命令组合 tail 命令,如下: 例如: 输出: 或者

    2024年02月11日
    浏览(36)
  • 使用Java的stream().sorted方法对集合进行排序

    Java Stream API 提供了丰富的方法来对流中的元素进行处理和操作。其中, sorted() 方法用于对流中的元素进行排序。本文将深入探讨 sorted() 方法的用法、示例代码以及详细解释,以帮助您更好地理解和使用这个方法。 StreamT sorted() : 这个方法用于对流中的元素进行自然排序。要

    2024年02月04日
    浏览(45)
  • Java 中反射的概念、作用和特点,在什么情况下使用反射及使用实例

    反射(Reflection)是 Java 的一种特性,它可以让程序在运行时获取自身的信息,并且动态地操作类或对象的属性、方法和构造器等。通过反射功能,可以让我们在不知道具体类名的情况下,依然能够实例化对象,调用方法以及设置属性。 反射的作用有以下几点: 运行时探查类

    2024年02月06日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包