Msmap AgentFileless深度解析:Windows与Linux无文件Java Agent注入完整指南
【免费下载链接】msmapMsmap is a Memory WebShell Generator.项目地址: https://gitcode.com/gh_mirrors/ms/msmap
Msmap 是一款开源的Java 内存马(Memory WebShell)生成器,其中的AgentFileless模式实现了真正的"无文件 Java Agent 注入":全程不需要在磁盘上放置 jar 包、不需要-javaagent启动参数,而是在运行时把 Instrumentation 代理对象直接构造在内存里,再重定义已加载的核心类,让 Tomcat 等 Java 容器"原地长出一个后门"。本文将带你彻底看懂 Msmap AgentFileless 在Windows 与 Linux两大平台上的实现原理与使用方法,面向新手、代码量极少 🚀
一、什么是"AgentFileless"无文件注入?
传统 Java 内存马的植入思路一般分两派:
| 派系 | 原理 | 局限性 |
|---|---|---|
| 进程内注入 | RCE 后直接操作容器内部结构(Valve / Filter / Listener 等) | 强依赖具体容器类型与版本,不够通用 |
| Java Agent 注入 | 借助 Instrumentation.redefineClasses 重定义已加载类 | 传统方式需要加载 agent(jar 文件 + 启动参数) |
AgentFileless 恰好取两者之长:
- 运行时在内存中"伪造"出一个合法的 Instrumentation 对象并 attach 到自身 JVM 进程;
- 用
redefineClasses替换已加载的javax.servlet.http.HttpServlet类; - 后门逻辑被埋进
service()方法入口,之后每个 HTTP 请求都会先经过后门判断。
📌 核心亮点:注入目标不是某个具体的 webapp,而是容器核心类HttpServlet。这意味着 Tomcat(及使用该 Servlet API 的容器)下的所有 Servlet 都受影响,注入点通用、覆盖面广,且全程不落盘、不重启。
相关源码位置(供进阶阅读):
- AgentFileless 注入器模板:
config/dependency.py(AGENTFILELESS 变量,内含 Windows/Linux 双平台逻辑) - 被后门化的 HttpServlet 模板:
gist/java/container/jdk/javax.py - 组装、编译、编码的生成器入口:
generator.py
二、三步走:从生成到生效的完整链路
- 生成注入器:执行一条命令(见第四节),
generator.py会写出target/AgentFileless.java,自动编译后把 class 字节码进行 Base64 编码,并同时产出shell.jsp/shell.jspx投递脚本(对应generator.py中的b64file()逻辑); - 投递到目标 JVM:把生成的 JSP 上传到目标站点并访问一次。JSP 内部定义了一个加载器类,负责把 Base64 解码、通过
ClassLoader.defineClass定义 AgentFileless 类并实例化; - 内存中自附加并重定义:AgentFileless 的静态构造块随即触发"获取 Unsafe → 开启自附加 → 获得 Instrumentation → redefineClasses(HttpServlet)",后门永久生效(直到 JVM 重启)。
三、核心原理:Windows 与 Linux 的两条不同路径
redefine()方法根据os.name自动分流,两个平台走的是完全不同的技术路线 👇
3.1 Windows:Unsafe 翻开关 + Attach API
- 打开自附加开关:JDK 默认
jdk.attach.allowAttachSelf=false,禁止进程 attach 自己。代码先setProperty,再用Unsafe.staticFieldOffset + putBoolean强制改写sun.tools.attach.HotSpotVirtualMachine.ALLOW_ATTACH_SELF静态字段为 true(enableAttachSelf); - 加载 attach 实现类:优先尝试从类路径加载
sun.tools.attach.WindowsVirtualMachine(有 tools.jar 时);找不到时,直接反序列化内置的字节码数组(defineClass(ByteBuffer))在内存中定义该类——依然不需要任何外部文件; - 完成注入:把目标类名
javax.servlet.http.HttpServlet和类字节码写入静态字段,并根据 x86/x64 设置pointerLength为 4/8,最后调用其work()方法。内部通过 JVM Attach 机制拿到 Instrumentation,执行redefineClasses完成替换。
3.2 Linux:/proc/self/mem 壳码 + JNI_GetCreatedJavaVMs
Linux 路线更"硬核"——完全绕开 Attach API,直接操作自身进程的内存:
- 解析
/proc/self/maps:找到libjava.so与libjvm.so的映射基址; - 解析 ELF 符号表:遍历
.symtab节区,定位Java_java_io_RandomAccessFile_length(当作一段可写的"临时执行区")和JNI_GetCreatedJavaVMs的真实地址; - 壳码替换执行:把一小段 x86_64 壳码(栈对齐 + 调用 JNI_GetCreatedJavaVMs)通过
/proc/self/mem写入前者所在内存并借道执行,拿到 JVMTI 环境指针后立即恢复原始字节,不留痕迹; - 伪造 InstrumentationImpl:用 Unsafe 分配 4096 字节伪造一个 JVMTI agent 结构体(在偏移 8 处写入 jvmtiEnv 指针),再反射调用
sun.instrument.InstrumentationImpl的私有构造器,得到一个"合法"的 Instrumentation 对象; - redefineClasses替换 HttpServlet,注入完成。
⚠️ Linux 实现依赖内存布局与符号表结构,因此 Msmap 默认支持Linux Tomcat 8/9,其他版本需按进阶指南自行适配;macOS 暂不支持。
四、快速上手:AgentFileless 生成器使用步骤
先获取项目(如需要 clone 仓库):
git clone https://gitcode.com/gh_mirrors/ms/msmap cd msmap python generator.py交互式菜单路径:Java → JDK → JavaX → 编码器 → WebShell 类型 → 密码;也支持命令行一步到位:
python generator.py Java JDK JavaX XOR AntSword passwd| 参数位 | 含义 | 可选项 |
|---|---|---|
| 1 | 语言 | Java |
| 2 | 容器 | JDK(AgentFileless 模式入口) |
| 3 | 组件 | JavaX(注入 HttpServlet) |
| 4 | 编码器 | RAW / Base64 / XOR / AES128 / RC4 |
| 5 | WebShell 类型 | CMD / AntSword / JSPJS / Godzilla / Behinder(随编码器而定) |
| 6 | 密码 | 任意字符串,需与客户端保持一致 |
进阶配置在config/environment.py中:
auto_build:自动调用 javac 编译b64_class:对类字节码做 Base64 编码generate_script:生成 shell.jsp / shell.jspx 投递脚本java_compiler_path:编译器绝对路径
各 WebShell 类型工作方式一览:
- CMD / SH:解码后按
os.name分别执行cmd.exe /c或/bin/sh -c(见gist/java/stub/cmd.py),一套代码通吃 Windows 与 Linux,用浏览器即可快速验证回显; - AntSword / JSPJS:payload 是 Base64 编码的 JSP,接收后在内存中
defineClass动态加载(见gist/java/stub/antsword.py),客户端选择对应编码(如xor_md5、rc_4_sha256、aes_128_ecb_pkcs7_padding_md5,脚本位于extend/AntSword/encoder/)即可连接; - Godzilla:AES128 编码对应 JAVA_AES_BASE64 类型,哥斯拉客户端直连。
五、AgentFileless 与传统注入方式对比
| 维度 | AgentFileless(本文方案) | 进程内注入(Valve/Filter 等) |
|---|---|---|
| 磁盘文件 | ❌ 无 jar、无 class 落盘 | ❌ 无 |
| 容器依赖 | 低(依赖 JDK 自身 attach/JNI 机制,跨容器通用) | 高(依赖具体容器内部结构) |
| 是否需要重启 | ❌ 热注入 | ❌ 热注入 |
| 存活周期 | JVM 进程存活期间 | JVM 进程存活期间 |
| 隐蔽性 | 无 jar、无-javaagent参数、无新类文件加载痕迹 | 视注入点而定 |
六、检测与防御要点(蓝队视角)
无文件注入的"痕迹"恰恰藏在运行时行为里:
- 内存扫描:枚举 JVM 中已加载类,对比
HttpServlet等方法体是否与标准库一致,识别异常 Base64 动态加载字节码的类; - 敏感行为监控:Windows 监控 jvm.dll 的异常自附加调用;Linux 监控
/proc/<pid>/mem的异常写入(本文 3.2 节的核心动作); - 类重定义审计:JVM 层面可开启对 redefineClasses 的校验与日志,核心类被重定义属于高危事件;
- 基线比对:定期比对内存中核心类字节码哈希与干净基线,发现篡改即可告警。
七、常见问题 FAQ
Q:需要什么 JDK 版本?注入逻辑依赖sun.misc.Unsafe、sun.instrument.InstrumentationImpl及 JDK attach 机制,主要面向 JDK 8/11 环境(Msmap 默认适配 Linux Tomcat 8/9);更高版本 JDK 限制更多,需要额外适配。
Q:服务器重启后门还在吗?不在。内存马只存活于 JVM 进程内存中,重启即消失——这也是"内存马"名称的由来。
Q:客户端类型和编码器必须严格对应吗?是的。如 AntSword 的 XOR 编码对应xor_md5,AES128 对应aes_128_ecb_pkcs7_padding_md5,Godzilla 的 AES128 对应JAVA_AES_BASE64,且密码必须与生成时设置的一致(选项大小写敏感)。
一句话总结:Msmap AgentFileless = "运行时自附加 + 内存类重定义",用一条命令同时打通了 Windows 与 Linux 平台的无文件 Java Agent 注入链路,是研究 Java 内存马原理与蓝队防御的优秀开源样本 🔍
【免费下载链接】msmapMsmap is a Memory WebShell Generator.项目地址: https://gitcode.com/gh_mirrors/ms/msmap
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考