前言
出发点是Java Agent
内存马的自动分析与查杀,实际上其他内存马都可以通过这种方式查杀
本文主要的难点主要是以下三个,我会在文中逐个解答
1.如何
dump
出JVM
中真正的当前的字节码
2.如何解决由于LAMBDA
表达式导致非法字节码无法分析的问题
3.如何对字节码进行分析以确定某个类是内存马
背景
对于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
内存马的检测)- 分析(如何确定该类是内存马,仅根据恶意类名和注解等信息不完善)
- 查杀(当确定内存马存在,如何自动地删除内存马并恢复正常业务逻辑)
大致看来,实现起来似乎不难,然而实际中遇到了很多坑,接下来我会逐个介绍
【→>所有资源关注我,查看“资料”获取<←】> 1、网络安全学习路线> 2、电子书籍(白帽子)> 3、安全大厂内部视频> 4、100份src文档> 5、常见安全面试题> 6、ctf大赛经典题目解析> 7、全套工具包> 8、应急响应笔记
SA-JDI分析
我尝试通过Java Agent
技术来获取当前的字节码,发现如师傅所说拿不到被修改的字节码
所以为了可以检测Agent
马需要从sa-jdi.jar
本身入手,想办法dump
得到当前字节码(这样不止可以分析被修改了字节码的Agent
马也可以分析普通类型的内存马)
注意到其中一个类:sun.jvm.hotspot.tools.jcore.ClassDump
并通过查资料发现该类功能正是dump
当前的Class(根据类名也可猜测出)其中的main
方法提供一个dump class
的命令行工具
于是我想了一些办法,用代码实现了命令行工具的功能,并可以设置一个Filter
ClassDump