动身点是Java Agent
内存马的自动剖析与查杀,实践上其他内存马都能够经过这种方式查杀
本文主要的难点主要是以下三个,我会在文中逐一解答
- 如何
dump
出JVM
中真正的当前的字节码 - 如何处理由于
LAMBDA
表达式招致非法字节码无法剖析的问题 - 如何对字节码停止剖析以肯定某个类是内存马
基于静态剖析动态,突破规则之道 — Java King 对本文的评价
背景
关于Java内存马的攻防不断没有中止,是Java平安范畴的重点
回忆Tomcat
或Spring
内存马:Filter
和Controller
等都需求注册新的组件
针关于需求注册新组件的内存马查杀起来比拟容易:
例如c0ny1
师傅的java-memshell-scanner
项目,应用了Tomcat API
删除添加的组件。优点在于一个简单的JSP
文件即可查看一切的组件信息,分离人工检查(类名和ClassLoader
等信息)对内存马停止查杀,也能够对有风险的Class停止dump
后反编译剖析
或者LandGrey
师傅基于Alibaba Arthas编写的copagent
项目,剖析JVM
中一切的Class,依据风险注解和类名等信息dump
可疑的组件,分离人工反编译后停止剖析
但实战中,可能并不是以上这种注册新组件的内存马
例如师傅们常用的冰蝎内存马,是Java Agent
内存马。以下这段是冰蝎内存马一段代码,简单剖析后能够发现冰蝎内存马是应用Java Agent
注入到javax.servlet.http.HttpServlet
的service
办法中,这是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
修正后的字节码。经过Javaassist
等ASM
工具获取到类的字节码,也只是读取磁盘上响应类的字节码,而不是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();
感谢您的来访,获取更多精彩文章请收藏本站。
![](https://www.gyzsq.com/wp-content/uploads/2022/07/9259adea4619.gif)
1 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
2 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
3 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
![头像](/wp-content/themes/zibll/img/avatar-default.png)
- 最新
- 最热
只看作者