浅谈冰蝎、哥斯拉内存马排查思路

浅谈冰蝎、哥斯拉内存马排查思路

前言

最近有师傅问到遇到被内存马注入了,应该怎么排查,特别是常见是冰蝎和哥斯拉的内存马。刚好有空这两天在本地分析了一下内存马的排查思路,以及怎么查杀清除内存马

环境

Centos :release 7.6.1810 (Core)

Tomcat:v8.0.35 https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.35/bin/apache-tomcat-8.0.35.tar.gz

Behinder:v4.0.6 https://github.com/rebeyond/Behinder

godzilla_v4.0.1 https://github.com/BeichenDream/Godzilla

arthas 3.7.0 https://github.com/alibaba/arthas (Alibaba Java诊断利器Arthas)

shell-analyzer 0.1 https://github.com/4ra1n/shell-analyzer (基于 Java Agent 的内存马查杀 GUI 工具)

在centos7上部署Tomcat

1
https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.35/bin/apache-tomcat-8.0.35.tar.gz

解压

1
tar -zxvf apache-tomcat-8.0.35.tar.gz

Behinder的webshell

我们生成服务端之后直接上传到tomcat的apache-tomcat-8.0.35/webapps/ROOT/ncshell目录中。(我自己创建了个目录ncshell)

image

使用客户端连接:http://192.168.88.104:8080/ncshell/bxdefault_aes.jsp

image

arthas的使用

1
2
3
下载:wget https://github.com/alibaba/arthas/releases/download/arthas-all-3.7.0/arthas-bin.zip;unzip 
解压:arthas-bin.zip
启动:java -jar arthas-boot.jar

发现报错了。CentOS 自带openjdk不支持jps、jstack等命令。

image

就算指定pid运行也会报错没有找到tools.jar;

image

我直接通过yum升级安装一下解决

1
yum install java-1.8.0-openjdk-devel.x86_64

image

再次启动arthas-boot.jar;成功

image

查看一下内存中mbean信息

1
mbean | grep "name=/"

image

Arthas 常用命令

1
2
3
4
5
6
7
dashboard:显示当前应用程序的实时运行状况,包括 CPU 使用率、内存使用情况、线程情况等
jvm:查看和管理 JVM 的相关信息,包括堆内存、GC 状态、类加载情况等
sc:查看和搜索类信息,包括加载的类、类的字段和方法等。
sm:查看和搜索方法信息,可以查看方法的字节码、参数、返回值等
jad:反编译指定类的字节码,查看类的实现代码。
classloader:显示当前应用程序中所有的类加载器及其层次结构。可以查看每个类加载器的名称、父加载器和已加载的类数量
heapdump 生成 Java 应用程序的堆转储(Heap Dump)文件

Behinder内存马排查思路

注入之前,先查看一下加载器的信息和servlet的信息(因为冰蝎注入的是servlet类型的内存马)

image

此时已经发现了一个可疑的类,这个是实体的webshell,也就是我们上传到tomcat目录的那个:org.apache.jsp.ncshell.bxdefault_005faes_jsp

使用jad查看一下

1
2
jad org.apache.jsp.ncshell.bxdefault_005faes_jsp
jad javax.servlet.http.HttpServlet

得知org.apache.jsp.ncshell.bxdefault_005faes_jsp很明显的是webshell

image

为什么也要看一下javax.servlet.http.HttpServlet这个类呢,因为冰蝎的内存马是注入到这个类里面的;此时查看发现暂未发现异常。

image

注入内存马;把防检测也勾选上。

image

注入成功,且成功连接内存马

image

我们再来看一下加载器的信息和servlet的信息;发现多了一个可疑的加载器。

image

jad查看后发现是使用 super.defineClass 方法将字节数组转换为一个 Class 对象进行定义和加载

image

我们再去查看一下javax.servlet.http.HttpServlet;此时我们发现在它的service方法中,已经被注入了 内存马。

1
jad javax.servlet.http.HttpServlet

image

那么很确定了这个就是内存马,下面我们来那它关闭或者破坏掉,使其失效。

Behinder内存马清除

找了一圈发现,arthas并没有直接关闭指定类的功能。但是可以使用arthas进行热更新代码;但是我使用它做编译的时候失败了,后来学习了一下Javaagent技术,可以对jvm内的运行时类操作,于是可以编写一个agent使用retransformClass字节码重定义技术重新定义这个类。

项目的代码我已上传到github:

1
https://github.com/Garck3h/killBehinderMemShell

直接使用工具重置javax.servlet.http.HttpServlet类

1
java -Xbootclasspath/a:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.372.b07-1.el7_9.x86_64/lib/tools.jar -jar killBehinderMemShell-1.0-jar-with-dependencies.jar 61259 javax.servlet.http.HttpServlet

image

heapdump的使用

首先导出当前内存快照

image

然后使用string查看post请求的记录;发现可疑的请求目录

1
strings /root/neicunma/apache-tomcat-8.0.35/temp/heapdump2023-08-16-23-286100384348377803151.hprof | grep "POST /"

image

查看可疑路径;无果

