Agent 内存马的攻防之道
字数 2109 2025-08-20 18:18:40
Agent 内存马的攻防之道 - 深入解析与实战指南
一、Java 内存马概述
Java 内存马主要分为两种形式:
- 创建 Java Web 组件(如 Controller、Servlet、Filter、Valve)并通过反射注册或替换
- 通过 Java Agent 技术修改关键类(如 Servlet)的代码
Agent 型内存马特点:
- 修改的类位置不固定
- 被修改的类不是纯粹的"内存"类
- 检测难度高于传统内存马
二、Java Agent 技术基础
1. 加载方式
- Agent_OnLoad:通过
-javaagent参数加载 - Agent_OnAttach:通过
VM.attach方法注入
2. 关键类与方法
Instrumentation接口redefineClasses:重定义类addTransformer+retransformClasses:添加转换器并重新转换类
3. JVM 类加载流程
-
正常类加载:
- 从本地 jar 包获取类字节码
- 经过
JvmtiClassFileLoadHookPoster转换 - 编译为
InstanceKlass
-
redefineClasses:
- 类来源更换为指定字节码
- 类加载流程与正常加载类似
-
retransformClasses:
- 根据
InstanceKlass重新生成类字节码 - 存入缓存
InstanceKlass._cached_class_file
- 根据
三、攻防对抗分析
1. 攻击方式
(1) 通过 redefineClasses
- 优点:直接有效
- 缺点:容易被防护模式检测到
(2) 通过 retransformClasses
- 优点:若攻击者 agent 在防御者之后注入,防御者无法获取修改后的字节码
- 缺点:需要先添加 reTransformer
2. 防御方式
(1) 防护模式
- 应用运行时加载检测 agent
- 添加 reTransformer 监控关键类
- 可检测到类被重新加载
(2) 临时检测模式
- 通过
VirtualMachine.attach加载检测 agent - 添加临时 reTransformer 获取类字节码
3. 攻防博弈场景
| 攻击方式 | 防御模式 | 检测结果 |
|---|---|---|
| redefineClasses | 防护模式 | 可检测 |
| retransformClasses | 防护模式 | 无法获取修改后字节码 |
| redefineClasses | 临时检测 | 可检测 |
| retransformClasses | 临时检测 | 可检测 |
四、高级攻击技术
1. 借尸还魂技术
原理:利用已有 agent 的 InstrumentationImpl 实例
实现步骤:
- 从内存解析
JvmtiEnv链 - 获取
_env_local_storage(_JPLISEnvironment) - 从中获取
InstrumentationImpl实例 - 使用
jobject转 Java 对象技术
关键代码:
// 获取对象地址
long address = unsafe.getLong(new Object[]{obj}, arrayBaseOffset);
// 从地址恢复对象
unsafe.putLong(array, arrayBaseOffset, jobjectAddr);
Object obj = array[0];
2. 无文件 Agent 注入
技术难点:
- 构造
JPLISAgent对象 - 获取
JavaVM实例(从libjvm.so的main_vm符号) - 获取
jmethodID(通过解析jobject)
实现方案:
- 使用
setHasRetransformableTransformers创建JvmtiEnv - 解析
jobject获取klass地址 - 通过方法参数数量定位
transformer方法
3. 隐蔽攻击技术
核心思想:确保攻击者的 jvmtiEnv 在链末尾
实现方法:
- 检查自身是否在链末尾
- 若不在,移动到末尾并设置清除标志
- 下次执行时结束链
代码片段:
if(!clearFlag){
long nextJvmti = getTheNextOfJvmtiEnv(ownJvmtiEnvAddr);
if (nextJvmti != 0){
// 从链中剔除自己的 jvmtiEnv
putLong(jvmtiPointer, nextJvmti);
// 将自己添加到链末尾
long lastJvmti = findTheLastJvmtiEnv();
setTheNextJvmti(lastJvmti, ownJvmtiEnvAddr);
clearFlag = true;
return null;
}
}
五、内存马实战
1. 传统 Agent 内存马
- 修改
javax.servlet.http.HttpServlet的service方法 - 拦截所有请求
2. 高级内存马特点
- 无文件落地
- 防御工具无法检测
- 修改后不会因防御扫描而失效
3. 防御建议
- 监控
addTransformer、retransformClasses、redefineClasses方法 - 定期检查关键类字节码
- 使用专业内存马检测工具
六、总结与展望
Java Agent 内存马技术不断发展:
- 从落地 Jar 到无文件注入
- 从简单修改到隐蔽攻击
- 攻防对抗日益复杂
未来方向:
- 更隐蔽的注入技术
- 对抗高级检测手段
- 跨平台兼容性解决方案
七、参考资源
- OpenJDK 源码
- Java Object Layout
- 基于 javaAgent 内存马检测查杀指南
- 如何优雅的注入 Java Agent 内存马
- Java 内存攻击技术漫谈
注:本文涉及技术仅供学习研究,请勿用于非法用途。实际应用中请遵守相关法律法规。