- 解包 tcaptcha-frame bundle,圈定 122 个模块中的核心加签与通信模块 - 还原 __TENCENT_CHAOS_VM 架构:映射全部 70 个操作码语义并实现字符串折叠反汇编 - 提取 246 个核心字符串,全量排查并枚举 95 项环境检测与自动化探针特征 - 实现零浏览器依赖的深度 Proxy 探针,原生生成与会话自洽的 collect 与 eks
5.8 KiB
5.8 KiB
腾讯验证码 (TCaptcha / TDC) 逆向工具链建设与协议解构报告
依据 AGENTS.md(自顶向下,拒绝打地鼠,工具优先)原则,已完成腾讯天御验证码全链路核心资产拉取、AST 工具链构建、混沌虚拟机(Chaos VM)反汇编以及运行时语义探针建设。
一、已建成的工具集清单
| 工具 | 路径 | 核心功能 | 解决什么问题 |
|---|---|---|---|
| Webpack 解包索引器 | tools/unpack_webpack.js |
将 230KB 单文件 bundle 拆解为 122 个独立模块,建立加签/风控关键词索引 | 圈定加签核心,剔除 80% 开源库与 UI 噪音 (L1 解构) |
| Chaos VM 字节码反汇编器 | tools/tdc_vm_disasm.js |
映射全部 70 个操作码语义,自动折叠字符拼接,反编译 45,636 字节码为 8,152 条指令流 | 彻底透明化 TDC 字节码调度器,提取 246 个环境检测特征 (L2/L3 解构) |
| 深度 Proxy 语义探针 | tools/tdc_probe.js |
零 Headless/CDP 依赖,通过深度 Proxy 沙箱执行 tdc.js,拦截并记录全部 95 项环境读取 |
毫秒级生成与当前会话时间戳和密钥 100% 自洽的动态 collect 与 eks (L4 数据层) |
二、核心逆向成果与证据账本
1. TDC 混沌虚拟机(Tencent Chaos VM)指令集
__TENCENT_CHAOS_VM 采用经典基于栈的虚拟机架构,包含 70 条操作码:
- 操作码分发器循环:
for (var M = !1; !M;) M = G[z[H++]](); z: 45,636 整数组成的解压字节码序列H: 程序计数器 (PC)- 关键操作码:
00:PUSH_STR_CHAR(字符串构造)03/30/62/35/36/65: 位运算 (^,&,|,>>,<<,>>>)06/34/41/61: 函数调用与对象实例化 (apply,new)46/68/47: 虚拟寄存器读写与分配56/48/49: 异常处理栈(Try-Catch 保护链)57: 闭包创建器(动态子程序展开)
2. TDC 关键检测项白名单(已由探针全量捕获,共 95 项)
探针运行实测表明,TDC 实际探测的环境特征仅 95 项,绝非海量属性:
- 自动化/反爬标记检测:
document.$cdc_asdjflasutopfhvcZLmcfl_(精准探测 ChromeDriver 变量)window.navigator.webdriverwindow.domAutomationwindow.fxdriver_idwindow.callPhantom/casper/CasperError/patchRequirewindow.ubot/WebPage
- 显示与硬件画像:
screen.width(2560),screen.height(1440),availHeight(1345),colorDepth(24)deviceXDPI,logicalXDPI,fontSmoothingEnablednavigator.hardwareConcurrency(10),platform("MacIntel"),languages
- 渲染上下文:
- WebGL Renderer:
"ANGLE (Apple, ANGLE Metal Renderer: Apple M4, Unspecified Version)" - WebGL Vendor:
"Google Inc. (Apple)" - Canvas Fingerprint: 成功样本原图 Base64 (368 字节)
- WebGL Renderer:
- 容器关系:
window.top !== window(识别是否运行在验证码 iframe 内)document.getElementById("tCaptchaDyContent")window.TCaptchaReferrer(宿主页面 URL 绑定)
3. L4 遥测协议数据解密 (cd 38 维字段)
成功解密的 collect 明文格式为 {"cd": [...], "sd": {"od": "C", "ft": "..."}}:
cd[0..1]: 屏幕宽、平台 (2560,"MacIntel")cd[2]: Canvas 指纹cd[8]: 宿主页面 URL (document.referrer)cd[9]: User-Agentcd[15/18]: WebGL 渲染器与厂商cd[19/22/27]: 当前会话的秒级与毫秒级 Epoch 时间戳(必须与请求自洽,旧方案硬编码是致死原因之一)cd[20]: 鼠标相对增量轨迹:首点为绝对坐标[start_x, start_y, delay_ms],后续为增量[dx, dy, dt_ms](dt 均值 16~18ms,模拟 60Hz 采样)cd[26]: 会话校验和与随机种子cd[31]: 执行容器类型 ("iframe")
三、旧方案致死原因归纳(为什么之前报 12)
re.sub破坏内部校验和与字段序: 旧方案拿固定的字符串模板进行正则替换,改变了明文长度,导致内部求和校验全部失效;且不同会话的tdc.js构建字段顺序会动态轮换,静态模板必死。- 时间戳严重错位: 旧方案使用数天前抓包的硬编码时间戳,与当前服务器时间差数天,风控系统秒判拒绝。
- 机械假轨迹:
旧代码用
random.randint随机构造假点,dt 分布为 0 或 1ms(相当于 20ms 内完成数十次移动),动力学完全反人类。 - CDP 特征泄露:
浏览器自动化直接被
document.$cdc_asdjflasutopfhvcZLmcfl_抓现行。
四、一键复验入口
# 1. 验证 Webpack 解包与核心模块提取
node tools/unpack_webpack.js
# 2. 验证 TDC 虚拟机反汇编与字符串提取
node tools/tdc_vm_disasm.js tcaptcha/core_js/tdc_sample.js
# 3. 验证深度 Proxy 语义探针执行并产出 100% 合法 collect 与 eks
node tools/tdc_probe.js tcaptcha/core_js/tdc_sample.js
# 4. 验证探针生成的 collect 成功解密
.venv/bin/python -c '
import json, base64, urllib.parse, subprocess
from tcaptcha.crypto import extract_xtea_key, xtea_decrypt_bytes
with open("tcaptcha/core_js/tdc_sample.js") as f: code = f.read()
key = extract_xtea_key(code)
res = subprocess.check_output(["node", "-e", "const {probeTdc}=require(\"./tools/tdc_probe.js\"); const r=probeTdc(\"tcaptcha/core_js/tdc_sample.js\"); console.log(r.collect);"], text=True).strip()
raw = base64.b64decode(urllib.parse.unquote(res))
plain = xtea_decrypt_bytes(raw, key).rstrip(b"\\x00")
print("成功解密探针生成的遥测载荷,长度:", len(plain))
print("明文前 150 字节:", plain[:150].decode("latin1"))
'