基于GLM-5.2的X-Gnarly(332位)纯算还原分析"

admin 2026-10-18 09:03:47 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

基于 GLM-5.2 的 X-Gnarly (332位) 纯算还原分析

红皮西瓜
红皮西瓜

看雪学苑

2026年7月28日 17:59
上海

在小说阅读器读本章

去阅读

目标接口:/api/post/item_list 签名参数:X-Gnarly(332 字符) SDK 版本:webmssdk 5.2.1 方法与工具:fast-spider skills 工作流 + GLM-5.2 辅助分析 + 语义级插桩

一、背景

在 TikTok Web 端中,访问 /api/post/item_list 等核心接口通常需要两个关键的签名参数:

  • X-Bogus

长度为 28 字符,一般非强制校验。
* X-Gnarly

长度为 332 字符,必须有效,服务端会对其进行多重深度校验。

X-Gnarly 参数由 webmssdk.js(byted\_acrawler SDK)动态计算生成。由于该 SDK 采用了 JSVMP(JavaScript VM Protection)混淆技术,其实际执行算法被编译为约 44KB 的字节码,源码中仅包含解释器内核,静态分析难以直观还原其明文逻辑。

本篇报告记录了如何利用 fast-spider skills 工作流,在 GLM-5.2 的辅助推理下,从 trace 日志中逐步还原出 X-Gnarly 的完整生成链路,并完成纯 JavaScript 算法复现的过程。

二、方法:fast-spider skills + 语义插桩

2.1 基础分析工作流

初始化环境 (init) → 捕获 SDK (capture) → 制定运行策略 (runbook) → 采集 trace → 逻辑分析 (analyze) → 制定方案 (plan) → 补全算法 (fill) → 对拍校验 (verify)

2.2 针对 JSVMP 混淆的增强策略

传统的补环境方案(如 FakeEnv 或 Node vm 模拟)在面对该级别的混淆时,往往因为大量未知的浏览器特征检测而难以推进。因此,本方案采用语义级插桩思路:

  • 动态插桩脚本

(基于工作流中的 patch_sdk.js):通过源码级特征匹配,定位 webmssdk.js 中的核心执行位置,在每个 .call()、.apply() 以及关键二元/三元运算处注入 __tk_log 记录器,自动输出函数对象、调用参数、返回值及运算轨迹。
* Playwright 动态替换

使用拦截代理,将页面请求的线上 CDN 脚本无缝替换为本地生成的插桩版 SDK。

通过这一方法,单次流程可稳定产出约 28 万行语义日志,为后续算法推导提供了坚实的数据支撑。

三、算法全链路设计

X-Gnarly 的生成可以划分为以下 4 个阶段:

(query, UA, ts)
│
▼  阶段 1:TLV 序列化
200 字节明文数据
│
▼  阶段 2:ChaCha 变种流加密
200 字节密文数据
│
▼  阶段 3:W 字节拼装 (嵌入 48 字节 Key)
248 字节拼装数据 (W)
│
▼  阶段 4:自定义 Base64 编码
332 字符 X-Gnarly 签名

四、阶段 1:TLV 序列化(→ 200 字节明文)

4.1 构建 17 元素原始数组

算法首先在内存中收集并构建一个包含 17 个元素的混合数组:

const arr = [
0,              // tag0: num0 (全局数字校验和,待后续计算)
73,             // tag1: 固定常量
14,             // tag2: 固定常量
    qsHash,         // tag3: md5(queryString) 结果
    md5(''),        // tag4: md5(空字符串) = 'd41d8cd98f00b204e9800998ecf8427e'
    md5(UA),        // tag5: md5(User-Agent) 结果
    ts,             // tag6: 秒级时间戳(10位整数)
    A,              // tag7: 固定常量
    B,              // tag8: 固定常量
'5.2.1',        // tag9: SDK 版本号
'2.0.0.493',    // tag10: webmssdk 内部版本号
1,              // tag11: 固定常量
    T12,            // tag12: 固定常量
    T13,            // tag13: 固定常量
    M1,             // tag14: 固定常量
    M2,             // tag15: 固定常量
    num15,          // tag16: 内部校验和
];

4.2 校验和算法

在进行洗牌前,需要计算数组中的两个校验和:

4.3 LCG 洗牌机制 (Fisher-Yates Shuffle)

基于线性同余生成器(LCG)生成的伪随机数对上述数组进行倒序洗牌:

let seed = B; // 初始种子来源于 tag8 对应的固定常量
const multiplier = 1664525;
const increment = 1013904223;
const modulus = Math.pow(2, 32);

for (let i = arr.length - 1; i > 0; i--) {
    seed = (multiplier * seed + increment) % modulus;
const targetIndex = Math.floor((seed / modulus) * (i + 1));
// 交换位置
const temp = arr[i];
    arr[i] = arr[targetIndex];
    arr[targetIndex] = temp;
}

