waterbili/ruishu-re/agentskill

Claude Code and agent skill by waterbili/ruishu-re

Trust tier 3
  • community
  • ext:[{"type":"plugin","description":"Custom plugin integration"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

瑞数(Ruishu/Rivers Security)反爬防护纯算逆向 — Cookie T 生成 + URL 后缀处理

Install

npx vskill@latest install waterbili/ruishu-re/agentskill

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

瑞数反爬纯算逆向 Skill

目标: 任何 Claude 实例读完本文档, 都能独立完成瑞数保护站点的 Cookie T 纯算生成 + URL 后缀处理。
已验证: 9+ 站点 HTTP 200。

决策树

拿到目标 URL 后, 按此流程选择方案:

1. HTTP GET 目标 URL
├── 非 412 → 不是瑞数防护, 退出
└── 412 + $_ts.cd + $_ts.nsd → 确认瑞数
│
2. 是否只需 GET 请求?
├── 是 (80%场景) → 纯算方案 [阶段 0→5]
└── 需要 POST
│
3. POST 是否需要 URL 后缀?
├── 不需要 (99%站点) → 纯算 Cookie + 普通 POST [阶段 0→5]
└── 需要后缀
├── 稳定方案 → JsRpc (浏览器注入, 通杀)
└── 轻量方案 → sdenv VM 内 XHR (单次POST后需重建实例)

快速验证是否需要后缀: 纯算 Cookie T + 普通 POST → 200 则不需要, 400/412 则需要。


防护原理 (精简版)

浏览器 GET → 412 + HTML (含 $_ts.nsd, $_ts.cd, mainjs URL, Set-Cookie: xxxS=...)
↓
mainjs 执行 → 解码 cd → 提取 45 组 keys + VM 字节码
↓
动态生成 ~296KB eval 代码 (变量名由 nsd 种子决定, 每次不同)
↓
eval 执行 → 三层嵌套 VM → 收集指纹 → 组装 basearr (154-166B TLV)
↓
basearr → Huffman → XOR → AES-CBC → CRC32 → AES-CBC → Base64 → Cookie T
↓
浏览器带 Cookie S+T 重新 GET → 200

我们纯算替代的部分:

浏览器做的纯算替代阶段详情
mainjs → eval 代码Coder 重写3coder_rewrite.md
cd → 提取 keysextractKeys2key_extraction.md
VM 收集指纹 → basearr数据驱动适配4basearr_adaptation.md
basearr → 加密 → Cookie TgenerateCookie1encryption_chain.md

阶段总览

阶段输入输出验证标准通用?
0 侦察目标 URL412 HTML + mainjs + Cookie S + sdenv 参考数据sdenv Cookie → 200通用
1 加密链sdenv Cookie T + keysgenerateCookie(basearr, keys) → Cookie Tsdenv basearr + 纯算加密 → 200通用, 一次性
2 密钥提取$_ts.cdkeys[0..44] (45 组)keys 和 sdenv 提取的一致通用, 一次性
3 Codermainjs + nsd + cdeval 代码 + codeUid + functionsNameSorteval 代码逐字节一致通用, 一次性
4 basearr参考数据 + keysbuildBasearr(config, keys) → basearr纯算全链路 → 200每站点 ~1h
5 端到端全部纯算 HTTP GET → 200连续 3+ 次 200组装即可

执行顺序: 严格 0 → 1 → 2 → 3 → 4 → 5, 每步验证通过后再进下一步。


方法论

数据驱动 (用于 Cookie T / basearr — 最重要!)

核心: 用 sdenv 采集 3-5 组真实数据 → 逐字节对比 → 找到每个字节的来源。绝对不要去读内层 VM 代码 (740 个 state, 三层嵌套 — 这是陷阱)。

采集 5 session → 每个 TLV 字段拆开 → 逐字节标注:
固定 (所有 session 相同) → 硬编码
来自 keys (匹配 keys[N]) → 动态提取
时间相关 (有规律变化) → 找公式
随机 (无规律) → Math.random
未知 → 需更多数据或更深分析

真实经验: 花 2 天读 VM 代码完全浪费。转向数据驱动后, 1 天内解决所有问题。

AST 分析 (用于 URL 后缀 / eval code 函数)

核心: eval code 是合法 JS, 用 acorn 解析 AST → 建立 rt[N] 函数映射 → 递归追踪调用链 → 提取核心算法。几小时完成手工需要数周的工作量。

产出: 14 个 AST 工具, ~20h, 从 296KB 混淆代码中完整逆向后缀核心函数。详见 ast_methodology.md

方法选择表
目标在哪一层?用什么方法
eval code JS 函数AST (精确高效)
basearr 数据结构数据驱动 (快速可靠)
r2mKa VM 字节码AST 提取 opcode + 自动反汇编
运行时动态值 (时间戳等)sdenv 采集

弯路警告 (来自真实踩坑经验)

弯路代价正确做法
反编译内层 VM 理解 basearr2 天浪费数据驱动: 5 session 采集, 10 分钟解决
照搬 rs-reverse 公式 (idx*7+6 等)1 天白费数据驱动: 公式是版本特定的, 不通用
补环境跑 eval 代码document.all 需 C++ AddonCoder 重写 mainjs 逻辑
硬编码 type=2 值换 session 就错cp1 索引→值映射 (5 session 反推)
跳过混合验证直接做 basearr400 了不知道哪步错先 sdenv basearr + 纯算加密 = 200, 证明加密正确
运行时栈追踪反推 opcode 语义80B/天效率AST 静态提取: 400B/小时 (效率 80 倍)
HTTP 下载 mainjs 用 string 拼接UTF-8 多字节字符损坏Buffer 拼接 + toString('utf-8')

排错指南

返回 412 (Cookie 未被接受)
  1. Cookie 名是否正确? → keys[7].split(';')[5] + 'T', 不是硬编码
  2. Cookie S 是否一起发了? → 必须同时带 S 和 T
  3. Cookie T 格式? → 必须以 "0" 开头
  4. 时间是否过期? → Cookie 有效期通常 < 5 分钟, 检查 nonce 时间戳
  5. cd 和 Cookie S 是否配套? → 必须来自同一个 412 响应
返回 400 (Cookie 格式/内容错误)
  1. 加密链是否通过混合验证? → 先用 sdenv basearr + 纯算加密验证
  2. basearr 长度是否匹配? → 对比 sdenv 参考 (通常 154-166B)
  3. basearr TLV 是否有缺失字段? → 逐字段对比参考
  4. keys 提取是否正确? → keys[0] 应为 "64", keys[2] 应为 48B
  5. POST 是否需要 URL 后缀? → 先用 sdenv POST 测试确认
Coder 输出不匹配
  1. 逐字节对比找第一个差异位置:

``javascript for (let i = 0; i < Math.min(gen.length, ref.length); i++) { if (gen[i] !== ref[i]) { console.log('差异 @' + i + ':', JSON.stringify(gen.substring(i, i+60))); console.log('参考:', JSON.stringify(ref.substring(i, i+60))); break; } } ``

  1. 常见 6 个 bug:
  • opmate 数量: 5 个命名 + 1 个无名 = 6 (不是 7)
  • gren(0) 用全局 opmate, 不是局部
  • var 声明: 用 mate index 1 (不是 2)
  • while(1): 也用全局 opmate
  • _ifElse: start 变量在 for 中被修改, else 分支用修改后的 start
  • debugger: 每个 gren 段重建 PRNG(seed=nsd), posis 跨段累积
  1. 差 ~180 字符 → 大概率 debugger 对齐问题
Keys 提取失败
  1. keys[0] 是否 = "64" (ASCII [0x36, 0x34])?
  • 是 → XOR 偏移正确
  • 否 → 需要实现 r2mka runTask (难度高, 优先换站点验证)
  1. keys.length < 45 → XOR 偏移计算错误
  2. keys[29..32] 不是各 4B → 结构异常
type=2 值不匹配
  1. 不要硬编码! type=2 依赖 nsd → cp1 洗牌结果
  2. 采集 5 session, 记录 keys[29..32] 变量名 + type=2 值
  3. 在 cp1=grenKeys(keynameNum, nsd) 中查变量名索引
  4. 建立 cp1_index → value 映射表 (映射对同一 mainjs 版本固定)
  5. 使用脚本: scripts/collect_type2.js

站点适配 Checklist

适配新站点时, 逐项检查打勾:

  • [ ] 修改 HOST / PORT / PATH
  • [ ] sdenv 跑通 → 200 (确认是标准瑞数版本)
  • [ ] 混合验证通过 (sdenv basearr + 纯算加密 → 200)
  • [ ] flag 值: 从参考 basearr type=7 的 [8..9] 读取
  • [ ] type=9 格式: payload 是 2B [8,0] 还是 5B? 从参考读取
  • [ ] type=3 结构: 长度/字段数是否和模板一致? 逐字节对比
  • [ ] type=2 映射: 5+ session 采集, 建立 cp1 索引→值映射
  • [ ] Cookie 名后缀: 'T' 还是 'P'? 看 412 响应 Set-Cookie 头
  • [ ] hasDebug: 观察 eval 代码是否有 debugger 语句
  • [ ] keynameNum: 从 mainjs 正则提取 (通常 918)
  • [ ] 端到端验证: 连续 3+ 次 200

通用常量速查

javascript
// PRNG (所有版本通用)
seed = 15679 * (seed & 0xFFFF) + 2531011
// Huffman 权重 (所有版本通用)
byte=0 → weight=45, byte=255 → weight=6, 其余 → weight=1
// AES-128-CBC
外层: key=keys[16], IV=随机16B 内层: key=keys[17], IV=全零16B
// CRC32 多项式
0xEDB88320
// 自定义 Base64 字母表 (所有版本通用)
'qrcklmDoExthWJiHAp1sVYKU3RFMQw8IGfPO92bvLNj.7zXBaSnu0TC6gy_4Ze5d'
// BASESTR (cd 解码用, 比 Base64 字母表多 24 个字符)
'qrcklmDoExthWJiHAp1sVYKU3RFMQw8IGfPO92bvLNj.7zXBaSnu0TC6gy_4Ze5d{}|~ !#$%()*+,-;=?@[]^'
// getLine 乘数 (mainjs op88)
55295
// 变量名字符集
'_$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
// _ifElse 二叉搜索步长表
[4, 16, 64, 256, 1024, 4096, 16384, 65536]
// Cookie 名
keys[7].split(';')[5] + 'T'
// URL 后缀参数名
keys[7].split(';')[1]
加密管线 (7 步)
basearr (154-166B)
→ Huffman 编码 (~118B)
→ 前 16 字节 XOR keys[2][0:15]
→ AES-128-CBC (key=keys[17], IV=全零, PKCS7) → ~128B
→ 拼 packet: [2, 8, r2mkaTime(4B), now(4B), 48, keys[2](48B), lenEnc, cipher]
→ CRC32 → [crc(4B), packet] → ~193B
→ AES-128-CBC (key=keys[16], IV=随机16B, PKCS7) → ~224B
→ 自定义 Base64 → "0" + 299 字符
关键 Keys 含义
key长度含义用途
keys[2]48BKEYS48XOR 前 16B + packet 内嵌全部 48B
keys[7]变长配置串 (分号分隔)Cookie 名 [5]+'T', 后缀参数名 [1]
keys[16]16BKEY2外层 AES 密钥
keys[17]16BKEY1内层 AES 密钥
keys[19]变长时间戳串type=10[6..9]
keys[21]变长r2mkaTime 串nonce 时间
keys[22]变长加密数据type=6 AES 解密
keys[24-26]变长数值串type=10 参数
keys[29-32]各 4B变量名type=2 映射 (cp1 索引→值)
keys[33-34]变长数值串codeUid 计算参数

变量名变化警告

瑞数的变量名不是固定的! nsd 不同 → grenKeys(918, nsd) 洗牌不同 → eval 代码中所有变量名变化。

Session 1 (nsd=84277): _$eX, _$hR, _$cR, _$bO ...
Session 2 (nsd=91234): _$f3, _$gT, _$aK, _$dP ...

hook 定位必须用结构特征, 不用变量名:

javascript
// ❌ 错误: 用变量名 (下次就变了)
const target = 'function _$hr(){var _$jZ=[324];';
// ✅ 正确: 用结构特征 (永远不变)
const statePattern = /function\s+(_\$\w+)\(\)\{var\s+(_\$\w+)=\[324\]/;
// ✅ 正确: 用代码长度
if (code.length > 250000) { /* 这是 eval 代码 */ }
// ✅ 正确: 用常量特征
if (code.includes('15679') && code.includes('2531011')) { /* 找到 PRNG */ }

工具依赖

工具安装用途阶段
Node.js crypto/http内置AES 加解密, HTTP 请求全部
sdenvnpx pnpm add sdenv参考数据采集, VM 内 XHR0, 4, 6
js-beautifynpm i js-beautify格式化 mainjs (可选)3
acorn + acorn-walknpm i acorn acorn-walkAST 分析 (后缀逆向)6

注意: npm 11.x + Node 24 有依赖解析死循环 bug, 安装 sdenv 必须用 pnpm。 编译原生模块需要 VS Build Tools (Windows) 或 gcc (Linux)。


配套数据采集 (阶段 0 核心)

瑞数的变量名每次加载都不同! 必须在同一个 session 中采集全套配套数据。
分开采集 (先拿 412, 再拿 mainjs) 的话 nsd 已经变了, 数据对不上!

使用 scripts/collect_session.js 一次性采集:

captured/
├── session.json nsd + cd + Cookie S/T + basearr + 时间戳
├── keys_raw.json 45 组密钥 (index + length + data)
├── ts_init.js $_ts 初始化脚本 (含 cd)
├── eval_code.js 296KB eval 代码 (配套变量名)
└── mainjs.js mainjs 源码 (静态, 可单独下载)

文件索引

详细参考 (按需加载)
文件内容
references/encryption_chain.md阶段 1: Huffman/AES/CRC32/Base64 完整加密解密实现
references/key_extraction.md阶段 2: cd 解码 + XOR 偏移推导 + 45 组 keys 提取
references/coder_rewrite.md阶段 3: 外层 VM 重写 + 75+55 opcode + 9 步调试过程
references/basearr_adaptation.md阶段 4: TLV 结构 + 每个 type 实现 + 数据驱动案例
references/ast_methodology.mdAST 反编译 4 步流水线 + 14 个工具 + 方法对比
references/vm_hook_cookbook.md7 种 VM 注入技术 + console 侧信道导出
references/suffix_analysis.mdURL 后缀 88B/120B 结构 + SHA-1 签名 + 现有方案
可执行脚本
文件用途
scripts/collect_session.js配套数据一次性采集 (sdenv + VM 注入)
scripts/hybrid_verify.js混合验证: sdenv basearr + 纯算加密 → 200
scripts/pure_run.js纯算全流程模板 (零第三方依赖)
scripts/collect_type2.jstype=2 多 session 采集 + 映射推导
scripts/sdenv_client.jssdenv 客户端 (Cookie + VM 内 XHR)
参考实现
文件说明
lib/coder.js外层 VM 重写器 (362 行, 验证: eval 代码 100% 字节一致)
lib/basearr.jsbasearr 生成器 (304 行, 验证: HTTP 200)

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
57
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Extension points

  • pluginCustom plugin integration

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/waterbili/ruishu-re/agentskill/badge)](https://verified-skill.com/skills/waterbili/ruishu-re/agentskill)

Something wrong with this skill or its page? Tell us.