Yoshk4e/OxidizedRelay
GitHub: Yoshk4e/OxidizedRelay
一款 Rust 编写的高性能 CLI 工具,专门用于从 PCAP 捕获文件中解密和解析 ChaCha20 加密的 Protobuf 游戏协议流量。
Stars: 2 | Forks: 0
# OxidizedRelay
一款高性能 CLI 工具,用于解密和解析 PCAP 捕获文件中 ChaCha20 加密的 protobuf 游戏协议流量。
## 目录
- [概述](#overview)
- [加密方案](#encryption-scheme)
- [帧结构布局](#wire-frame-layout)
- [CSHead Schema](#cshead-schema)
- [构建](#building)
- [用法](#usage)
- [参数](#arguments)
- [选项](#options)
- [示例](#examples)
- [输出格式](#output-format)
- [帧过滤的工作原理](#the-process-of-frame-filtering)
- [Proto Schema 加载](#proto-schema-loading)
- [支持的链路类型](#supported-link-types)
- [计划](#plans)
- [许可证](#license)
## 概述
OxidizedRelay 从提供的 .pcap 文件中拼装 TCP 连接,根据流的密钥使用 ChaCha20 加密 (RFC 7539) 解密每个帧的有效载荷,分析二进制协议格式和 CSHead protobuf 头部,通过 CRC 校验验证 body 的完整性,并以可读的方式打印输出,还可以选择将字段映射到你自己的 .proto schema 文件。
## 加密方案
| 参数 | 值 |
|-----------|-------|
| 加密算法 | ChaCha20 (RFC 7539) |
| 密钥长度 | 32 字节 |
| Nonce 长度 | 12 字节 |
| 首个块索引 | 1(索引 0 被保留,AEAD 标准) |
| 密钥流生成 | 在 TCP 方向上连续(不会为每个帧重新生成) |
### 帧结构布局
```
┌──────┬─────────────────┬─────────────────────────────┐
│ hl │ bl (u16 LE) │ head[hl] || body[bl] │
│ (u8) │ │ ← encrypted together ──► │
└──────┴─────────────────┴─────────────────────────────┘
```
- `hl`:CSHead protobuf 部分的长度
- `bl`:消息 body 的长度
- head + body 拼接后与当前密钥流位置进行异或 (XOR) 运算
- `CSHead.checksum` 是已解密 body 的 CRC-32/IEEE 校验和
### CSHead Schema
```
syntax = "proto3";
message CSHead {
int32 msgid = 1;
uint64 up_seqid = 2;
uint64 down_seqid = 3;
uint32 total_pack_count = 4;
uint32 current_pack_index = 5;
bool is_compress = 6;
uint32 checksum = 7;
}
```
## 构建
要求:Rust 1.75+(通过 [rustup](https://rustup.rs) 安装)
```
git clone https://github.com/Yoshk4e/OxidizedRelay.git
cd OxidizedRelay
cargo build --release
# 二进制文件位于:target/release/OxidizedRelay
```
## 用法
```
OxidizedRelay [OPTIONS]
```
### 参数
| 参数 | 描述 |
|----------|-------------|
| `` | 输入 .pcap 文件的路径(pcapng 必须事先进行转换) |
### 选项
| 标志 | 缩写 | 描述 |
|------|-------|-------------|
| `--key ` | `-k` | 会话密钥,为 64 字符的十六进制字符串(32 字节)。如果省略,将进行交互式提示。 |
| `--iv ` | `-i` | 加密 IV/nonce,为 24 字符的十六进制字符串(12 字节)。如果省略,将进行交互式提示。 |
| `--host ` | | 仅处理一端匹配此 IP 的 TCP 流。 |
| `--proto ` | | 用于命名字段解码的 .proto 文件路径。 |
| `--msgid-map ` | | 映射 msgid:TypeName 对的文件路径(每行一对)。与 `--proto` 搭配使用时必需。 |
| `--plaintext-frames ` | | 每个流中视为明文的前导帧数量(默认:1)。 |
| `--show-invalid` | | 同时显示未通过 CSHead 解析或 CRC 校验的帧。 |
| `--raw` | | 转储每个帧解密后的十六进制字节。 |
## 示例
### 交互式输入 key/IV
```
OxidizedRelay capture.pcap
# → 提示输入 session key 和 IV
```
### 内联 key/IV 并使用服务器过滤
```
OxidizedRelay capture.pcap \
--key a3f1...64hexchars...9c2d \
--iv 00000000deadbeefcafebabe \
--host 192.168.1.100
```
### 使用 proto schema 获取可读的字段名
```
OxidizedRelay capture.pcap \
--key a3f1...64hexchars...9c2d \
--iv 00000000deadbeefcafebabe \
--host 192.168.1.100 \
--proto game_messages.proto \
--msgid-map msgid_map.txt
```
`msgid_map.txt` 格式,每行一个映射:
```
1001:LoginReq
1002:MoveReq
2001:LoginResp
2002:ChatMsg
```
### 显示所有内容包括无效帧
```
OxidizedRelay capture.pcap -k -i --show-invalid --raw
```
### pcapng → pcap 转换
OxidizedRelay 仅接受传统的 .pcap 格式。请事先进行转换:
```
tshark -F pcap -r input.pcapng -w output.pcap
```
## 输出格式
```
╔════════════════════════════════════════════════════════════════════════╗
║ TCP Stream 192.168.1.50:54321 → 192.168.1.100:8080 (42 frames) ║
╚════════════════════════════════════════════════════════════════════════╝
▶ Frame #1 encrypted │ msgid: 1001 (LoginReq)
──────────────────────────────────────────────────────────────────────
[CSHead]
msgid: 1001
up_seqid: 1
down_seqid: 0
total_pack_count: 1
current_pack_index: 0
is_compress: false
checksum: 0xA1B2C3D4 ✓
[Body: LoginReq]
account_id (1): 123456789
token (2): "eyJhbGciOiJSUzI1NiJ9..."
platform (3): 2
```
除非传递了 `--show-invalid` 参数,否则未能通过帧格式验证或 CRC 校验的帧将被静默跳过。最后将打印出汇总信息:
```
══════════════════════════════════════════════════════════════════════
Summary total=247 valid=241 crc_fail=3 skipped=3
══════════════════════════════════════════════════════════════════════
```
## 帧过滤的过程
如果满足以下任一条件,该帧将被静默过滤掉(除了使用 `--show-invalid` 标志时):
1. 解密后的头部数据无法解析为合法的 protobuf 消息,或者缺少字段 1 (msgid)。
2. 解密后有效载荷的 CRC-32/IEEE 校验和与 `CSHead.checksum` 不一致。
这可以被视为一个自动过滤过程,因此随机垃圾数据或 TLS 流量,甚至来自其他 TCP 连接的帧,都不会具备合法的 CSHead 结构和正确的校验和,从而被过滤掉。
## Proto Schema 加载
如果同时提供了 `--proto` 和 `--msgid-map` 标志,OxidizedRelay 会在运行时利用 protox 加载提供的 .proto 文件(无需安装 protoc)。字段名将通过加载的描述符确定,并叠加到被解码的输出 body 字段上。
如果没有 schema,解码后的 body 字段名将以 `field_N` 的形式输出,并附带原始字节值。嵌套的消息体将被递归解码,其中长度分隔的字段将通过启发式方法解码为文本 → 嵌套 proto → 字节。
## 支持的链路类型
| pcap 数据链路类型 | 备注 |
|---------------|-------|
| `ETHERNET` | 标准以太网 II |
| `LINUX_SLL` | Linux 聚合捕获(任意接口) |
| `NULL / LOOP` | BSD 环回(剥离了 4 字节 AF 头部) |
| `RAW` | 原始 IP |
## 计划
- **CS/SC 过滤器:** 实现过滤功能,以区分并分别处理客户端到服务器 (CS) 和服务器到客户端 (SC) 的流量,并提供针对每个方向帧的有组织且结构化的表示。
## 许可证
本项目基于 [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl-3.0.html) (AGPL-3.0) 授权。
您可以自由使用、修改和分发本软件,但在网络上运行的任何修改版本也必须在相同的许可证下公开。
标签:ChaCha20, PCAP, Protobuf, Rust, 二次元游戏, 二进制分析, 云安全运维, 可视化界面, 数据包重组, 游戏安全, 网络安全, 网络流量审计, 解密, 通知系统, 防御绕过, 隐私保护