4.4 TLV 序列化打包

洗牌完成后的数组将被转化为 TLV(Type-Length-Value)二进制流:

  • 结构布局:[Tag (1B)] [Length_Hi (1B)] [Length_Lo (1B)] [Value (NB)]
  • 编码规则:对于整数类型,若 ≤0xFFFF\le 0xFFFF≤0xFFFF 采用 2 字节大端表示,若 >0xFFFF> 0xFFFF>0xFFFF 则采用 4 字节大端表示;字符串统一采用 UTF-8 编码。
  • 头部标识:整个二进制流的第 1 字节记录了字段总数(即固定的 0x11 / 17 个字段)。

最终输出:200 字节明文字节数组。

五、阶段 2:ChaCha 变种加密(→ 200 字节密文)

5.1 矩阵状态初始化 (16 Words / 64 Bytes)

加密状态矩阵的 16 个 32位 Word 布局如下:

[0..3]  = OT = [1196819126, 600974999, 3863347763, 1451689750]  // 4 个固定状态字
[4..15] = key48 的 12 个 Little-Endian Word // 48 字节固定 Key

5.2 动态加密轮数计算

轮数由初始 key48 决定。由于本方案中 key48 采用提取自真机环境的静态常量,其推导轮数亦维持不变:

5.3 核心 Quarter Round (QR) 实现

QR 结构与标准 ChaCha 保持一致,保留了经典移位常数:

function quarterRound(x, a, b,c, d){
    x[a]=(x[a]+ x[b])|0;  x[d]= rotl32(x[d]^ x[a],16);
    x[c]=(x[c]+ x[d])|0;  x[b]= rotl32(x[b]^ x[c],12);
    x[a]=(x[a]+ x[b])|0;  x[d]= rotl32(x[d]^ x[a],8);
    x[c]=(x[c]+ x[d])|0;  x[b]= rotl32(x[b]^ x[c],7);
}

5.4 魔改对角线变换 (Diagonal Round)

这是 webmssdk 对经典 ChaCha 算法做出的核心修改。对比标准对角线变换索引,本版本进行了如下替换:

该修改打破了标准 ChaCha 算法原有的对称扩散特性,需在重构时严格遵循变种索引。

5.5 块流处理与 Feed-Forward

分块对 200 字节明文执行流加密(每块 64 字节):

  • 拷贝当前 state 矩阵副本。
  • 依次进行列变换与变种对角线变换,交替执行 rounds 轮。
  • 加密完毕后,执行 Feed-Forward 累加操作以生成最终密钥流块:
    keystream[j]=(transformed[j]+initial[j])∣0\text{keystream}[j] = (\text{transformed}[j] + \text{initial}[j]) \mid 0keystream[j]=(transformed[j]+initial[j])∣0
  • 初始状态矩阵中的 state[12] (counter) 递增,用于下一块计算。
  • 将得到的密钥流与明文块按字节进行异或。

最终输出:200 字节密文数组。

六、阶段 3:W 字节拼装(→ 248 字节)

6.1 分割点计算

分割索引依据密文及 key48 数据之和求模动态计算:

6.2 拼接融合

将 48 字节的 key48 插入到密文字节流的分割点处,构建合成数组 W:

最终输出:248 字节的数据块。

七、阶段 4:自定义 Base64 编码(→ 332 字符)

7.1 添加协议前缀

在数据块头部附加固定标识 0x4B(字符 'K'):

7.2 变种 Base64 转换

使用指定的自定义字母表进行标准的 3 字节至 4 字符转换(转换过程中无填充字符 =):

  • 自定义字母表(64 字符):

u09tbS3UvgDEe6r-ZVMXzLpsAohTn7mdINQlW412GqBjfYiyk8JORCF5/xKHwacP=
* 编码转换逻辑:

最终输出:332 字符长度的有效 X-Gnarly 签名。

八、常量与动态变量对照

为保持长期调用的稳定性,算法实现中明确区分了动态变量与静态常量:

参数类型 字段明细 处置策略
动态输入 queryString (URL 查询参数), userAgent (浏览器 UA), ts (当前时间戳) 随每次请求实时生成,用于计算数组中的 Tag 字段
固定参数 状态矩阵 OT, 加密密钥 key48, rounds, 变量 A, B, M1, M2, T12, T13 采用从真机 trace 日志中分析固定的静态数值,降低运行时的环境依赖风险

九、对拍验证流程

9.1 校验路径

  • Playwright 加载目标页面,利用代理机制将 webmssdk.js 重定向至本地插桩版。
  • 触发 API 请求,捕获签名过程中的 trace 日志。
  • 从控制台捕获的最终 X-Gnarly 反解出 249 字节,恢复出相应的密文与 key48,直至还原明文 TLV。
  • 运行纯 JS 复现程序,对比复现产物与浏览器端生成的结果是否完全对齐。

