Agent内存马的自动分析与查杀

动身点是Java Agent内存马的自动剖析与查杀,实践上其他内存马都能够经过这种方式查杀

本文主要的难点主要是以下三个,我会在文中逐一解答

  1. 如何dumpJVM真正的当前的字节码
  2. 如何处理由于LAMBDA表达式招致非法字节码无法剖析的问题
  3. 如何对字节码停止剖析以肯定某个类是内存马

基于静态剖析动态,突破规则之道 — Java King 对本文的评价

背景

关于Java内存马的攻防不断没有中止,是Java平安范畴的重点

回忆TomcatSpring内存马:FilterController等都需求注册新的组件

针关于需求注册新组件的内存马查杀起来比拟容易:

例如c0ny1师傅的java-memshell-scanner项目,应用了Tomcat API删除添加的组件。优点在于一个简单的JSP文件即可查看一切的组件信息,分离人工检查(类名和ClassLoader等信息)对内存马停止查杀,也能够对有风险的Class停止dump后反编译剖析

或者LandGrey师傅基于Alibaba Arthas编写的copagent项目,剖析JVM中一切的Class,依据风险注解和类名等信息dump可疑的组件,分离人工反编译后停止剖析

但实战中,可能并不是以上这种注册新组件的内存马

例如师傅们常用的冰蝎内存马,是Java Agent内存马。以下这段是冰蝎内存马一段代码,简单剖析后能够发现冰蝎内存马是应用Java Agent注入到javax.servlet.http.HttpServletservice办法中,这是JavaEE的标准,理论上部署在Tomcat的都要契合这个标准,简单来了解这是Tomcat处置恳求最先且总是经过的中央,在该类参加内存马的逻辑,能够保证稳定触发

相似的逻辑,能够运用Java Agent将内存马注入org.apache.catalina.core.ApplicationFilterChain类中,该类位于Filter链头部,也就是说经过Tomcat的恳求都会交经过该类的doFilter办法处置,所以在该办法中参加内存马逻辑,也是一种稳定触发的方式(听说这是老版本冰蝎内存马的方式)

还能够对相似的类停止注入,例如org.springframework.web.servlet.DispatcherServlet类,针关于Spring框架的底层停止注入。或者一些巧妙的思绪,比方注入Tomcat自带的Filter之一org.apache.tomcat.websocket.server.WsFilter类,这也是Java Agent内存马能够做到的

上文简单地引见了各种内存马的应用方式与普通内存马的查杀,之所以最后引见Java Agent内存马的查杀,是由于比拟艰难。宽字节平安的师傅提出查杀思绪:基于javaAgent内存马检测查杀指南

援用文章讲到Java Agent内存马检测的难点:

调用retransformClass办法的时分参数中的字节码并不是调用redefineClass后被修正的类的字节码。关于冰蝎来讲,基本无法获取被冰蝎修正后的字节码。我们本人写Java Agent肃清内存马的时分,同样也是无法获取到被redefineClass修正后的字节码,只能获取到被retransformClass修正后的字节码。经过JavaassistASM工具获取到类的字节码,也只是读取磁盘上响应类的字节码,而不是JVM中的字节码

宽字节平安的师傅找到了一种检测手腕:sa-jdi.jar

借用公众号师傅的图片,这是一个GUI工具,能够查看JVM中一切已加载的类。区别在于这里获取到的是真正的当前的字节码,而不是获取到原始的,本地的字节码,所以是能够查看被Java Agent调用redefineClass后被修正的类的字节码。进一步能够dump下来以为存在风险的类然后反编译人工审核

引见

以上是背景,接下来引见我做了些什么,可以完成怎样的效果

不难看出,以上内存马查杀手腕都是半自动分离人工审核的方式,当检测出内存马后

能否能够找到一种方式,做到一条龙式效劳:

  • 检测(同时支持普通内存马和Java Agent内存马的检测)
  • 剖析(如何肯定该类是内存马,仅依据歹意类名和注解等信息不完善)
  • 查杀(当肯定内存马存在,如何自动地删除内存马并恢复正常业务逻辑)

大致看来,完成起来似乎不难,但是实践中遇到了很多坑,接下来我会逐一引见

SA-JDI剖析

我尝试经过Java Agent技术来获取当前的字节码,发现如师傅所说拿不到被修正的字节码

所以为了能够检测Agent马需求从sa-jdi.jar自身动手,想方法dump得到当前字节码(这样不止能够剖析被修正了字节码的Agent马也能够剖析普通类型的内存马)

留意到其中一个类:sun.jvm.hotspot.tools.jcore.ClassDump并经过查材料发现该类功用正是dump当前的Class(依据类名也可猜想出)其中的main办法提供一个dump class的命令行工具

于是我想了一些方法,用代码完成了命令行工具的功用,并能够设置一个Filter

ClassDump classDump = new ClassDump();
// my filter
classDump.setClassFilter(filter);
classDump.setOutputDirectory("out");
// protected start method
Class<?> toolClass = Class.forName("sun.jvm.hotspot.tools.Tool");
Method method = toolClass.getDeclaredMethod("start", String[].class);
method.setAccessible(true);
// jvm pid
String[] params = new String[]{String.valueOf(pid)};
try {
    method.invoke(classDump, (Object) params);
} catch (Exception ignored) {
    logger.error("unknown error");
    return;
}
logger.info("dump class finish");
// detach
Field field = toolClass.getDeclaredField("agent");
field.setAccessible(true);
HotSpotAgent agent = (HotSpotAgent) field.get(classDump);
agent.detach();
------本页内容已结束,喜欢请分享------

感谢您的来访,获取更多精彩文章请收藏本站。

© 版权声明
THE END
喜欢就支持一下吧
点赞8赞赏 分享
评论 共1条
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片
    • 头像后场0