carcabot/tiktok-xgnarly-decoded
GitHub: carcabot/tiktok-xgnarly-decoded
对 TikTok X-Gnarly 请求签名的完整逆向工程,提供纯 JavaScript 的编码器和解码器实现,帮助研究人员理解和分析该签名机制的每一个细节。
Stars: 2 | Forks: 1
# tiktok-xgnarly-decoded
对 TikTok 的 `X-Gnarly` 请求签名的完整逆向工程,包含可用的纯 JavaScript 参考编码器和解码器。无需原生绑定,无需无头浏览器,无需混淆包——传输格式的每一个字节都已解析。
## 什么是 X-Gnarly?
`X-Gnarly` 是 TikTok 的 Web 客户端(`webmssdk` / `secsdk`)附加到 API 调用上的请求参数。它是一个类似 base64 的数据块(当前的 ZTCA payload 大小约为 332 个字符),包含:
- 一个包含 16 个字段的 TLV payload(时间戳、计数器、URL/body/UA 的 MD5、SDK 版本、两个随机 uint32,以及一个将所有整数联系在一起的 XOR header),
- 由 48 个随机字节作为密钥生成的 ChaCha 风格流密码输出,这 48 个字节本身通过校验和计算的偏移量嵌入到了密文中,
- 一个开头的魔数(Magic byte)(`'K'` = 75),以便解码器可以快速失败。
本仓库详细介绍了每一个步骤,并提供了一个大小适中、足够在一个下午阅读完毕的实现。
## 涵盖的版本
X-Gnarly 签名已在多个内部版本标签下发布。本项目追踪了以下完整范围内的传输格式;`src/` 中的参考实现与 **5.1.3-ZTCA** 逐字节对应。
**X-Gnarly payload 版本(TLV 字段 9):**
- `5.1.3-ZTCA` *(当前版本 — 本仓库的参考向量)*
- `5.1.3`
- `5.1.2`
- `5.1.1`
- `5.1.0`
- `5.0.x`
**观察到携带 X-Gnarly 的 `webmssdk` 宿主包版本:**
- `webmssdk 1.0.0.211`
- `webmssdk 1.0.0.224`
- `webmssdk 1.0.0.368` *(`encode.js` 中的默认 `sdkVersion`)*
- `webmssdk 1.0.0.4xx`
- `webmssdk 2.0.0.485`
- `webmssdk 2.0.0.485-ZTCA`
在我们观察到的从 `1.0.0.211` 到 `2.0.0.485-ZTCA` 的每一个 `webmssdk` 构建版本中,自定义 base64 字母表、魔数(`'K'` / 75)和 ChaCha 核心一直**保持稳定**。TLV 字段集和轮次推导方案才是不断演进的部分。
## 相关的 TikTok 签名参数
对于通过搜索引擎来到这里的读者——X-Gnarly 是 TikTok 的 Web 和移动端技术栈发出的几种签名之一。它们*不可*互换,但经常在流量抓包中同时出现,并且可以使用相同的逆向工程技术:
| Header / param | Surface | 说明 |
|---|---|---|
| `X-Gnarly` | web (`webmssdk`) | 本仓库。ChaCha-XOR + TLV。 |
| `X-Bogus` | web (`acrawler`) | 前身;类 AES + base64。 |
| `X-Argus` | 移动端 | Protobuf payload,原生库。 |
| `X-Ladon` | 移动端 | 基于 `X-Khronos` + sec_device_id 的 XOR。 |
| `X-Khronos` | 移动端 | Unix 时间戳。 |
| `X-Gorgon` | 移动端(旧版) | 基于 MD5,在较新的构建版本中已弃用。 |
| `X-Mssdk-Info` | web | 来自 `webmssdk` 的配套遥测数据。 |
| `X-TT-Params` | web | AES-128-CBC 加密的查询字符串。 |
| `msToken` | web + 移动端 | 服务器颁发的防重放 token。 |
| `ttwid` | web | 基于 Cookie 的会话/设备 ID。 |
此处仅实现了 `X-Gnarly`。
## 快速开始
```
import { encode, decode } from "./src/encode.js";
const xgnarly = encode(
// queryString: the URL's `?...` portion, minus the leading '?',
// with msToken substituted in and X-Bogus / X-Gnarly stripped.
"aid=1988&app_language=en&...",
// body: empty string for GET, the raw body for POST.
"",
// navigator.userAgent at sign time.
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...",
// secsdk request counters; small ints are fine off-page.
{ totalXHRRequests: 3, totalFetchRequests: 1 },
);
const { fields, keyStart, rounds } = decode(xgnarly);
console.log(fields[9]); // "5.1.3-ZTCA"
console.log(fields[10]); // "1.0.0.368"
```
运行往返 + 已知向量测试:
```
node --test test/
```
## 项目结构
```
src/
alphabet.js custom base64 alphabet used by webmssdk
cipher.js ChaCha-style stream cipher + round derivation
payload.js 16-field TLV encoder / decoder
encode.js producer (encode → cipher → embed key → base64)
decode.js consumer (base64 → recover key by brute-force keyStart → decrypt → parse)
test/
roundtrip.test.mjs encode → decode round-trip on synthetic inputs
vectors.test.mjs decode of a real captured X-Gnarly with field-by-field assertions
examples/
verify-real.mjs pretty-print a captured X-Gnarly's fields
```
## TLV 字段参考
| # | 类型 | 含义 |
|---|---|---|
| 0 | uint | XOR header(所有整数字段的异或结果,**最后**写入) |
| 1 | uint | 常量 `65` |
| 2 | uint | `ubcode` — 端点类别(`/api/post/...` 的默认值为 `4`) |
| 3 | str | MD5(queryString) — 十六进制 |
| 4 | str | MD5(body) — 十六进制;GET 请求时为 `""` |
| 5 | str | MD5(userAgent) — 十六进制 |
| 6 | uint | `floor(now / 1000)` — Unix 秒数 |
| 7 | uint | 写入 SDK 的构建时哈希值(观察到为 `3181061566`) |
| 8 | uint | `now % 0x80000000` — 毫秒时间戳的低 31 位 |
| 9 | str | X-Gnarly payload 版本(如 `5.1.3-ZTCA`) |
| 10| str | `webmssdk` SDK 版本(如 `1.0.0.368`) |
| 11| uint | 常量 `1` |
| 12| uint | 拦截的总请求数(XHR + fetch) |
| 13| uint | 字段 12 的伴随计数对 |
| 14| uint | 高 16 位 = 字段 1 << 16;低 16 位 = 随机值 |
| 15| uint | 完整的 uint32 随机值 |
## 免责声明
本仓库以 MIT 协议发布,仅供**研究、教育、安全分析和互操作性**之用。它不包含 TikTok 的专有代码;每一个字节都是独立地从公共网络流量和对公开发布的 `webmssdk` 包的净室逆向中重新推导出来的。
- 使用它来了解现代客户端请求签名的工作原理。
- 使用它来验证捕获的 X-Gnarly 是否由真正的 SDK 构建版本发出。
- **请勿**将其用于绕过速率限制、在生产端点上规避机器人防护、进行工业规模的抓取,或以其他方式违反 TikTok 的服务条款或适用法律(如 CFAA、DMCA §1201、GDPR 等)。
维护者不隶属于 TikTok、ByteDance 或其任何子公司。诸如 `webmssdk`、`secsdk`、`ZTCA`、`X-Gnarly`、`X-Bogus`、`X-Argus`、`X-Ladon`、`X-Khronos`、`X-Gorgon` 和 `msToken` 等名称在此仅用于标识正在研究的协议。
## 许可证
MIT — 详见 [许可证](./LICENSE)。
标签:Base64, ChaCha, CMS安全, JavaScript, TikTok, webmssdk, Web安全, X-Gnarly, 云资产清单, 加解密, 协议分析, 数据可视化, 权限提升, 流密码, 算法还原, 自定义脚本, 蓝队分析, 请求签名, 逆向工程