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. 编写一个包含 premain 或 agentmain 方法的类。
  2. 在 MANIFEST.MF 文件中指定 Premain-Class 或 Agent-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'
相关推荐
深盾科技_Virbox2 分钟前
云端与本地并行交付,软件许可管理如何实现统一运营?
java·大数据·开发语言·安全
thefool1122662 分钟前
多线程 3
java
CoderYanger8 分钟前
A.每日一题:856. 括号的分数
java·程序人生·算法·leetcode·面试·职场和发展·学习方法
liangbo725 分钟前
01-Java 集合框架全景:从 Collection 到 Map 一张关系网理清
java
xuxigifxfh29 分钟前
HJ15 求int型正整数在内存中存储时1的个数
java·开发语言·华为机考
Wokoo732 分钟前
自动化测试入门:核心场景、回归测试与 Web 自动化环境搭建
java·开发语言·测试工具
LONGZETECH32 分钟前
新能源技术实训难题破解:纯电动汽车五大核心系统三维仿真解决方案
大数据·c语言·人工智能·安全·汽车
我是人✓1 小时前
Spring IOC注解全解析和Spring整合测试单元
java·后端·spring
智购科技无人售货机工厂店1 小时前
玻璃瓶饮料破损率突然上升,排查发现是取货口缓冲垫老化了~YH
java·开发语言·人工智能·python·eclipse
byte轻骑兵1 小时前
【HOGP】规范精讲[7]: BLE人机交互的安全防线——HOGP安全规范全解析与落地指南
安全·计算机外设·人机交互·蓝牙·hogp