cobalt strike header/jarm 特征及修改绕过检测

前言:用了三个月发现ioc被封了,这边进行发现问题然后记录解决

参考文章:https://www.cobaltstrike.com/blog/a-red-teamer-plays-with-jarm
参考文章:https://conference.hitb.org/hitbsecconf2021ams/materials/D2 COMMSEC - JARM Randomizer Evading JARM Fingerprinting - Dagmawi Mulugeta.pdf
参考文章:https://github.com/salesforce/jarm
参考文章:https://intelinsights.substack.com/p/cobalt-on-the-weekends
参考文章:https://github.com/wikiZ/RedGuard

情况

发现域名被IOC标记了,如下图所示

原因

这边通过排查发现存在一些特征,分别是相同的header/banner hash, cert fingerprint,jarm fingerprint的这几个维度

header/banner hash

先来看header/banner hash的维度问题

通过censys语法查询可以发现存在CS特征的服务器

https://search.censys.io/search?q=services.banner="HTTP/1.1 404 Not Found\r\nDate: <REDACTED>\r\nContent-Type: text/plain\r\nContent-Length: 0\r\n"&resource=hosts

一看大概率就是CS服务器的特征,如下图所示,可以看到已经被censys标记为CS了

接着看下listener默认访问的header/banner hash特征,如下图所示

import requests
import mmh3

url = 'https://159.65.9.106'

# 发送请求
response = requests.get(url, verify=False)

# 获取响应头,并按 key 排序以保证一致性
headers = response.headers

# 将 headers 转换为有序字符串(只保留键和值)
headers_str = ''.join(f"{k}={v}" for k, v in sorted(headers.items()) if k.lower() != 'date')

# 计算 mmh3 哈希值
hash_value = mmh3.hash(headers_str.encode('utf-8'))

print("Headers 字符串:", headers_str)
print("MurmurHash3 哈希值:", hash_value)

jarm fingerprint

接着看jarm fingerprint的维度问题,如下图所示

通过censys语法查询可以发现存在CS特征的服务器,这里的jarm特征2ad2ad16d2ad2ad00042d42d00042de5fb3038104f457d92ba02e9311512c2语法配合上述的header特征

https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q=services.jarm.fingerprint%3A+2ad2ad16d2ad2ad00042d42d00042de5fb3038104f457d92ba02e9311512c2+AND+services.banner%3D%22HTTP%2F1.1+404+Not+Found%5Cr%5CnDate%3A++%3CREDACTED%3E%5Cr%5CnContent-Type%3A+text%2Fplain%5Cr%5CnContent-Length%3A+0%5Cr%5Cn%22

可以看到缩减了很多主机数量,基本全是被标记为C2特征的机器,如下图所示

补充说明:jarm上述的2ad2ad16d2ad2ad00042d42d00042de5fb3038104f457d92ba02e9311512c22ad2ad16d2ad2ad00042d42d00042ddb04deffa1705e2edc44cae1ed24a4da不一样,这边猜测的可能是先通过header特征中搜索大量的IP,然后又在IP中识别CS,接着中CS中获取到的2ad2ad16d2ad2ad00042d42d00042de5fb3038104f457d92ba02e9311512c2,然后再从2ad2ad16d2ad2ad00042d42d00042de5fb3038104f457d92ba02e9311512c2中继续检索header特征然后从中又提取出少量存在CS特征的服务器。

cert fingerprint

关于证书指纹就不多讲,这个主要出现的问题就是使用了默认的CS提供生成自签名证书的命令,这个比较好避免。

绕过检测

header/banner hash绕过

针对header/banner hash特征,这边通过profile的http-config即可进行修改,如下图所示

http-config {
	#set "true" if teamserver is behind redirector
	set trust_x_forwarded_for "false";
	header "Server" "Microsoft-IIS/8.5";
	header "X-Powered-By" "ASP.NET";
}

重新查看header特征,可以看到已经发生了改变,如下图所示

jarm fingerprint

2017 年,有安全团队开发了 JA3/S,这是一种被动的 TLS 客户端/服务器指纹识别方法,目前大多数网络安全工具中都存在这种技术。

JA3/S 是 被动的,通过监听网络流量来对客户端和服务器进行指纹识别;而 JARM 则是一种 主动的服务器指纹扫描器。您可以点击此处 了解更多关于 TLS 协商和 JA3/S 被动指纹识别的信息 。

JARM 的工作原理是主动向目标 TLS 服务器发送 10 个 TLS 客户端 Hello 数据包,并捕获 TLS 服务器 Hello 响应中的特定属性。然后,聚合后的 TLS 服务器响应以特定方式进行哈希处理,以生成 JARM 指纹。

JARM 中的 10 个 TLS 客户端 Hello 数据包经过特殊设计,用于在 TLS 服务器中提取唯一响应。JARM 会以不同的顺序发送不同的 TLS 版本、密码和扩展,以收集唯一响应。

  • 服务器是否支持 TLS 1.3?

  • 它会使用 1.2 密码与 TLS 1.3 进行协商吗?

  • 如果我们按从弱到强的顺序排列密码,它会选择哪种密码?

JARM 本质上就是在询问服务器提取最独特的响应,并提出这类不寻常的问题。然后对这 10 个响应进行哈希处理,以生成 JARM 指纹。

  • TLS Version

  • Cipher chosen

  • TLS Extensions

  • JARM前半部分由每个ClientHello选择的TLS版本TLS Version和加密套件Cipher chosen组成

  • JARM后半部分表示服务器端扩展TLS Extensions的截断SHA256哈希值

这边可以通过 https://github.com/salesforce/jarm 提供的工具来获取对应服务器的jarm指纹信息,如下图所示

这边的话可以通过RedGuard来作为前置域转发,流程图如下所示

git clone https://github.com/wikiZ/RedGuard.git
cd RedGuard
# 也可以使用upx压缩编译后的文件体积
go build -ldflags "-s -w" -trimpath
# 赋予工具可执行权限,并进行初始化操作
chmod +x ./RedGuard&&./RedGuard

接着通过jarm指纹信息工具来获取jarm指纹如下所示,可以看到实现了随机化jarm返回

注:每次重启RedGuard才会随机化jarm指纹

最后总结下,比如header或者是jarm指纹实际上不能作为直接判定C2服务器的因素,一般都是两个取交集的数据,然后再根据其他的特征来最终判定该主机是否为C2服务器。

posted @ 2025-06-17 15:46  zpchcbd  阅读(320)  评论(0)    收藏  举报