Agent 内存马禁止 Attach JVM

网络安全是数字时代的基石,但学习过程中必须严守法律红线 。‌

根据《中华人民共和国网络安全法》《数据安全法》等法律法规,任何未经授权的网络测试、数据访问或攻击行为均属违法 。本文所有技术讨论与实例均基于‌合法授权的靶场环境‌(如Metasploitable、DVWA、Hack The Box等),严禁将文中方法应用于真实系统或非授权场景
网络安全学习应以提升防御能力为目标,而非成为攻击工具。

写在前边:此文章现在看不懂没关系,后边的内容是重点,最后再回头看这个文章,会用茅塞顿开来形容。

一、相关名词解释

1、JVM

JVM 是 ‌Java Virtual Machine‌(Java 虚拟机)的缩写,它是一种‌抽象化的计算机‌,也是 Java 实现"一次编写,到处运行"的核心基石。

简单来说,JVM 就像是一个"翻译官"或"中间层"。我们写的 Java 源代码(.java 文件)会被编译成一种特殊的中间代码------字节码(.class 文件)。JVM 的工作就是读取并"翻译"这些字节码,把它们变成特定操作系统(Windows、Linux、macOS 等)能够理解和执行的机器指令。

JVM 的核心价值
  1. 跨平台性‌

    这是 JVM 最广为人知的特点。只要在不同的操作系统上安装了对应版本的 JVM,同一份 Java 字节码就可以不加修改地在任何平台上运行。开发者不需要为每个操作系统单独编译一份程序。

  2. 自动内存管理(垃圾回收)‌

    JVM 会自动管理内存的分配和回收,程序员不再需要手动释放内存,大大降低了内存泄漏和程序崩溃的风险。JVM 提供了多种垃圾回收算法(如 Serial GC、Parallel GC、G1 GC、ZGC 等),可以根据不同场景灵活选择。

  3. 安全沙箱‌

    JVM 为 Java 程序提供了一个受控的运行环境,能够有效隔离恶意代码,防止其损害底层操作系统。

    JVM 的核心组成部分

JVM 的内部结构

JVM 的内部结构主要包含以下几个关键模块:

组件 作用
类加载器(Class Loader)‌ 负责查找并加载 .class 字节码文件到 JVM 内存中
运行时数据区‌ JVM 的内存管理区域,包含堆(存放对象)、方法区(存放类元数据)、虚拟机栈、程序计数器、本地方法栈
执行引擎‌ 负责解释或编译执行字节码,包含解释器和 JIT 即时编译器(将热点代码编译成本地机器码以提升性能)
本地方法接口(JNI)‌ 允许 Java 调用 C/C++ 等语言编写的本地方法库
JVM、JRE、JDK 的关系

这三者经常被放在一起提及,它们的包含关系如下:

‌JVM‌:Java 虚拟机本身,负责执行字节码。

‌JRE‌(Java Runtime Environment):Java 运行环境,包含 ‌JVM‌ + Java 核心类库,是运行 Java 程序的必备条件。

‌JDK‌(Java Development Kit):Java 开发工具包,包含 ‌JRE‌ + 开发工具(如编译工具 javac、调试工具等),是开发 Java 程序的必备条件。

可以这样理解:‌JDK 是工具箱,JRE 是运行平台,JVM 则是这个平台最核心的发动机。

2、 ‌Attach

Java 的 Attach 机制,是 JDK 提供的一套允许外部进程动态连接到正在运行的 JVM 并注入代理程序的技术方案。它解决了 Java Agent 只能在 JVM 启动时通过 -javaagent 参数加载的限制,让开发者可以在程序运行期间随时进行诊断、监控和调试。

核心 API

Attach API 不是 Java 的标准 API,而是 Sun 公司提供的一套扩展 API,位于 com.sun.tools.attach 包中,主要包含两个类:

类名 作用
VirtualMachine 代表一个目标 JVM,提供 JVM 枚举、Attach 动作(连接)、加载代理、Detach 动作(断开连接)等核心操作
VirtualMachineDescriptor 描述虚拟机的容器类,配合 VirtualMachine 完成各种功能,如列出所有正在运行的 JVM 进程
工作流程