1
strings /root/neicunma/apache-tomcat-8.0.35/temp/heapdump2023-08-16-23-286100384348377803151.hprof | grep -E "/webapps/.*?\!" | sort -u

image

至此冰蝎内存马的排查已完毕。

godzilla内存马

生成哥斯拉webshell上传至tomcat,进行连接。

image

哥斯拉工具中有FilterShell和memoryShell两种内存马

FilterShell

注入Filter类型的内存马

image

看一下当前的过滤器;有两个过滤器监听着所有的访问路径

image

使用arthas分析;查看所有的Filter;看到了一个可疑的Filter:org.apache.coyote.jsonFormatVisitors.JsonFormatTypes

1
2
sc *.Filter

image

使用jad查看源码,分析得知

1
jad org.apache.coyote.jsonFormatVisitors.JsonFormatTypes

继承了加载器和过滤器的接口;同时定义了一些敏感的属性

image

可以看到,这里监听了全部的uri路径”/*“。代码的大致功能为添加一个过滤器,并将过滤器配置和过滤器映射添加到标准上下文中,然后对过滤器进行排序,确保把它放在最高的优先级。

image

剩下的就是一个处理请求的和一些编码的函数了。

MemoryShell

我们重点来分析一下MemoryShell;该功能不仅可以注入哥斯拉的shell,还可以注入冰蝎、菜刀甚至ReGeorg。我们注入一个哥斯拉的内存马。

image

连接成功

image

查看jvm中的servlet的情况;多了一个可疑的类:org.apache.coyote.ser.impl.TypeWrappedSerializer

image

jad分析可疑的Servlet类:org.apache.coyote.ser.impl.TypeWrappedSerializer;该类实现了一个包装器,大致是用于在Servlet上下文中添加Servlet。其中transform 方法用于对传入的 standardContext 对象进行一系列的处理;x 方法是一个AES的加解密方法;还有md5方法;最后还使用了noLog 方法禁止日志记录。

image

同时查看内存中的请求url;也可以发现可疑的情况

1
mbean | grep "name=/"

image

哥斯拉内存马查杀一

github地址:https://github.com/c0ny1/java-memshell-scanner

直接把jsp上传到tomcat下,访问解析会自动查找疑似的内存马,可dump class文件下来分析,也可直接kill掉该类。

这时候发现了servlet类型的内存马。直接kill掉。

image

kill掉之后,业务还可正常访问,但内存马已经失效。

image

哥斯拉内存马查杀二

github:https://github.com/4ra1n/shell-analyzer

使用jps查看进程

image

启动服务端

1
2
3
4
5
java -cp remote-0.1.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.372.b07-1.el7_9.x86_64/lib/tools.jar com.n1ar4.RemoteLoader 76589 adminasd

参数解析
76589为进程pid
adminasd 为设置的密码

image

启动gui客户端

1
java -jar gui-0.1.jar

输入token(上面设置的密码)和IP之后点击attach即可。双击显示的类可以反编译代码

image

直接删除内存马

image

jdk自带的sa-jdi

sa-jdi是JDK提供的一个强大的调试工具集,适用于语言层和虚拟机层,支持调试运行着的Java进程、core文件和虚拟机crash之后的dump文件。在没有其它工具的情况下,也可以勉强凑合着使用它进行简单的分析。

运行

1
java -cp /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.372.b07-1.el7_9.x86_64/lib/sa-jdi.jar sun.jvm.hotspot.HSDB

输入jps查看到Bootstrap的pid

image

可以直接查看正在jvm中运行的类,以及反编译查看源码内容

image

总结

本文主要简单分析了冰蝎和哥斯拉常见的内存马,其中冰蝎的内存马是agent类型的,使用常规的杀软工具未必可以扫描杀除,我写了个小工具根据分析得知的恶意类之后,进行重置。对于普通的Filter和servlet类型的内存马可以使用上述的jsp查杀工具或者gui工具进行查杀。当然感兴趣的师傅也可以使用arthas热更新代码功能尝试去破坏掉恶意类。后续若有空,我也继续完善一下内存马清除工具。

arthas热更新破坏godzilla内存马(失败)

jad反编译的结果保存在 /tmp/bxdefault_005faes_jsp.java文件里

1
jad --source-only org.apache.coyote.ser.impl.TypeWrappedSerializer > /tmp/TypeWrappedSerializer.java

在新窗口使用vim修改内存马的密码(在Decrypt方法内),或者进行其它操作都可以;然后保存。

image

回到arthas。使用sc查找加载.bxdefault_005faes_jsp的ClassLoader

1
2
sc -d org.apache.coyote.ser.impl.TypeWrappedSerializer | grep classLoaderHash
classLoaderHash 42f71ecb

image

使用mc命令编译

1
mc -c 42f71ecb /tmp/TypeWrappedSerializer.java -d /tmp

image

使用redefine命令重新加载新编译好的bxdefault_005faes_jsp.class

1
redefine  /tmp/org/apache/jsp/ncshell/bxdefault_005faes_jsp.class /tmp/org/apache/jsp/ncshell/bxdefault_005faes_jsp$U.class

image