浅谈大模型在威胁分析的落地下篇
原创 花十一一 2025-08-18 20:04 北京
上篇分析了Havoc上线的三种方式,接下来看看如何从空间测绘侧发现Havoc teamserver。AI提供了如下思路,我们一一验证可行性。


(1) websocket默认端口40056扫描
在profiles\havoc.yaotl中teamserver默认配置的监听端口是40056,是Havoc客户端与teamserver进行WebSocket通信的主入口,这个端口承担着客户端连接、命令控制、数据交换和多组件协调的关键作用。配置文件中默认的账号有是5pider/Neo,密码都是password1234。

首先分析下客户端与teamserver的认证逻辑。client\src\Havoc\
Connector.cc文件实现了客户端如何建立连接并进行认证。默认websocket通信的路径是/havoc/,伴有SSL证书加密。构造连接URL为 wss://host:port/havoc/。

在连接建立后,客户端通过SendLogin 方法发送认证请求,构造认证消息包。
1.配置Head.Event = 0x1 (InitConnection.Type)
2.配置Body.SubEvent = 0x3 (OAuthRequest)
3.使用 QCryptographicHash 计算用户密码的SHA3-256 Hash,将结果填充到 Body.Info["Password"] 字段
4.通过 SendPackage 方法发送JSON格式的认证消息
# 序列成json格式:{"Head":{"Event":1,"User":"test","Time":"10:50:54"},"Body":{"SubEvent":1,"Info":{"User":"test","Password":"test"}}}

teamserver\cmd\server\teamserver.go中handleRequest 方法实现了服务端在接收到请求后处理的过程,teamserver端首先验证用户名是否存在于配置文件中,检查是否已有同名用户在线(防止重复登录),最后调用 ClientAuthenticate 方法进行密码验证:
- 验证 Head.Event 是否为 InitConnection.Type (0x1)。
- 验证 Body.SubEvent 是否为 OAuthRequest (0x3)。
- 从配置文件中查找匹配的用户名 - 使用SHA3-256计算配置文件中存储的密码Hash对比客户端发送的密码Hash与服务端计算的Hash。

接下来进入认证阶段,认证成功:
- 服务端设置 client.Authenticated = true
- 发送 Authenticated(true) 事件给客户端
- 记录日志: User <username> Authenticated
- 广播新用户连接事件给所有在线客户端
认证失败 :
- 服务端记录错误日志:Client [User: username] failed to Authenticate! (IP地址)
- 发送 Authenticated(false) 事件给客户端
- 关闭与客户端的连接

最后客户端接收到teamserver的认证结果后做如下处理。client\src\Havoc\Packager.cc中的DispatchInitConnection 方法实现。认证成功 :
- 初始化Havoc UI界面
- 从配置文件加载脚本
- 调用 HavocApplication->Start() 启动应用程序
- 如果是已存在的连接,则创建新的Teamserver标签页
认证失败 :
- 显示错误消息框,提示"Couldn't connect to Teamserver"

理清楚了认证过程,那就可以写脚本来验证登录。如下是账密可用登录成功teamserver返回的信息。
{"Head": {"Event": 1,"User": "","Time": "17/08/2025 07:07:07","OneTime": ""},"Body": {"SubEvent": 1,"Info": {"Message": "Successful Authenticated"}}}

密码错误返回的信息。
{"Head": {"Event": 1,"User": "","Time": "17/08/2025 07:10:32","OneTime": ""},"Body": {"SubEvent": 2,"Info": {"Message": "Wrong Password"}}}

用户名错误返回的信息。
{"Head": {"Event": 1,"User": "","Time": "17/08/2025 07:11:31","OneTime": ""},"Body": {"SubEvent": 2,"Info": {"Message": "User doesn't exits"}}}