Attach 机制的运行流程大致分为以下几个步骤:

  1. 发现目标 JVM ‌:Attach 进程首先需要找到目标 JVM。这通常通过操作系统的进程列表来实现,jps 命令就是基于这个原理工作的。
  2. 建立连接 ‌:Attach 进程使用 Attach API 向目标 JVM 发送 Attach 请求。这个请求实际上是一个‌本地 Socket 连接‌,目标 JVM 会监听特定的 Socket 地址来接收请求。
  3. 加载 Agent ‌:目标 JVM 接收到 Attach 请求后,会加载一个特殊的 Agent,这个 Agent 负责处理 Attach 进程发送的各种命令。在 Linux/Unix 系统上通常是 sun.tools.attach.BsdVirtualMachine,在 Windows 系统上则是 sun.tools.attach.WindowsVirtualMachine
  4. 执行命令‌:Attach 进程通过 Agent 向目标 JVM 发送各种命令,例如加载 JDWP Agent、获取 JVM 信息、执行线程转储等。
  5. 触发 agentmain ‌:如果 Attach 进程请求加载自定义的 Agent JAR 包,目标 JVM 会执行该 JAR 包中指定的 agentmain 方法,从而完成字节码增强、类重定义等操作。
底层原理

Attach 机制的实现依赖于底层的操作系统 API。例如在 Linux 上,它使用 ptrace 系统调用来访问目标进程的内存空间。当外部进程发起 Attach 请求时,操作系统层面的信号机制会通知目标 JVM,目标 JVM 内部的 ‌Attach Listener‌ 线程会被唤醒并处理后续命令。

与 premain 的对比

Java Agent 有两种加载方式,Attach 机制对应的是动态加载模式:

对比维度 premain(静态加载) agentmain(动态加载)
加载时机 JVM 启动时,在应用程序 main 方法执行之前 JVM 运行期间,随时可以触发
启动方式 通过 -javaagent 参数指定 通过 Attach API 动态附着
典型场景 APM 监控探针、代码覆盖率工具 远程调试、线上诊断(Arthas)、热部署
是否需要重启 需要重启应用 不需要重启应用
主要应用场景

Attach 机制凭借"无需重启"的优势,被广泛应用于以下场景:

  • 远程调试‌:通过动态加载 JDWP Agent,实现本地 IDE 对远端服务器程序的断点调试。
  • 性能诊断‌:Arthas、VisualVM 等工具通过 Attach 连接到目标 JVM,实时采集线程状态、内存使用等性能数据。
  • 热更新与热部署‌:在不重启服务的情况下,动态修改类定义或替换字节码。
  • 安全测试‌:在授权环境中,通过 Attach 注入 Agent 型内存马进行渗透测试。

Attach 机制让 JVM 从一个封闭的运行环境变成了一个可被动态观测和干预的开放平台,极大地扩展了 Java 应用的可维护性和可调试性

3、Java Agent

Java Agent 是一种在 JVM 启动或运行时,对 Java 程序进行字节码修改和监控的探针技术‌。它可以在不改变原有代码的情况下,实现对程序行为的增强、监控或调试,常用于性能监控、日志埋点、热部署等场景。

核心原理

Java Agent 通过 JVM 提供的 Instrumentation API,在类加载或运行时动态修改字节码,实现类似 AOP(面向切面编程)的效果。它有两种加载方式:

  • 静态加载 ‌:通过 -javaagent:jar路径 参数在 JVM 启动前加载,执行 premain 方法。
  • 动态加载 ‌:在 JVM 运行中通过 Attach API 动态注入,执行 agentmain 方法。
典型应用场景
  1. 开发工具支持‌:如 IDEA、Eclipse 的调试功能。
  2. 热部署工具‌:如 JRebel,实现代码修改后无需重启应用。
  3. 线上诊断工具 ‌:如阿里开源的 Arthas、Skywalking 等。
  4. 性能监控与追踪‌:如 APm 探针、Prometheus 监控集成。
如何使用
  1. 编写一个包含 premainagentmain 方法的类。
  2. MANIFEST.MF 文件中指定 Premain-ClassAgent-Class
  3. 将其打包为 JAR 文件,并通过 -javaagent 参数启动目标程序。

二、Java内存马的表象

webshell可以正常访问,并且从log日志中可以看到webshell的访问状态码为200,但是在对应的目录中却找不到文件。如果存在此类情况,可以判断服务器中了内存马。

三、实现禁止Attach JVM的原理

禁止 JVM Attach 机制的核心原理是通过 JVM 启动参数 -XX:+DisableAttachMechanism 控制内部线程的初始化逻辑,从而阻断外部进程与目标 JVM 建立通信通道。

​ JVM 的 Attach 机制依赖于两个关键线程:"Signal Dispatcher"和"Attach Listener"。其中,"Signal Dispatcher"线程在 JVM 启动时始终创建,负责监听操作系统信号;而"Attach Listener"线程负责处理具体的 Attach 请求(如线程 dump、加载 Agent 等),它默认不会在启动时立即创建,而是由"Signal Dispatcher"在接收到特定信号后懒加载创建,或者通过参数 StartAttachListener 强制在启动时创建。

