152 lines
8.0 KiB
Markdown
152 lines
8.0 KiB
Markdown
# 虎牙网页设备字段溯源(2026-09-01 浏览器实测实证)
|
||
|
||
## 一、来源判定方法(有头 Chrome + 打点探针)
|
||
|
||
- `Page.addScriptToEvaluateOnNewDocument` 拦截 `Document.prototype.cookie` setter,
|
||
记录每条写入的 值/时间/调用栈(栈中含脚本 URL + 行号)。
|
||
- `Network.responseReceivedExtraInfo` 捕获服务端 **Set-Cookie** 头。
|
||
- 全新 profile,导航 www.huya.com + 直播间页,静置后导出。
|
||
|
||
## 二、决定性结论:哪些字段服务端下发,哪些浏览器生成
|
||
|
||
### ✅ 服务端 Set-Cookie 下发(仅 5 个)
|
||
| 字段 | 实测 |
|
||
| --- | --- |
|
||
| `PHPSESSID` | l.web.huya.com / l.huya.com |
|
||
| `udb_deviceid` | udblgn.huya.com(`w_` + 19 位数字,匿名设备) |
|
||
| `sdid` | udblgn.huya.com(`0UnHUgv0_qmfD4KA...` 设备指纹) |
|
||
| `v` | 页面版本 |
|
||
| `HMACCOUNT` | 百度统计 |
|
||
|
||
### ✅ 浏览器脚本 document.cookie 写入(铁证:调用栈)
|
||
| 字段 | 生成脚本 | 关键位置 |
|
||
| --- | --- | --- |
|
||
| `guid` | `a.msstatic.com/huya/main3/npm..pnpm-d84ecac2_850fe68b.js` `Object.setCookie` | 写入 5 次;**位置 12-16 固定 `966a`(跨会话一致)** |
|
||
| `_qimei_fingerprint` | `staticfile.qq.com/qimei/qimeisdk-web/0.6.3/index.js` | 写入 1 次 |
|
||
| `udb_passdata` | `a.msstatic.com/huya/main3/common/headerfunction_d8b3ad0c.js` `writeCookie` | 固定值 3 |
|
||
| `__yasmid` / `__yamid_tt1` | 页面脚本 | 同值 17 位小数 |
|
||
|
||
### ⚠️ 浏览器生成但**非 document.cookie 写入**(走 Cookie Store API / localStorage 同步等)
|
||
| 字段 | 证据 | 说明 |
|
||
| --- | --- | --- |
|
||
| `__yamid_new` | 88 条写入中无此 key,但最终 cookie 有值 | **CBCC 前缀 + 递增种子**(见下) |
|
||
| `game_did` | 同上 | 30-35 位字母数字 |
|
||
| `_qimei_uuid42` | 同上 | `1a` 前缀 + 32hex UUID 结构 + 10hex |
|
||
|
||
## 三、设备字段结构规律(真实样本)
|
||
|
||
### guid = `0a` + 10hex + `956a`/`966a` + 16hex —— 有固定段,非纯随机
|
||
```
|
||
0a7dfa5fc9ee966aab02a2eaa3ea1de1 ← live 窗口
|
||
0a7dfaa2d7af966a2101f370f470ce50 ← round2 fresh
|
||
0a7de265986f956a24015b505c504506 ← reqable 8.31
|
||
0a89d5f6614b956aa6020bbc0cbc18fe ← cahrles 8.31
|
||
```
|
||
位置 12-16 恒为 `956a` / `966a`(产品段?),8.31 为 `956a`、我们机器为 `966a` ——
|
||
可能与 SDK/页面版本有关。
|
||
|
||
### __yamid_new = `CBCC`/`CBCB` + 种子6hex + 计数4hex + `0001` + 随机12hex
|
||
```
|
||
CBCC 6479D9 B000 0001 52EC19001D2017B2 ← live 窗口
|
||
CBCC 551C11 E000 0001 783D8F5530901BCC ← round2 fresh
|
||
CBCC 06ECB5 0000 0001 B63016D6162BC990 ← reqable 8.31
|
||
```
|
||
- 前缀 `CBCC`/`CBCB` 恒定(产品标识)
|
||
- 种子段递增且与 `_yasids`(rootsid)**同源共享时钟**:
|
||
`yamid=CBCC6479D9B0...` ↔ `rootsid=CBCC647A8A20...`(同会话,种子差 0xB1≈177)
|
||
- `0001` 固定,尾部大段随机
|
||
|
||
### _qimei_uuid42 = `1a` + 40hex(32hex UUID 结构 + 10hex 附加)
|
||
```
|
||
1a81f140c08100b89fb1be450f640501568684b2ea ← reqable 8.31
|
||
1a901123a1f10045427c1c73420287f44f49d11b45 ← round2 fresh
|
||
1a901171b051007527940c2acef15dcd2342b6ff ← live 窗口
|
||
```
|
||
首字节 `1a` 恒定;前 32 hex 符合 RFC 4122 UUID 布局(8-4-4-4-12)。
|
||
|
||
### _qimei_fingerprint = SpookyHashV2(canvas指纹, 31) 32hex
|
||
qimeisdk-web 0.6.3 源码已定位:
|
||
- 画 "qimei" 文本(Times New Roman 11pt)+ `#f60` 背景 + 透明度矩形
|
||
- 三圆叠加(`#f2f`/`#2ff`/`#ff2` 40 半径)+ 环形 `#f9c` evenodd
|
||
- `canvas.toDataURL()` → **SpookyHashV2**(r 函数,64 位,seed=31)→ 32hex
|
||
|
||
## 四、溯源结论与建议
|
||
|
||
| 字段 | 来源 | 风控关联性 | 建议 |
|
||
| --- | --- | --- | --- |
|
||
| `guid` | 浏览器脚本(有固定段 `0a..966a`)| 高(设备与会话绑定) | **必须按结构仿造或复用 wsLaunch 会话值**;随机纯 hex 与真实结构不符 |
|
||
| `__yamid_new` | 浏览器脚本(CBCC 前缀+种子)| 高(与 rootsid 同源)| 需要前缀 `CBCC` + 种子同步生成逻辑 |
|
||
| `_qimei_uuid42` | QIMEI SDK 0.6.3(`1a` 前缀)| 中 | 前缀 `1a` + UUID 布局 |
|
||
| `_qimei_fingerprint` | QIMEI SDK 0.6.3 SpookyHashV2 | 中 | **算法已完全逆向**(源码在手),可精确复现 |
|
||
| `game_did` | 浏览器脚本 | 中 | 长度需对齐(35 变体含 `-`)|
|
||
| 统计字段(SoundValue 等)| 页面脚本 | 低 | 随机 OK |
|
||
|
||
**下一步选项**:
|
||
1. `_qimei_fingerprint` 直接用 SpookyHashV2 实现(canvas 指纹用标准值替代)
|
||
2. `guid` 采样更多样本确认固定段后按 `0a` + 结构仿造
|
||
3. `__yamid_new` 需找到生成它的具体脚本(非 document.cookie 写入,可能在
|
||
ubtk/埋点脚本里)做种子同步
|
||
## 六、核心字段生成算法逆向结果(2026-09-01 晚,浏览器实测 + 源码定位)
|
||
|
||
### ✅ __yamid_new = room_normal.js generate32(UUID-v1 风格,已 Python 复刻验证)
|
||
```js
|
||
// a.msstatic.com/huya/main3/app/room_normal_55c7cc4f.js
|
||
function u(e){var t="__yamid_new",n=getCookieVal(t);if(n)return n;n=e||d.generate32();...writeCookie(t,n,...)}
|
||
d.generate32(){
|
||
c = new Date().getTime() - new Date(1582,10,15,0,0,0,0).getTime(); // 本地时区 epoch
|
||
return generateBits(c,0,31) // time_low 8hex
|
||
+ generateBits(c,32,47) // time_mid 4hex
|
||
+ generateBits(c,48,59)+"1" // time_hi+版本位
|
||
+ generateBits(rand(4095),0,7) + generateBits(rand(4095),0,7)
|
||
+ generateBits(rand(8191),0,7)+... 48位随机node;
|
||
}
|
||
```
|
||
- 浏览器实测 epoch(GMT+8): `-12216643543000`;Python 复刻 12hex 时间戳段与浏览器**逐位一致**
|
||
- **`CBCC` 前缀是时间戳自然结果**(1582-epoch 当前值的高位),非固定魔数;随生成时刻缓慢递增
|
||
- `_yasids`(rootsid)同源同刻生成(浏览器实测 yamid=`CBCC653E4B...` / rootsid=`CBCC647A8A...` 共享种子时钟)
|
||
|
||
### ✅ game_did = vplayerUI.js 35 位随机(已复刻)
|
||
```js
|
||
// a.msstatic.com/huya/h5player/room/2608311423/vplayerUI.js
|
||
B = (t=35) => { const e="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
||
for(i="";i.length<t;) i += e.charAt(parseInt(Math.random()*(e.length-1))); return i }
|
||
```
|
||
- **长度 35**(旧随机 30 位是错的);字符集 64 去掉末尾 `_`(63 选 1)
|
||
- cookie 名 `game_did`,无 cookie 时生成并写入
|
||
|
||
### ⚠️ _qimei_uuid42 结构已定,算法待深挖
|
||
- cookie 值:首字节 `1a` 固定 + 40hex(localStorage 是 44hex,cookie 为截断子串)
|
||
- 由 qimeisdk-web 0.6.3 内部 VM 生成(`_qimei_ssid`/`_qimei_last_get_id_time_<16hex>` 同源)
|
||
- 当前实现对齐结构(1a 前缀 + 42hex 随机化),精确算法待继续
|
||
|
||
### ⚠️ _qimei_fingerprint = SpookyHashV2(canvas指纹,31),待 canvas 复现
|
||
- SDK 0.6.3 内置 x64hash128 与 canvas 指纹逻辑(文本+三圆+环形)
|
||
- 设备稳定(同 profile 跨会话不变);当前实现随机 32hex 格式对齐
|
||
- 复现需在真实环境执行 canvas(headless 下 canvas 指纹固定,可抽取一次固化为常量)
|
||
|
||
### 已修正生成器(core/huya/web_cookie_fields.py, commit 待定)
|
||
- `__yamid_new` → `_yamid_new_generate32()`(UUID-v1 时间戳复刻)
|
||
- `game_did` → `_game_did_generate()`(35 位 63 字符集)
|
||
- `_yasids` → 与 `__yamid_new` 同源同刻生成
|
||
- `_qimei_uuid42` → `1a` 前缀 + 42hex
|
||
- `guid`(无会话值回退)→ `0a` + 10hex + `966a` + 16hex 结构
|
||
|
||
## 七、逆向生成器端到端验证(2026-09-01 晚,账号 18397482576 重新登录后)
|
||
|
||
新版生成器(web_cookie_fields.py commit 8fef04d)产出字段:
|
||
- guid=`0a43b01a366c966a7fe26a281e1d3c88`(0a 前缀 + 966a 固定段)
|
||
- __yamid_new=`CBCC65D6C5200001F176114BCF181E25`(UUIDv1 时间戳)
|
||
- _qimei_uuid42=`1a552b4b...`(1a 前缀)
|
||
- game_did=35 位
|
||
- _yasids 与 yamid 同源(CBCC65D6C5 前缀一致)
|
||
|
||
webActUI 全链路 status=200:
|
||
1. checkUserBindGameAccount → 和平精英/痛仰之吻
|
||
2. getUserScore → gain=5580 available=280
|
||
3. getActPrizeList → 29 商品
|
||
4. **scoreExchangePrize → status=200 真实兑换成功**
|
||
(荣耀勋章礼包(小)20 分,订单 sOrderId_2203_12855_1199667330433_...)
|
||
5. getUserPrizeRecords → 4 条
|
||
|
||
↑ 之前 getConfig 超时是旧 cookie 过期(id58 已清空),非生成器问题。
|