# 虎牙网页设备字段溯源(历史证据,2026-09-01 浏览器实测) > 当前实现状态以 [HUYA_COOKIE路线状态.md](HUYA_COOKIE路线状态.md) 为准;本文保留原始浏览器证据与算法推导。 ## 一、来源判定方法(有头 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` | 同上 | 14 位时间前缀 + 8 位 CRC32 替换值 + 20 位随机半字节 + 4 位 CRC32 尾段 | ## 三、设备字段结构规律(真实样本) ### 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 = 14 位时间前缀 + CRC32 替换段 + 20 位随机半字节 + CRC32 尾段 ``` 17b0f060d14100037f4444444444444444444437df ← 固定时间/随机 .25 17b0f060d1410053db888888888888888888883ff6 ← 固定时间/随机 .5 17b0f060d141003174ffffffffffffffffffffd85d ← 固定时间/随机 .999 ``` 时间前缀的编码为:年份末两位十六进制(补两位)+ 月份十六进制 + 日/时/分/秒各两位十六进制 + `cookieEnabled` 标志(`100`/`000`)。模板 `prefix + "----" + random_nibbles + "----"` 的标准 CRC32 小写结果会拆成前后四位填回两个占位;`random_nibbles` 由 20 次独立的 `floor(Math.random() * 16)` 依次拼接,因此每位合法范围为 `0` 到 `f`。 ### _qimei_fingerprint = x64hash128(feature_string, 31) 32hex qimeisdk-web 0.6.3 源码已定位: - 画 "qimei" 文本(Times New Roman 11pt)+ `#f60` 背景 + 透明度矩形 - 三圆叠加(`#f2f`/`#2ff`/`#ff2` 40 半径)+ 环形 `#f9c` evenodd - Canvas `id`/`geometry` 是 SDK 特征对象的独立字段;Cookie 指纹实际使用浏览器能力特征串 → SDK 内置 **x64hash128**(seed=31)→ 32hex。 ## 四、溯源结论与建议 | 字段 | 来源 | 风控关联性 | 建议 | | --- | --- | --- | --- | | `guid` | 活动 `wsLaunch` 响应 `sGuid`;页面 SDK 负责持久化 | 高(设备与会话绑定) | **优先复用当前 wsLaunch 会话值**;`956a/966a/976a` 等中间段随服务端返回变化,不能固化为版本常量 | | `__yamid_new` | 浏览器脚本(CBCC 前缀+种子)| 高(与 rootsid 同源)| `room_normal.js` `generate32` 已复刻;精确 rootsid 共享计数仍待确认 | | `_qimei_uuid42` | QIMEI SDK 0.6.3 VM 生成器 `e=6064` | 中 | Python 已按时间编码、CRC32 和随机半字节逐项复刻 | | `_qimei_fingerprint` | QIMEI SDK 0.6.3 x64hash128(feature_string, 31) | 中 | Python 已复刻,输入字段见路线状态文档 | | `_qimei_h38` | 当前页面不写入同名 Cookie;SDK 内部 `h38` = UUID42 | 低 | 积分链路仅检查键存在,缺失时复用 `_qimei_uuid42` | | `game_did` | 浏览器脚本 | 中 | 长度需对齐(35 变体含 `-`)| | 统计字段(SoundValue 等)| 页面脚本 | 低 | 随机 OK | **当时的下一步记录(部分已完成,保留作历史)**: 1. `_qimei_fingerprint` 已改为浏览器能力特征串的 `x64hash128`,见路线状态文档。 2. `guid` 已统一使用 `wsLaunch` 会话值;活动 AUTH、getConfig 与后续业务 Cookie 均复用同一返回值。 3. `__yamid_new` 已定位 `room_normal.js` `generate32` 并完成 Python 复刻。 ## 六、核心字段生成算法逆向结果(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` 同源);字段本身为 42 位小写十六进制。 - Python 实现按 SDK 时间、CRC32 和随机上界复刻,固定向量覆盖 `0`、`.25`、`.5`、`.75`、`.999`。 - SDK 对该内部值使用 `h38` 属性名,但它的长度是 42;`_qimei_h38` 只是活动积分链路的 Cookie 兼容键,不存在另一套 38 位 SDK 生成算法。 ### ✅ _qimei_fingerprint = x64hash128(feature_string,31),已完成 Python 复刻 - Cookie 输入由屏幕分辨率、浏览器能力、WebGL 和时区字段按 `###` 拼接。 - Python 实现位于 `core/huya/web_cookie_fields.py`,测试向量与 SDK 输出一致。 - 没有实时浏览器能力对象时,生成器使用稳定的默认 Web 特征档案。 ### 已修正生成器(core/huya/web_cookie_fields.py) - `__yamid_new` → `_yamid_new_generate32()`(UUID-v1 时间戳复刻) - `game_did` → `_game_did_generate()`(35 位 63 字符集) - `_yasids` → 与 `__yamid_new` 同源同刻生成 - `_qimei_uuid42` → `_qimei_uuid42_generate()`(14 位时间前缀 + CRC32 替换段 + 20 位随机半字节 + CRC32 尾段) - `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=42 位小写十六进制(SDK VM 时间/CRC32 结构) - 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 已清空),非生成器问题。