​ 当设置 -XX:+DisableAttachMechanism 参数时,JVM 在初始化阶段会检查该标志位。如果该标志位为 true,JVM 将跳过"Attach Listener"线程的初始化代码,既不会在启动时创建该线程,也不会允许"Signal Dispatcher"在后续运行时创建它。由于缺少了处理 Attach 命令的核心线程,外部工具(如 jstack、jmap、Arthas 等)即使通过文件 Socket 或信号机制尝试连接目标 JVM,也无法得到响应或执行任何操作,从而实现了禁止 Attach 的效果。

​ 此外,从 JDK 9 开始,为了增强安全性,默认配置进一步收紧,不仅可以通过上述参数完全禁用 Attach 机制,还默认禁止了动态加载 Agent(即 Attach API 中的 load 命令),除非显式启用 -XX:+EnableDynamicAgentLoading。这种设计旨在防止恶意代码通过 Attach 机制动态注入 JVM,提升了平台的安全性。

四、禁止Attach JVM情况下如何分析

1、还原被删除的Agent库文件(jar文件)

为防止被监控到,冰蝎 Agent 内存马会删除 /tmp/.java_pid4233 文件,该文件为AttachJVM时产生的socket文件。

可以使用命令恢复文件

bash 复制代码
ls -la /proc/4233/fd/ | grep deleted | grep /tmp

然后通过日志查看,反向找到 冰蝎 源码

2、内存dump分析-MAT工具

将内存dump文件拖入MAT工具,打开dominator_tree 。搜索相关关键字:rebeyond

内存dump分析-关键词

bash 复制代码
# 强制导出目标 JAVA 进程 22868 的堆内存转储
jmap -F -dump:format=b,file=heap.hprof 22868 
jcmd 22868 GC.heap_dump /tmp/heap.hprof
# 查看堆栈中可疑类和方法
yum install binutils 

# 1. 关键字简单分析 JAVA Heap 
# "POST /memshell HTTP/1.1" 
strings heap.bin | grep "POST /" 
strings heap.bin | grep -E "/webapps/.*?\!" |sort -u 
# 已知 memshell 特征
# fastjson 反序列化 classloader 
strings heap.bin | grep 'com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$TransletClassLoader' 
# behinder 
strings heap.bin | grep -i 'rebeyond\|behinder\|Agent Injected Successfully\|MemShell' 
# n1ntyfilter 
strings heap.bin | grep -i 'inject n1ntyfilter injected' 
# msf 
strings heap.bin | grep 'com.metasploit.' 

# 查找执行过的可疑 jsp 代码
# 寻找已知的恶意代码模式,如动态执行 Bash 命令、动态注册 /shell 路径、以及反射加载和解密操作。
strings heap.bin | grep -i 'new ProcessBuilder("/bin/bash","-c", req.getParameter("\|Runtime.getRuntime().exec(\|standardCtx.addServletMapping("/shell\|.getClass().getClassLoader()).g(c.doFinal(' 
# 寻找所有与进程执行、加密库和 Spring 映射机制相关的痕迹
strings heap.bin|grep -i 'javax.crypto.\|ProcessBuilder\|getRuntime\|ProcessImpl\|shell\|org.springframework.web.servlet.handler.AbstractHandlerMapping' 

# 查找最近可疑访问记录
strings heap.bin | grep '\b\(whoami\|pwd\|ps\|netstat\)\b'
相关推荐
陈天伟教授1 小时前
图解人工智能(2)最智能
人工智能·安全·架构
@insist1231 小时前
信息安全工程师-病毒、木马、蠕虫技术原理与防御基础
安全·软考·信息安全工程师·软件水平考试
小雅痞1 小时前
[Java][Leetcode middle] 36. 有效的数独
java·算法·leetcode
代码漫谈1 小时前
JVM 参数调优:Spring Boot与JDK新特性的最佳结合
java·jvm·spring boot
IT菜鸟程1 小时前
Linux 系统安全加固实战:从密码策略到 SSH 访问控制
linux·ssh·系统安全
卷毛的技术笔记1 小时前
双十一零点扛过10倍流量洪峰:Sentinel与Redis+Lua的分布式限流深度避坑指南
java·redis·分布式·后端·系统架构·sentinel·lua
逻辑驱动的ken1 小时前
Java高频面试考点场景题27
java·开发语言·面试·职场和发展·求职招聘
学习论之费曼学习法1 小时前
AI 入门 30 天挑战 - Day 27 - AI 伦理和安全
人工智能·安全
南境十里·墨染春水1 小时前
C++ 日志 4—— 多线程安全与异步日志优化
数据库·c++·安全