docs(账本): 记录 VM 程序结构层打通(#33/#34)与槽位语义残留点
已知 #33: 顶层 = 62 个模块工厂注册表; 修了反汇编器的 RET_TRUE/THROW 终结符缺失 已知 #34: cd 槽位序 = 清单模块 require 顺序(追加式数组), tools/tdc_layout.py 可静态导出 §五 1(b) 重写: 静态提取已打通, 残留两件 —— 取值寄存器规则收口 + 运行时 require 序对拍
This commit is contained in:
@@ -63,6 +63,8 @@
|
||||
| 30 | **真机某次成功会话的 collect 明文已完整解出** | 抓包同时拿到**同会话**的 `tdc.js`(`app_data=1793575418729725952`)与 `cap_union_new_verify` 的 collect,用该构建密钥解密:784B 密文 → 可打印率 0.991,得<br>`{"cd":["",[360,360],0,"Mozilla/5.0 (Macintosh…) Chrome/155…","https://turing.captcha.gtimg.com/1/template/drag_ele.html?rand=…",["zh-CN","zh"],641547489,1791732001,"GgoAAA…png…",2560,[[34,96,3284],[154,50,370],…],1023,1440,"+08",1,0,"ANGLE (Apple, ANGLE Metal Renderer: Apple M4, …)",10,"",1,1986013704,"iframe","MacIntel",0,1791733986,"1440-2560-2530-24-*-*-|-*",1791733982,"Google Inc. (Apple)",24,"",[],0,"https://1ms.run/console/personal/benefits/check-in","98k",2,0,0,"UTF-8"],"sd":{"od":"C","ft":"qf_7Pf__H"}}`<br>(`tdc.js?app_data=…&appid=<aid>`:真机 URL 带 `appid`,我们客户端不带)| 确证 |
|
||||
| 31 | **`cd` 的槽位顺序按会话/构建随机化(不是按版本固定)** | 5 份同日样本(真机 cap2 / `签到成功-1` / `点选` / `login_checkin` / 仓库模板)全部 `len(cd)=38`、**同一批取值**、**同一个 `sd`**,但**槽位顺序 5/5 互不相同**(两两不同槽位 26~29 个)。复现:`.venv/bin/python scripts/analyze_collect_layout.py --json <cap>.json` | 确证 |
|
||||
| 32 | **仓库在用的 collect 模板 = `签到成功-1.har` 那一次的槽位序** | 模板指纹与 `签到成功-1#0` **逐槽一致**;与晚些时候的真机会话 29 个槽不同。→ `generate_collect_success()` 虽然回填了新轨迹/时间戳,但**槽位序是那一次的** | 确证 |
|
||||
| 33 | **VM 程序结构层已吃透:顶层就是 62 个模块工厂的注册表** | 顶层 `@0` 做 `registry[id] = function(module, exports, require){...}`(`DUP; PUSH_IMM [id]; REVERSE_TOP2; JUMP -> CREATE_CLOSURE; SET_PROP`)。`tools/tdc_program.py --modules` 直接导出。修了两个真 bug:① 反汇编器漏了 `RET_TRUE`/`THROW` 是终结符(控制流穿过函数结尾 → 子程序归属全错);② 提升器终结符判定写死 opcode 数值 | 确证 |
|
||||
| 34 | **`cd` 槽位序的来源已定位并可静态导出** | 装配链:清单模块 `arr[arr.length] = require(N)`(**追加,所以 require 顺序就是数组顺序**,已核)→ 分发模块按 `.on`/`.reset`/`.get` 分三数组 → 装配模块 `r3='{"cd":['` + `for(...) r3 += arr[i].get()`。线上构建实测 **37 个 require + 1 个字面量槽 = 38**,与真机 `cd` 槽数完全吻合;两份构建的 require 串不同(与 #31 一致)。工具:`tools/tdc_layout.py` | 确证(顺序)/ 语义标签部分 |
|
||||
|
||||
---
|
||||
|
||||
@@ -153,11 +155,14 @@ TencentCaptchaClient(telemetry_mode="python_keyed") # 默认
|
||||
让 widget 把 collect **组好但不发**;再把这一包原样交给 **Python** 发。
|
||||
若 Python 也 0 → "谁在发 HTTP"彻底无关,12 只剩"包内容"一个自变量 → 坐实 H-LAYOUT。
|
||||
若 Python 仍 12(而同一包在浏览器里是 0)→ 说明还有"会话↔连接"绑定,需换实验 A'。
|
||||
(b) **拿到本次构建的槽位表**(二选一):
|
||||
① 神谕路(快):`tools/tdc_probe.js` / `tdc_keytrace.js` 在 JS 运行时 hook XTEA 输入,
|
||||
dump 出**本次构建的明文骨架** → 得槽位序;Python 按该序回填。
|
||||
② 纯算路(慢,但符合项目"零环境"目标):用 `tools/tdc_disasm.py` / `tdc_lift.py`
|
||||
反汇编构造 `cd` 的字节码段,还原 "push 顺序 ↔ 语义字段" 映射表。
|
||||
(b) **拿到本次构建的槽位表** —— 已打通静态提取(已知 #33/#34):
|
||||
顶层 62 个模块工厂注册表 → 清单模块 `arr[arr.length] = require(N)` 的**顺序即槽位序**
|
||||
→ `tools/tdc_layout.py <tdc.js>` 直接导出。
|
||||
⚠️ 残留:逐槽**语义标签**还没全对齐(已精确命中 `cd[3]←c.navigator.userAgent`、
|
||||
`cd[5]←c.navigator.languages`,其余若干槽仍对不上)。
|
||||
两个待收口点:① `get` 闭包"取值寄存器"的判定规则要覆盖全部模块形状;
|
||||
② **运行时反证**:在真机页面里包一层 `require`,把清单模块实际按顺序请求的 id 打出来,
|
||||
与静态导出串对拍(一条命令就能证伪/证实静态提取)。
|
||||
(c) **验证**:collect 按 (b) 的槽位序重排后重发 195672344,期望 **12 → 0**。
|
||||
注意:既然 tdc.js 按请求随机(#29),Python 客户端必须用**它自己那次 prehandle 拿到 sid
|
||||
之后请求的那份 tdc.js** 的槽位表,不能用缓存/模板。
|
||||
|
||||
Reference in New Issue
Block a user