草案:请求讨论
本文档概述了 OST C&C 规范第 1 版。其目的是提供对消息及其字段的详细描述。
制定本规范的动机是提供一种 C&C 消息传递协议(包括任务下发、结构化输出和点对点路由),该协议可以被原样实现,也可以仅仅作为项目开发者的灵感来源。本文档不旨在描述什么是 C&C。假定读者理解它是什么以及它的用途。
关键词 "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"MAY" 和 "OPTIONAL" 应按照 [RFC2119] 中的描述进行解释。
本规范做出以下假设:
以下是本文档中使用的术语列表。
植入体元数据:植入体向团队服务器报告的关于自身的信息。
任务请求:交给植入体执行的任务。
任务响应:给定任务的状态和输出(如果有)。
会话密钥:植入体用于加密其消息的唯一加密密钥。
每个任务请求和响应消息必须具有以下 16 字节头。```text | Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | -------------------------------------------------------------| | 0 | Type | Code | Flags | Label | | -------------------------------------------------------------| | 1 | Identifier | Length | | -------------------------------------------------------------|
- **Type**: 1-byte integer. 此任务的 'type'。 参见 [任务类型与代码](https://github.com/rasta-mouse/ost-c2-spec?tab=readme-ov-file#task-types-and-codes).
- **Code**: 1-byte integer. 给定 Type 的 'sub code'。 参见 [任务类型与代码](https://github.com/rasta-mouse/ost-c2-spec?tab=readme-ov-file#task-types-and-codes).
- **Flags**: 2-byte integer. 一组按位标志,用于描述消息的状态。 参见 [任务标志](https://github.com/rasta-mouse/ost-c2-spec?tab=readme-ov-file#task-flags).
- **Label**: 4-byte integer. 用于关联同一任务多条消息的唯一标签。
- **Identifier**: 4-byte integer. 用于按正确顺序构造分片消息的序号标识符。
- **Length**: 4-byte integer. 任务数据的总长度。
## 任务类型与代码```text
|------------------|--------------------------|
| Type | Code |
|------------------|--------------------------|
| 0 - NOP | 0 |
|------------------|--------------------------|
| 1 - Exit | 0 |
|------------------|--------------------------|
| 2 - Set | 0 - Sleep/Jitter |
| | 1 - SpawnTo |
| | 2 - BlockDLLs |
| | 3 - PPID |
|------------------|--------------------------|
| 3 - File | 0 - Copy |
| | 1 - Move |
| | 2 - Delete |
| | 3 - Upload |
| | 4 - Download |
|------------------|--------------------------|
| 4 - Directory | 0 - Print |
| | 1 - Change |
| | 2 - Create |
| | 3 - Copy |
| | 4 - Move |
| | 5 - List |
| | 6 - Delete |
|------------------|--------------------------|
| 5 - WhoAmI | 0 |
|------------------|--------------------------|
| 6 - Process | 0 - List |
| | 1 - Kill |
| | 2 - Inject Spawn |
| | 3 - Inject Explicit |
|------------------|--------------------------|
| 7 - Registry | 0 - Query |
| | 1 - Add |
| | 2 - Delete |
|------------------|--------------------------|
| 8 - RPortFwd | 0 - Start |
| | 1 - Data |
|------------------|--------------------------|
| 9 - Environment | 0 - Get |
| | 1 - Set |
|------------------|--------------------------|
| 10 - SOCKS | 0 - Connect |
| | 1 - Data |
| | 2 - Close |
|------------------|--------------------------|
| 11 - Tokens | 0 - List |
| | 1 - Make |
| | 2 - Steal |
| | 3 - Use |
| | 4 - Revert |
| | 5 - Delete |
| | 6 - Purge |
|------------------|--------------------------|
| 12 - Run | 0 |
|------------------|--------------------------|
| 13 - ItemStore | 0 - List |
| | 1 - Add |
| | 2 - Delete |
| | 3 - Purge |
|------------------|--------------------------|
| 14 - LocalExec | 0 - .NET |
| | 1 - BOF |
| | 2 - Managed PowerShell |
| | 3 - Unmanaged PowerShell |
|------------------|--------------------------|
| 15 - PrintScreen | 0 |
|------------------|--------------------------|
| 16 - RemoteExec | 0 - WinRM |
| | 1 - WMI |
| | 2 - PsExec |
| | 3 - SSH |
|------------------|--------------------------|
| 17 - Link | 1 - Link SMB |
| | 2 - Link TCP |
|------------------|--------------------------|
| 18 - Unlink | 0 |
|------------------|--------------------------|
| 19 - P2P | 0 - Acknowledge |
| | 1 - PassThru |
|------------------|--------------------------|
| 20 - Jobs | 0 - List |
| | 1 - Kill |
|---------------------------------------------|
某些标志是互斥的,绝不能同时设置。 如果没有设置任何标志,则任务应被视为已成功完成,相关的输出(如果有)不会被分段。```text
| Value | Description |
|---|---|
| 0 | No flags |
| 1 | Task Error |
| 2 | Task Running (as job) |
| 4 | Message is fragmented, more to follow |
| 8 | Message is fragmented, no more to follow |
## 任务数据
任务数据附加在头部之后,由二进制结构组成,具体取决于任务类型和代码。 每个任务请求和响应消息类型都在[[消息定义](https://github.com/rasta-mouse/ost-c2-spec?tab=readme-ov-file#message-definitions)]中定义。
如果不需要,任务请求或响应并非必须携带任何数据。
## 加密任务消息
在传输之前,任务头部和任务数据会被合并,并使用植入体的会话密钥进行 AES 加密。```text
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| ------------------------------------ |
| 0 | Iv |
| 8 | |
| ------------------------------------ |
| 16 | Checksum |
| 24 | |
| 32 | |
| 40 | |
| ------------------------------------ |
| 48 | Data |
| .. | |
| ------------------------------------ |
植入体必须先向团队服务器注册,然后才能接收或发送任何任务数据。
植入体生成一条 [IMPLANT-METADATA] 消息,使用团队服务器的 RSA 公钥对其进行加密,然后发送给团队服务器。
团队服务器使用其 RSA 私钥解密植入体的 [IMPLANT-METADATA],并且必须将其注册为新的会话/回调。
植入体必须与团队服务器进行“签到”,以接收自身或其子植入体的待处理任务数据。
签到方式取决于 C2 信道,不属于本规范的范畴。已注册的植入体可以仅发送其 ID 进行签到。但是,如果植入体后续更改了其会话密钥、睡眠或抖动配置,则还必须重新发送其元数据。
如果没有待处理任务,团队服务器可以返回无数据,或以一条或多条 [NOP] 消息的形式返回虚拟数据。否则,它必须返回一组使用植入体会话密钥进行 AES 加密的任务请求。
子植入体在与新的父植入体建立连接后,必须将其元数据写入 P2P 信道(例如命名管道或 TCP 套接字)。
父植入体必须读取此元数据,并通过 [LINK-REP] 消息将其发送回团队服务器。