前言
最近学习内存马,发现目前内存马主要集中在三个层面,1、原生的Servlet/Filter 2、框架封装的控制器 3、jvm层面(rebeyond的memshell,目前已集成在最新版冰蝎中)。前两种其实听的比较多,第三种听的比较少,研究了一下发现比较有意思,又学到了一个知识点。本文主要分析第三种内存马,以memshell工具为例。
代码分析
该工具分为两块,Agent.jar和Inject.jar,Agent.jar为一个attach类型的java agent。Inject.jar为将Agent.jar attach到tomcat的jvm上的程序。
首先看Agent部分代码
Agent.java
Agent.java前半部分的代码为添加类转换的方法,找到org.apache.catalina.core.ApplicationFilterChain类进行类转换,具体怎么转化内的可以看Transformer类的transform()方法。
看上图可知,transform获取到org.apache.catalina.core.ApplicationFilterChain的ClassLoader,类名,Class,ProtectionDomain,字节数组。然后使用javaassit将org.apache.catalina.core.ApplicationFilterChain的internalDoFilter方法中插入自定义的代码,对应上图代码中的
1 | m.insertBefore(readSource()) |
source.txt
1 | javax.servlet.http.HttpServletRequest request=$1; |
可以看到各种功能性的代码被插入到了org.apache.catalina.core.ApplicationFilterChain的Filter中。因此,之后每段通过tomcat filter的请求都会被执行memshell的功能代码。
而至于Agent.java中得下图的try代码,主要是做一些删除jar包操作,不是agent其内存马作用的逻辑。
然后再看Inject.jar的内容
对应源码的Attach.java
1 | if (args.length != 1) { |
以上代码获取命令行输入的password和当前文件位置,并将两者拼接为agentArgs,留做后续转给agent.jar。
1 | while (true) { |
上述代码在所有的jvm中寻找tomcat的jvm,然后将agent.jar attach到tomcat的jvm上。就会运行agent.jar中Agent.java中的agentmain方法逻辑,最后打上jvm层面的内存马。
排坑
1、如果缺少VirtualMachine类,请将jre/lib中的tools.jar加入CLASSPATH
2、作者github上传的源码有点问题,发布的jar包是没问题的,可能发布源码时忘了改了。
具体就是将Transformer.java中的部分代码修改就没问题了
原本:
修改后:
原因是因为transform的Class参数如果是类加载的话则为空,如果是重定义或重转发不为空。我们是用Agent.java中的inst.retransformClasses(c);来重转发这个类的。
而如果class类为空,然后又执行了new ClassClassPath(aClass),后续会报错空指针,程序就异常了,因此要加一个判断是否为空的逻辑。
3、打包
之前一直对打包这个东西不太了解,这次打包这个项目打包了很久,我是用maven打包的,直接贴出我的pom.xml吧
1 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
lib里面放了一个source.txt,注意这里我打包的是Agent.jar,其实都不需要tools.jar的,只不过我懒得删了。打包用了maven的jar-with-dependencies,会把依赖的jar包以class的形式和程序的class封装在一个jar包里,该jar包名称以jar-with-dependencies结尾。
然后在pom.xml目录执行
1 | mvn assembly:assembly |
解压jar-with-dependencies后的目录结构,这样的agent.jar就可以直接使用了
后记
昨天有朋友和我说看了我的博客,以前一直以为没人看我的博客,所以写的基本上都是自己记录类型的,也没想着写的很清晰,自己能看懂就行了。因此,后面还是尽量写的清晰一些,毕竟挂在互联网上了,需要对读者负责。