rebeyond 师傅在参考【1】中提出利用javaagent 永久注入tomcat进程的方案,有几个重要的技术点
- javaagent技术
- javassist技术
- tomcat ApplicationFilterChain.internalDoFilter方法
- ShutdownHook 钩子
javassist技术
Java 字节码以二进制的形式存储在 .class 文件中,每一个 .class 文件包含一个 Java 类或接口。Javaassist 就是一个用来 处理 Java 字节码的类库。它可以在一个已经编译好的类中添加新的方法,或者是修改已有的方法,并且不需要对字节码方面有深入的了解。同时也可以去生成一个新的类对象,通过完全手动的方式。
javassist 相关文档可以参考【2】和【3】,以简单的javassist demo
为例
Demo
目录结构
1 | ├── ModifyTarget.java |
其中Target为Demo
1 | public class Target { |
ModifyTarget功能为利用javassist动态更改Target.class,添加一段静态代码段
1 | public void testClassPool() throws CannotCompileException, NotFoundException, IOException |
但是仅仅改动class还不够,如何替换掉正在运行的Target类呢?
Java Instrumentation
java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序。这种监测和协助包括但不限于获取JVM运行时状态,替换和修改类定义等。简单一句话概括下:Java Instrumentation可以在JVM启动后,动态修改已加载或者未加载的类,包括类的属性、方法。
Demo
目录结构
1 | └── AgentMainTest.java |
其中AgentMainTest为Demo,agentmain为主函数
1 | public class AgentMainTest { |
打包为jar需要注意,必须指定Agent-Class:为目标类,比如rebeyond师傅的memshell
Agent-Class:net.rebeyond.memshell.Agent
主要的功能逻辑在自定义Transformer 上,Transformer提供transform接口,输入可以是各种类,如果需要修改该类,改动返回新类的bytes即可
如下
1 | public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { |
打包为agent.jar
1 | > java -javaagent:/Users/mody/study/java/MemShell/JavassistDemo/target/JavassistDemo-1.0-SNAPSHOT.jar Target |
可以成功在hello函数中插入弹出计算器
tomcat internalDoFilter
前文servlet中有提及tomcat http请求的调用链
1 | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) |
有了以上的基础知识,将Target类替换为internalDoFilter类即可
在internalDoFilter中插入的payload改为evil code
ShutdownHook
JDK提供了Java.Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在一下几种场景中被调用:
- 程序正常退出
- 使用System.exit()
- 终端使用Ctrl+C触发的中断
- 系统关闭
- OutOfMemory宕机
- 使用Kill pid命令干掉进程(注:在使用kill -9 pid时,是不会被调用的)
1 | Thread t = new Thread() { |
小结
本节将rebeyond 师傅首发的agent类型java内存马拆为几个关键技术点,简单的分别作了介绍,其实前两个javassist/javaagent应该还有更多的知识点。
愈发觉得java安全就像堆积木
感叹一声学海无涯
参考
- [1] 【原创】利用“进程注入”实现无文件不死webshell
- [2] javassist wiki
- [3] javassist使用全解析
- [4] memshell