web_cookie_fields 用逆向算法替换随机:__yamid_new=UUIDv1时间戳复刻、game_did=35位63字符集、_yasids同源、_qimei_uuid42=1a前缀、guid回退加固定段
This commit is contained in:
@@ -17,8 +17,8 @@ status=200(和平精英已绑定)、getUserScore 返回 status=200(积分
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
import secrets
|
||||
import string
|
||||
import time
|
||||
|
||||
# 统计/会话字段生成规则;9.1 抓包值为样例,格式保持对齐
|
||||
@@ -30,6 +30,71 @@ _FILL_MAP: tuple[tuple[str, str], ...] = (
|
||||
("udb_accdata", "undefined"),
|
||||
)
|
||||
|
||||
# 浏览器实测逆向(2026-09-01,见 docs/HUYA_WEB_FIELD_TRACE.md):
|
||||
# - __yamid_new: room_normal.js generate32(UUID-v1 风格,1582-epoch 本地时区时间戳
|
||||
# + v1 版本位 + 时钟序列 + 48 位随机 node)。浏览器 epoch = new Date(1582,10,15,
|
||||
# 0,0,0,0).getTime() 实测 -12216643543000(GMT+8)。CBCC 前缀是时间戳自然结果。
|
||||
# - game_did: vplayerUI.js 35 位随机,字符集 64 去掉末尾 '_'(63 选 1)。
|
||||
# - _qimei_uuid42: QIMEI SDK 生成,cookie 值首字节固定 '1a'(本地存储 44hex 截断)。
|
||||
|
||||
_SDK_EPOCH_1582 = -12216643543000 # 浏览器实测 JS Date(1582,10,15) 本地时区 ms
|
||||
_BASE16 = "0123456789ABCDEF"
|
||||
_GAME_DID_CHARS = (
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
|
||||
)
|
||||
|
||||
|
||||
def _return_base16(a: int) -> str:
|
||||
"""JS returnBase(a,16):正整数转大写十六进制;a<=0 返回空串。"""
|
||||
if a <= 0:
|
||||
return ""
|
||||
out = ""
|
||||
while a > 0:
|
||||
out = _BASE16[a % 16] + out
|
||||
a //= 16
|
||||
return out
|
||||
|
||||
|
||||
def _generate_bits(a: int, b: int, c: int) -> str:
|
||||
"""JS generateBits(a,b,c):取 a 的 16 进制串 [floor(b/4)..floor(c/4)] 字符,越界补0。"""
|
||||
d = _return_base16(a)
|
||||
out = ""
|
||||
for g in range(b // 4, c // 4 + 1):
|
||||
out += d[g] if g < len(d) and d[g] != "" else "0"
|
||||
return out
|
||||
|
||||
|
||||
def _yamid_new_generate32(rng=None) -> str:
|
||||
"""逐字复刻 room_normal.js generate32(__yamid_new 生成器)。"""
|
||||
import random
|
||||
|
||||
r = rng if rng is not None else random.Random()
|
||||
now_ms = int(time.time() * 1000)
|
||||
c = now_ms - _SDK_EPOCH_1582
|
||||
return "".join((
|
||||
_generate_bits(c, 0, 31),
|
||||
_generate_bits(c, 32, 47),
|
||||
_generate_bits(c, 48, 59) + "1",
|
||||
_generate_bits(r.randrange(4096), 0, 7),
|
||||
_generate_bits(r.randrange(4096), 0, 7),
|
||||
_generate_bits(r.randrange(8192), 0, 7)
|
||||
+ _generate_bits(r.randrange(8192), 8, 15)
|
||||
+ _generate_bits(r.randrange(8192), 0, 7)
|
||||
+ _generate_bits(r.randrange(8192), 8, 15)
|
||||
+ _generate_bits(r.randrange(8192), 0, 15),
|
||||
))
|
||||
|
||||
|
||||
def _game_did_generate(length: int = 35) -> str:
|
||||
"""逐字复刻 vplayerUI.js game_did:35 位随机,字符集 64 去掉末尾 '_'。"""
|
||||
import random
|
||||
|
||||
out = ""
|
||||
for _ in range(length):
|
||||
idx = int(random.random() * (len(_GAME_DID_CHARS) - 1)) # 63 → 排除 '_'
|
||||
out += _GAME_DID_CHARS[idx]
|
||||
return out
|
||||
|
||||
|
||||
def _rand_float() -> str:
|
||||
import random
|
||||
@@ -78,15 +143,17 @@ def fill_web_cookie_fields(
|
||||
else:
|
||||
add("guid", str(guid))
|
||||
elif "guid" not in pairs:
|
||||
add("guid", secrets.token_hex(16))
|
||||
add("_qimei_uuid42", secrets.token_hex(21)) # 42 hex
|
||||
add("__yamid_new", secrets.token_hex(16).upper()) # 32 hex 大写
|
||||
alnum = string.ascii_letters + string.digits
|
||||
import random
|
||||
|
||||
add("game_did", "".join(random.choices(alnum, k=30))) # 30 位字母数字
|
||||
# guid 结构: '0a' + 10hex + '956a'/'966a' + 16hex(浏览器实测固定段,见 trace 文档)
|
||||
add("guid", "0a" + secrets.token_hex(5) + "966a" + secrets.token_hex(8))
|
||||
# _qimei_uuid42: QIMEI SDK 产物,cookie 首字节 '1a' + UUID 布局 32hex + 8hex 附加
|
||||
add("_qimei_uuid42", "1a" + secrets.token_hex(20))
|
||||
# __yamid_new: room_normal.js generate32 精确复刻(UUID-v1 时间戳,含 CBCC 前缀规律)
|
||||
add("__yamid_new", _yamid_new_generate32())
|
||||
add("game_did", _game_did_generate()) # 35 位随机(真实长度)
|
||||
|
||||
# qimei 皮肤字段
|
||||
# _qimei_fingerprint: QIMEI SDK SpookyHashV2(canvas指纹,31) 32hex;设备稳定,
|
||||
# 无真实 canvas 时可随机(格式 32hex 对齐),真实算法见 trace 文档
|
||||
add("_qimei_fingerprint", secrets.token_hex(16))
|
||||
add("_qimei_h38", secrets.token_hex(19))
|
||||
|
||||
@@ -99,7 +166,8 @@ def fill_web_cookie_fields(
|
||||
add("h_unt", str(int(time.time())))
|
||||
if uid:
|
||||
add("__yaoldyyuid", str(uid))
|
||||
add("_yasids", "__rootsid%3D" + secrets.token_hex(16).upper())
|
||||
# _yasids 与 __yamid_new 同源(共享时间戳生成器,浏览器实测前缀一致)
|
||||
add("_yasids", "__rootsid%3D" + _yamid_new_generate32())
|
||||
add("Hm_lvt_51700b6c722f5bb4cf39906a596ea41f", str(int(time.time())))
|
||||
add("Hm_lpvt_51700b6c722f5bb4cf39906a596ea41f", str(int(time.time())))
|
||||
add("HMACCOUNT", secrets.token_hex(8).upper())
|
||||
|
||||
Reference in New Issue
Block a user