一个使用 OneDrive 作为传输层的 Cobalt Strike 用户自定义 C2 通道。

Files.ReadWrite.All 应用程序权限的应用注册。在 Azure 门户中,转到 应用注册 并创建一个新应用:
记下概览页面中的 租户 ID 和 客户端 ID。
在 API 权限 下:
Files.ReadWrite.All。在 证书和密码 下,创建一个新密钥并复制其值。
在该用户的 OneDrive 中,创建两个文件夹,一个用于收件箱,一个用于
发件箱(例如 c2inbox 和 c2outbox)。
打开 Graph Explorer, 以该用户身份登录,然后运行:
GET https://graph.microsoft.com/v1.0/me/drive/root/children
获取每个文件夹的 id,以及 JSON 响应中任意条目的 driveId。
cp server/config.json.example server/config.json
填写 server/config.json:
然后构建客户端:
make
启动中继(使用 screen 或 tmux,这样当你的终端断开连接时它仍能保持运行):
python3 server/relay.py --config server/config.json --ts-addr <teamserver-ip> --ts-port <udc2-port>
在 Cobalt Strike 中,在同一端口上创建一个 UDC2 监听器,并加载 client/bof.o。
中继会在你的配置旁边创建一些文件,以便在重启之间跟踪各种事项:
config.json.state.json)- 跟踪哪些收件箱文件已被处理、待处理的上传以及 beacon 会话信息。使用 --state 设置自定义路径。config.json.state.json.spool/)- 保存尚未上传到 OneDrive 的响应数据。如果中继在上传过程中崩溃,假脱机会保留数据,以便在下次启动时重试。config.json.state.json.lock)- 防止两个中继实例针对同一状态运行。如果你看到 Another relay holds the lock 且没有其他中继在运行,则该锁是崩溃后遗留的陈旧锁。如果中继的本地状态损坏,或者陈旧的锁阻止了启动,请使用 --clean 清除状态文件和假脱机目录,以便中继重新开始:
python3 server/relay.py --config server/config.json --clean
锁文件会被保留。当另一个实例正在运行时,中继不会执行清理。在下次正常启动时,它会重新初始化并跳过任何超过 30 分钟的收件箱文件。
你也可以通过自行删除状态文件和假脱机目录来手动重置。如果锁文件已陈旧(没有中继在运行),也请将其删除。

| 字段 | 值 |
|---|
tenant_id | Microsoft Entra ID 租户 ID |
client_id | 应用程序客户端 ID |
client_secret | 客户端密钥值 |
drive_id | OneDrive 驱动器 ID |
inbox_folder_id | 收件箱文件夹 ID |
outbox_folder_id | 发件箱文件夹 ID |
| 标志 | 描述 |
|---|
--config | config.json 的路径(必填) |
--ts-addr | Teamserver IP |
--ts-port | UDC2 监听器端口 |
--poll | 轮询间隔(秒)(默认 2.0) |
--state | 状态文件的路径(默认:<config>.state.json) |
--debug | 启用调试日志记录 |
--clean | 删除状态文件和假脱机目录,然后退出 |