Files
coruna-lab/doc/C2_API.md
T
2026-08-07 05:21:44 +08:00

459 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Coruna Reporting C2 API
Lab 实现见 `routes/c2.php`。字段形状主要来自:
- [`coruna-online/docs/CORUNA_COMPLETE_DATAFLOW_REPORT.md`](../../../coruna-online/docs/CORUNA_COMPLETE_DATAFLOW_REPORT.md) §7
- HAR 解密红acted 样本
[`c2_decrypted_redacted.json`](../../../coruna-online/evidence/cases/2026-08-02-coruna-har/c2_decrypted_redacted.json)
敏感值在证据里已打码;下文用「含义 + 类型」描述,不复述真实秘密。
---
## 1. 传输约定
### 1.1 JSON POST(除 `/api/user/check`、除 `GET /api/user/query`)
| 项 | 说明 |
|----|------|
| Header `timestamp` | 13 位毫秒时间戳 |
| Body | Base64(AES-256-ECB-PKCS7(key, `timestamp \|\| JSON`)) |
| key | `SHA256(session_key \|\| timestamp)`(session_key 为 16 ASCII) |
响应同样用自生成 `timestamp` 头 + 加密 body。常见明文为:
```json
null
```
或:
```json
{"code":0,"msg":"ok","data":null}
```
**Lab 默认回包**:加密 `{"code":0,"msg":"ok","data":null}`(与客户端不死循环的成功 ack 对齐)。真实战役响应字段可能更丰富,但客户端通常只认成功/可解密。
### 1.2 GET `/api/user/query`
- 无加密 body
- 响应明文:`OK`(`text/plain`)
### 1.3 POST `/api/user/check`
- `multipart/form-data`
- `file`:Coruna 头混淆的加密 7z;口令 `session_key || batchBase`(首批常见 `"0"`)
- `sig`:不透明二进制,**Lab 不校验**
### 1.4 通用身份字段(多接口复用)
| 字段 | 观察含义 |
|------|----------|
| `c` | 32 hex,会话/渠道类 ID |
| `d` / `f` | 16 hex,设备相关指纹(二者常相同) |
| `id` / `lhu` | UUID 形字符串(事件/本地句柄) |
| `pn` / `m` / `et` | 产品名 / 机型 / 事件类型文本 |
| `pv` | 系统版本(如 `15.8.4`) |
| `s` / `u` / `sbu` | 其它会话/用户侧短字段 |
| `v` | 插件或模块版本串 |
设备主键:只取 `d` / `f`(见 `IngestService::extractDeviceKey`)。
`/api/user/check` multipart 的 `d`/`f` 为编码形态
`hex(ascii(nibbleSwap(byteReverse(json_d))))`(例:`000430C910E8E526` → `36323545384530313943303334303030`);Lab 在入库前归一化为 JSON 侧 16 hex。
---
## 2. 接口一览
| 方法 | 路径 | 用途(战役观察) | Lab 行为 |
|------|------|------------------|----------|
| GET | `/api/user/query` | DGA/连通性探测,选 reporting C2 | 明文 `OK` |
| POST | `/api/user/avatar/set` | 首次设备 profile | 写 devices(+apps 若有) |
| POST | `/api/user/get` | 拉/登记状态;带已装 App 列表 | 登记设备;ack |
| POST | `/api/user/avatar/put` | 下载/注入/模块健康等遥测 | 登记设备;ack;落文件日志 |
| POST | `/api/user/avatar/status` | 钱包 keystore / identity JSON | `wallet_keystores.raw_json` ← `result` |
| POST | `/api/user/status` | 地址 → 资产/余额(`ba`/`ad`) | `wallet_addresses`(balance JSON,source←`a`) |
| POST | `/api/user/set` | 明文助记词或私钥 | `wallet_mnemonics`(加密,source←`a`) |
| POST | `/api/user/check` | 相册命中图 7z 归档 | 修头解包 → photos |
| POST | `/api/user/avatar/pic` | Notes 批次(`list`) | `notes.content` ← `payload.list` |
| POST | `/api/user/profile/{add,delete,remove}` | imagent 侧 profile 变更 | 仅日志 + ack |
| POST | `/link/config/list` | WebClip/链接配置轮询 | ack `data: []` |
| POST | `/link/config/icon` | WebClip 图标 | ack `data: null` |
**不做**:`/kill`、助记词/私钥自动划转。
---
## 3. 分接口说明
### 3.1 `GET /api/user/query`
**用途**:reporting 是否存活;DGA 用成功响应选定当前 C2。
**请求**:无 body;可无特殊头。
**响应(Lab / 战役一致观察)**:
```text
OK
```
---
### 3.2 `POST /api/user/avatar/set`
**用途**:植入后上报设备画像(机型、系统、区域、运营商、宿主 App 等)。
**请求明文(红acted 形状)**:
```jsonc
{
"c": "<32hex>",
"d": "<16hex>",
"f": "<16hex>",
"application": {
"applicationIdentifier": "<bundle>",
"bundleIdentifier": "<bundle>"
},
"deviceInfo": {
"productName": "iPhone OS",
"productType": "iPhone9,1",
"productVersion": "15.8.4",
"hardwareModel": "...",
"buildVersion": "..."
},
"deviceModel": "iPhone9,1",
"deviceName": "<name>",
"systemVersion": "15.8.4",
"machine": "...",
"kernVersion": "...",
"bootHash": "...",
"boottime": 0,
"carrierNames": [],
"language": "...",
"regionCode": "...",
"timezone": "...",
"totalGB": 0,
"jbsdk_version": "...",
"lhu": "<uuid>",
"s": "...",
"sbu": "...",
"u": "..."
}
```
**响应**:加密 ack(见 §1.1)。
---
### 3.3 `POST /api/user/get`
**用途**:初始状态/注册拉取;HAR 中携带已装应用简表 `al`。
**请求明文要点**:
```jsonc
{
"c": "<32hex>",
"d": "<16hex>",
"f": "<16hex>",
"al": [
{ "a": "<app name>", "b": "<bundle id>", "v": "<version>" }
],
"b": "...",
"i": "...",
"lhu": "<uuid>",
"m": "...",
"p": "...",
"s": "...",
"sbu": "...",
"u": "...",
"v": "..."
}
```
| 字段 | 含义 |
|------|------|
| `al[].a` | App 显示名 |
| `al[].b` | bundle id |
| `al[].v` | App 版本 |
**响应**:加密 `{"code":0,"msg":"ok","data":null}`(Lab)。战役侧可能带配置 `data`;未完全还原时以可解密成功 ack 为准。
---
### 3.4 `POST /api/user/avatar/put`
**用途**:通用遥测/事件总线。同路径多种 `ctx`:
| ctx 形态 | 含义 |
|----------|------|
| `url, sha256, size, downloadTimeMs, isFirstLoad` | 模块/资源下载 |
| `totalModules, abnormalModules, overallStatus, checkTimeMs` | 模块健康检查 |
| `bundleId, targetPid, injectionTimeMs` | 进程注入结果 |
| 空 `ctx` | 其它短事件(配合 `desc` / `et` / `ex`) |
**公共字段示例**:
```jsonc
{
"c": "<32hex>",
"d": "<16hex>",
"f": "<16hex>",
"id": "<uuid>",
"lhu": "<uuid>",
"pn": "iPhone OS",
"m": "iPhone9,1",
"pv": "15.8.4",
"desc": "<event description>",
"et": "<event type text>",
"ex": 0,
"exp": "",
"ctx": { /* 见上表 */ },
"s": "...",
"..."
}
```
WhatsApp 等插件也会复用此路径上报消息相关事件(静态/流量均有指认)。
**响应**:加密 ack。
---
### 3.5 `POST /api/user/avatar/status`
**用途**:上传仍加密的钱包/keystore/identity JSON(如 imToken `walletsV2` 解密前结构)。
**请求明文要点**:
```jsonc
{
"a": "<短标签>",
"c": "<32hex>",
"d": "<16hex>",
"d1": "<40hex>",
"d2": "<短串>",
"d3": "<40hex>",
"v": "<module version>",
"result": {
"crypto": {
"cipher": "aes-128-ctr",
"cipherparams": { "iv": "<hex>" },
"ciphertext": "<hex>",
"kdf": "pbkdf2",
"kdfparams": { "c": 0, "dklen": 0, "prf": "...", "salt": "<hex>" },
"mac": "<hex>"
},
"identity": { /* encAuthKey, encKey, ... */ },
"encOriginal": "...",
"imTokenMeta": { /* ... */ }
}
}
```
**响应**:加密 ack。
Lab:`wallet_keystores` 存整份 `result`(`raw_json`)。
---
### 3.6 `POST /api/user/status`
**用途**:地址 → 链上资产/余额映射。
**请求明文要点**:
```jsonc
{
"a": "<短标签>",
"c": "<32hex>",
"d": "<16hex>",
"d1": "<40hex>",
"d2": "...",
"d3": "<40hex>",
"v": "...",
"ba": {
"<walletAddress>": [
{
"balance": "<string>",
"chainId": "<string>",
"chainType": "<string>",
"decimal": "<string>",
"name": "<token name>",
"symbol": "<symbol>"
}
]
}
}
```
`ba` 的 key 为地址;value 为该地址下资产数组。
**响应**:加密 ack。Lab 写入 `wallet_addresses`:`chain_type`←`chainType`(缺省则按地址推断),`balance` 为 `{SYMBOL: 格式化数量}`(按 `decimal`/`decimals`),`source`←`a` 短标签映射钱包名。亦接受 `ad`(Global 标量 map / Trust 资产数组)。
---
### 3.7 `POST /api/user/set`
**用途**:上报**明文**助记词或私钥(HAR 已证实 12 词助记词在 `result`)。
**请求明文要点**:
```jsonc
{
"a": "<短标签>",
"c": "<32hex>",
"d": "<16hex>",
"d1": "<40hex>",
"d2": "...",
"d3": "<40hex>",
"v": "...",
"result": "<12/15/18/21/24 words mnemonic OR private key string>"
}
```
**响应**:加密 ack。Lab:`wallet_mnemonics`(`mnemonic_enc` Laravel crypt,`source`←`a`),后台仅打码展示。
---
### 3.8 `POST /api/user/check`
**用途**:相册 OCR/敏感命中后的图片归档上传(非 AES JSON)。
**Content-Type**:`multipart/form-data`
| Part | 观察 |
|------|------|
| `file` | Coruna 头混淆 7z;解压后为 JPEG 等 |
| `sig` | ~352–472 字节不透明数据,用途未证实 |
| `idx` | 12 hex:`upload_count\|\|process_index`(各 6 位);Lab 解码入库 |
| `ftu` | 12 hex:`text_count\|\|barcode_count`;Lab 解码入库 |
| `x-hit` | BIP39 词数或 -1/-2/-3;Lab 存 `photos.x_hit` |
| `rid` | ~36 字符请求/资源 id |
| `c`,`d`,`f`,`s`,`u`,`b`,`m`,`ts` | 设备/会话侧短字段(与 JSON 接口同族) |
| `d`,`f` | **长度 32**:相对 JSON 的 16 hex 做了 nibble/byte 重排后再 hex(ascii);Lab 归一化后入库 |
| `ts` | **即 batchBase**:首批为 `"0"`;后续为 `LastProcessedTimestamp` 十进制字符串 |
7z 口令:`session_key || ts`(Lab 读 multipart 字段 `ts`;缺省才回落 `"0"`)。
**响应**:加密 ack(Lab)。战役侧亦为加密成功体,具体 JSON 未作为契约固定。
---
### 3.9 `POST /api/user/avatar/pic`
**用途**:Notes reader 批次上报。
**请求明文要点**(真机已见):
```jsonc
{
"c": "<32hex>",
"d": "<16hex>",
"f": "<16hex>",
"s": "...",
"u": "<40hex>",
"list": ["<note text>", "..."]
}
```
**响应**:加密 ack。Lab:`notes.content` ← `payload.list`(JSON 数组)。
---
### 3.10 `POST /api/user/profile/add|delete|remove`
**用途**:`imagent` 消息/profile 状态变更(静态接口表)。HAR 本批无样本。
**请求**:加密 JSON(形状未钉死)。
**响应**:加密 ack;Lab 仅日志。
---
### 3.11 `POST /link/config/list`
**用途**:WebClip / 链接配置轮询。
**请求明文(HAR)**:
```jsonc
{
"c": "<32hex>",
"channel": "<32hex>",
"d": "",
"f": "",
"s": "",
"u": ""
}
```
**响应**:
- Lab:加密 `{"code":0,"msg":"ok","data":[]}`
- 战役:可能返回链接列表;未完整还原时客户端以可解密为准
---
### 3.12 `POST /link/config/icon`
**用途**:拉取 WebClip 图标。
**HAR**:本批无独立解密样本。
**请求**:加密 JSON(预期含图标/链接标识)。
**响应(Lab)**:加密 `{"code":0,"msg":"ok","data":null}`。
---
## 4. Lab 响应统一格式
除 `query` 外,控制器经 `CorunaCrypto::encryptJson` 返回:
**HTTP**
- Status:`200`
- Header:`timestamp: <13-digit>`
- Body:Base64 AES 密文
**明文(Lab)**
```json
{
"code": 0,
"msg": "ok",
"data": null
}
```
`/link/config/list` 的 `data` 为 `[]`。
原始请求/响应落盘:`public/log/c2/Ymd.log`(`create_log`,不写 DB)。
- `dir: "in"`:请求明文(解密后 `payload`)
- `dir: "out"`:响应明文(有 `timestamp` 头则 AES 解密;`query` 等明文直接记)
---
## 5. 调用顺序(HAR 观察)
典型顺序(同一 reporting 域名):
```text
query → avatar/put(telemetry) → query → avatar/set → get
→ avatar/put* → check* → … → avatar/status → status → set
→ link/config/list …
```
相册命中(`check`)可早于或并行于钱包本地解密上报(`avatar/status` → `status` → `set`)。
---
## 6. 参考
| 文档/证据 | 内容 |
|-----------|------|
| `CORUNA_COMPLETE_DATAFLOW_REPORT.md` §7.2 | 接口职责总表 |
| `CORUNA_DOMAIN_DGA_REPORT.md` | `query` 与 DGA 选服 |
| `c2_decrypted_redacted.json` | 各路径请求字段形状 |
| `app/Services/CorunaCrypto.php` | 加解密实现 |
| `app/Http/Controllers/C2/C2Controller.php` | Lab 处理与回包 |