基于这些特征,再扫描到havoc teamserver时候可以猜测用户,验证密码。
(2)SSL证书特征
关于SSL证书上篇文章有分析,这里总结下证书的几个显著特点。
- 2048 位 RSA 密钥:使用标准且安全的密钥长度
- 自签名 CA 证书:证书同时作为 CA 和服务器证书使用
- 美国地址信息:所有证书的国家代码固定为 "US"
- 随机化特征:包括有效期起始时间、地理位置详情和组织信息的随机化
- 有效期设计:基础有效期为3年,但会随机调整起始时间以避免统一到期。
根据此特征可以验证teamserver 证书是不是符合要求。脚本里需要把预定义的随机特征都覆盖。


(3)http响应特征
在teamserver\pkg\handlers\http.go中存 fake404 函数。用于生成伪造的nginx 404页面,该函数在以下情况被调用:
- 请求头验证失败
- 请求URI不符合配置
- User-Agent不匹配
- 无法解析代理请求
错误页面的关键特征包括:
- HTTP状态码 :404 Not Found
- 响应头 :
- Server: nginx
- Content-Type: text/html
- X-Havoc: true (这是最具辨识度的特征)
- 响应体 :标准的nginx 404页面,位于teamserver\pkg\handlers\404.html,包含"404 Not Found"标题和"nginx"页脚


脚本主要验证源码大小、header特征。

结合上述特征,可以有个思路监控网络测绘中的havoc teamserver。
1、针对websocket协议发送登录验证逻辑,如果返回了teamserver的响应包,包括"Successful Authenticated"、 "Wrong Password"、"User doesn't exits"三个字符
2、测绘http协议的header、html源码命中特征后,对IP进行全端口扫描,走方法1验证,如果没有验证,只能说是可疑。
3、测试ssl证书,命中特征后对IP进行全端口扫描,走方法1验证,如果没有验证,只能说是可疑。
笔者用此逻辑扫描了一批havoc teamserver,大部分都对默认账密做了修改,当然也扫描到了一些弱口令。


最后附上teamserver\pkg\packager\types.go中定义了Event、SubEvent全部类型,具体如下。
Event:InitConnection (初始化连接) - 0x1Listener (监听器操作) - 0x2Credentials (凭证管理) - 0x3Chat (聊天相关) - 0x4Gate (远控相关) - 0x5HostFile (主机文件操作) - 0x6Session (会话相关) - 0x7Module (模块操作) - 0x6Misc (杂项) - 0x7Service (服务相关) - 0x9Teamserver (团队服务器相关) - 0x10
每个Event有定义了一些SubEvent。
1. InitConnection (0x1)- Success : 0x1 (认证成功)- Error : 0x2 (错误)- OAuthRequest : 0x3 (OAuth认证请求)- InitInfo : 0x4 (初始化信息)- Profile : 0x5 (配置文件)2. Listener (0x2)- Add : 0x1 (添加监听器)- Edit : 0x2 (编辑监听器)- Remove : 0x3 (移除监听器)- Mark : 0x4 (标记监听器)- Error : 0x5 (监听器错误)3. Credentials (0x3)- Add : 0x1 (添加凭证)- Edit : 0x2 (编辑凭证)- Remove : 0x3 (移除凭证)4. Chat (0x4)- NewMessage : 0x1 (新消息)- NewListener : 0x2 (新监听器)- NewSession : 0x3 (新会话)- NewUser : 0x4 (新用户)- UserDisconnected : 0x5 (用户断开连接)5. Gate (0x5)- Staged : 0x1 (分阶段)- Stageless : 0x2 (无阶段)- MSOffice : 0x3 (Microsoft Office相关)6. HostFile (0x6)- Add : 0x1 (添加主机文件)- Remove : 0x2 (移除主机文件)7. Session (0x7)- NewSession : 0x1 (新会话)- Remove : 0x2 (移除会话)- Input : 0x3 (输入)- Output : 0x4 (输出)- MarkAsDead : 0x5 (标记为死亡)8. Module (0x6)- Register : 0x1 (注册模块)- Unload : 0x2 (卸载模块)- Call : 0x3 (调用模块)9. Misc (0x7)- MessageBox : 0x1 (消息框)10. Service (0x9)- RegisterAgent : 0x1 (注册代理)- RegisterListener : 0x2 (注册监听器)11. Teamserver (0x10)- Log : 0x1 (日志)- Profile : 0x2 (配置文件)