9.2 对拍结果

测试批次 key48 摘要 加密轮数 变量 B splitIndex 复现结果一致性
trace4 e0671fe6... 17 354945180 38 ✅ 一致
trace6 098bf137... 11 1316161044 194 ✅ 一致

十、复现实现与调用

10.1 本地调用示例 (Node.js)

const { generateXGnarly } = require('./registry/tiktok/xgnarly521.js');

const query = 'WebIdLastTime...msToken..';
const ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)...';
const timestamp = Math.floor(Date.now() / 1000);

const xGnarly = generateXGnarly(query, ua, timestamp);
console.log('Generated X-Gnarly:', xGnarly); // 输出 332 字符的签名

10.2 发包验证测试 (Python)

from curl_cffi import requests

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)...',
# ... 其他必要请求头
}

url = f'https://www.tiktok.com/api/post/item_list/?{query}&X-Bogus=&X-Gnarly={x_gnarly}'
resp = requests.get(url, headers=headers, impersonate='chrome120')
print(\"Status:\", resp.status_code)
# 数据成功解包说明签名通过深度校验

十一、逆向方法论总结

11.1 突破 JSVMP 的静态阻碍

面对包含数百个虚拟机操作码分支及复杂分发循环的 JSVMP 保护,完全依赖静态反汇编分析极易陷入迷局。此时,借助 GLM-5.2 的代码分析与逻辑整合能力,配合同步插桩方案,是定位真实解密链路的高效途径。

11.2 语义日志的解构价值

通过自动向执行单元添加插桩,能够避开虚拟机内部繁琐的操作码转换,直接将寄存器数值与函数交互以自然语言级别记录下来。这不仅极大地缩短了逆向周期,而且保证了底层逻辑还原的准确性。

看雪ID:红皮西瓜

https://bbs.kanxue.com/user-home-1046416.htm

\*本文为看雪论坛优秀文章,由 红皮西瓜 原创,转载请注明来自看雪社区

第十届安全开发者峰会【议题征集】-欢迎投稿

往期推荐

ISCC 2026 题目 [house of apple 2] 利用方法

Android 内核无痕 Hook 框架设计思路和避坑经验

从零手写 ARM64 自定义 Linker

从2026CCB决赛堆题CreditMarket学习Glibc2.39后ptmalloc的机制更新

2019-SUCTF-SUDriver 学习笔记

球分享

球点赞

球在看

点击阅读原文查看更多


基于GLM-5.2的X-Gnarly(332位)纯算还原分析" 网络安全文章

基于GLM-5.2的X-Gnarly(332位)纯算还原分析"

本文详细记录了利用GLM-5.2辅助分析和语义级插桩技术,逆向还原TikTokWeb端X-Gnarly签名算法(332位)的完整过程。算法分为TLV序列化、ChaCha变种加密、W字节拼装和自定义Base64编码四个阶段。通过动态插桩突破JSVMP混淆,成功复现了纯JavaScript算法,并验证了其与浏览器端生成结果的一致性。该方法为分析类似混淆保护提供了高效路径。
突发!libssh2曝四枚高危漏洞,恶意SSH服务器可操控客户端内存" 网络安全文章

突发!libssh2曝四枚高危漏洞,恶意SSH服务器可操控客户端内存"

libssh21.11.1及更早版本曝出四个高危漏洞,两个可在认证前触发。攻击者通过恶意SSH服务器能引发客户端内存破坏,导致代码执行或拒绝服务。受静态链接影响,漏洞面极广且易被忽视。建议立即升级至最新版,利用命令扫描静态链接资产,无法升级时须限制连接可信服务器或部署堡垒机过滤,以阻断风险。
防勒索阻入侵火绒打造轻量化企业安全运维防线" 网络安全文章

防勒索阻入侵火绒打造轻量化企业安全运维防线"

针对勒索病毒与内网攻击频发现状,本文介绍了火绒终端安全系统的三项更新:新增工具软件行为监控防范恶意投递、开放API与流量标签打通NAC和SIEM集成、以及修复Nginx高危漏洞并升级勒索拦截能力。建议企业扩展防护至工具软件,利用接口实现数据联动,及时修复漏洞。
AI安全风口红利期!CISP-AISA解锁网络安全新赛道" 网络安全文章

AI安全风口红利期!CISP-AISA解锁网络安全新赛道"

本文推广CISP-AISA注册人工智能安全评估专业人员认证,由中国信息安全测评中心推出,旨在培养AI安全评估人才。文章强调该认证的官方权威性、全岗位适配性、实战化课程体系及低门槛报考优势,并介绍培训机构谷安天下的服务。核心建议是抓住AI安全风口,通过考取该认证提升职场竞争力。
评论:0   参与:  0