通过Unsafe和反射执行命令

String cmd = "open /System/Applications/Calculator.app/";
        
int[] ineEmpty = {-1, -1, -1};
Class clazz = Class.forName("java.lang.UNIXProcess");
Unsafe unsafe = Utils.getUnsafe();
Object obj = unsafe.allocateInstance(clazz);
Field helperpath = clazz.getDeclaredField("helperpath");
helperpath.setAccessible(true);
Object path = helperpath.get(obj);
byte[] prog = "/bin/bash\u0000".getBytes();
String paramCmd = "-c\u0000" + cmd + "\u0000";
byte[] argBlock = paramCmd.getBytes();
int argc = 2;
Method exec = clazz.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, byte[].class, int.class, byte[].class, int[].class, boolean.class);
exec.setAccessible(true);
exec.invoke(obj, 2, path, prog, argBlock, argc, null, 0, null, ineEmpty, false);

代码功能概览

  • 这段代码尝试在 macOS 系统中调用 Calculator 应用程序 (Calculator.app)。
  • 它通过使用 Unsafe 类和 Java 反射来访问 Java 的内部 UNIXProcess 类,进而执行系统命令。
  • 该代码基本上是绕过了 Java 的安全机制,直接与操作系统交互。

代码分步解释

  1. 定义命令:

    String cmd = "open /System/Applications/Calculator.app/";
    
    • 这里定义了要执行的命令,打开 macOS 系统的计算器应用。
  2. 初始化参数:

    int[] ineEmpty = {-1, -1, -1};
    
    • ineEmpty 数组用于存储文件描述符,用于重定向输入/输出流。-1 表示不重定向。
  3. 获取 UNIXProcess 类:

    Class clazz = Class.forName("java.lang.UNIXProcess");
    
    • 使用 Class.forName() 方法获取 java.lang.UNIXProcess 类的引用,这是一个内部类,通常不应该在普通 Java 代码中被访问。
  4. 获取 Unsafe 实例:

    Unsafe unsafe = Utils.getUnsafe();
    
    • Unsafe 类允许直接操作内存和执行低级别操作。正常情况下,这个类是受保护的,但这里使用了某种方式(Utils.getUnsafe())绕过了限制。
  5. 实例化 UNIXProcess 对象:

    Object obj = unsafe.allocateInstance(clazz);
    
    • 通过 UnsafeallocateInstance 方法创建 UNIXProcess 的实例,而不调用其构造函数。
  6. 获取 helperpath 字段的值:

    Field helperpath = clazz.getDeclaredField("helperpath");
    helperpath.setAccessible(true);
    Object path = helperpath.get(obj);
    
    • 这里通过反射获取 UNIXProcess 类的 helperpath 字段。这个字段通常用于存储用于执行系统命令的帮助程序路径。
  7. 准备要执行的程序和参数:

    byte[] prog = "/bin/bash\u0000".getBytes();
    String paramCmd = "-c\u0000" + cmd + "\u0000";
    byte[] argBlock = paramCmd.getBytes();
    int argc = 2;
    
    • prog 是要执行的程序路径 (/bin/bash)。
    • paramCmd 是实际要传递给 bash 的参数,这里使用了 -c 来执行 cmd 中定义的命令。
  8. 获取 forkAndExec 方法并执行:

    Method exec = clazz.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, byte[].class, int.class, byte[].class, int[].class, boolean.class);
    exec.setAccessible(true);
    exec.invoke(obj, 2, path, prog, argBlock, argc, null, 0, null, ineEmpty, false);
    
    • 这里使用反射获取 UNIXProcessforkAndExec 方法,并通过 invoke 调用。
    • forkAndExec 是一个底层方法,用于在 Unix 系统中创建新的进程。这里实际执行的命令是 open /System/Applications/Calculator.app/

总结

  • 目的:这段代码的目的是在 macOS 系统上执行特定的 shell 命令,打开计算器应用程序。
  • 技术手段:利用 Java 反射和 Unsafe 类来绕过 Java 的安全限制,直接与操作系统交互。这种技术通常被认为是恶意行为的标志,因为它绕过了 Java 的安全沙箱。
  • 风险:这类代码有可能被恶意使用,运行未经授权的命令,特别是在用户不知情的情况下。因此,使用 Unsafe 类和反射需要极高的权限,并且可能会被现代 JVM 和安全策略所禁止。

**注意:**此代码片段可能在现代 Java 版本(如 17 或更高版本)中失效,因为 Java 在新版本中加强了安全防护措施,防止未经授权的反射访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值