diff --git a/tools/full_web_cookie.py b/tools/full_web_cookie.py new file mode 100644 index 0000000..c72b97f --- /dev/null +++ b/tools/full_web_cookie.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""一键: 账号密码 -> 完整网页Cookie全套。 +用法: python tools/full_web_cookie.py <账号> <密码> +产出: 打印全部cookie并写 evidence/web_cookies_full.txt +""" +import sys +if len(sys.argv)>=3: + import json,re,hashlib + sys.argv=[sys.argv[0]] +import sys,json,time,base64 +from urllib.parse import quote +sys.path.insert(0,'scripts'); sys.path.insert(0,'tools') +from probe_forge_cert_bind import load_capture, parse_p1, build_p1, forge_cert +from probe_huya_qr_bind import QrRole, web_behavior +from core.huya.device_fingerprint import get_huya_sdid +qurl,P1_old=load_capture() +fields=parse_p1(P1_old) +import hashlib,requests as _rq +from huya_wup_encoder import build_password_login_wup +_raw=(__import__('pathlib').Path(__file__).resolve().parent.parent/'evidence/wup_passwordlogin_taf.bin').read_bytes() +_mj=json.loads(re.search(rb'(\{"associationId.*?\})',_raw).group(1)) +_ua=re.search(rb'(\{"curl".*?"user_action":\[.*?\]\})',_raw).group().decode() +_sd=re.search(rb'PQwemAN9[A-Za-z0-9+/=]+',_raw).group().decode() +_dev={"app_version":"13.4.22","sdk_version":"1.0.80138","vendor":"xiaomi","model":"M2102J2SC","os":"android","ip":"127.0.0.1","fingerprint":"02df398797432eadefcc12767119ad5e80999389","screen":"M2102J2SC,30,11","width":"1080","height":"2120","device_id":"7c5387e0539c023c31c4ff0e807e7256117385ee"} +_pkt=build_password_login_wup("300023887",hashlib.sha1(PWD.encode()).hexdigest(),_sd,"ed0db8334cadd236c00cadf7e11ab5a5",_mj["session"],_mj["traceId"],_ua,_dev) +_r=_rq.post("https://wup.huya.com",data=_pkt,headers={"Content-Type":"application/multipart-formdata; charset=UTF-8","User-Agent":"Dalvik/2.1.0"},timeout=15) +_b=_r.content; _s=_b.find(b'\x0a\x0a',0x40); _e=_b.find(b'_wup_header'); _d=_b[_s:_e-6] +_m=re.search(rb'\x3d\x00\x00.',_d); _ln=_m.group()[3] +cred=_d[_m.start()+4:_m.start()+4+_ln] +print('新鲜cred:',len(cred),cred[:8].hex()) +P1n=build_p1(b"5008",fields["fingerprint"],cred,rnd=fields["rnd"]) +cert=base64.b64encode(forge_cert(P1n,key_idx=fields and 0x20)).decode() +raw=base64.b64decode(qurl) +i=raw.find(base64.b64encode(forge_cert(build_p1(b"5008",fields["fingerprint"],b"\x0a"*114,rnd=fields["rnd"]),key_idx=0x20))) +# 直接替换原证书段: 找原cert b64 span——用原P1重建 +old_b64=None +from probe_forge_cert_bind import find_cert_span as _fcs; j=_fcs(raw) +if True: + # 退路: 用find_cert_span + from probe_forge_cert_bind import find_cert_span + s0,s1,_=find_cert_span(raw); raw=raw[:s0]+cert.encode()+raw[s1:] +else: + raw=raw[:j]+cert.encode()+raw[j+len(old_b64):] +wup=base64.b64encode(raw).decode() +sdid=get_huya_sdid(allow_fallback=False).sdid +pc=QrRole(pc=True,sdid=sdid); ph=QrRole(pc=False,sdid=sdid) +beh,page=web_behavior() +resp=pc.call("/qrLgn/getQrId","70001",{"behavior":beh,"type":"","domainList":"","page":page}) +qrid=resp["data"]["qrId"] +cp=f"https://aq.huya.com/r/confirm.html?k={qrid}&id=5002" +ph.call("/qrLgn/scanQrPicNotify","70005",{"qrId":qrid,"wupData":wup,"behavior":quote("[]",safe=""),"page":quote(cp,safe="")}) +r2=ph.call("/qrLgn/bindQrLoginUser","70007",{"qrId":qrid,"wupData":wup,"behavior":quote("[]",safe=""),"page":quote(cp,safe="")}) +print("bind rc",r2.get("returnCode")) +for i in range(10): + rt=pc.call("/qrLgn/tryQrLogin","70003",{"qrId":qrid,"remember":"1","domainList":"","behavior":beh,"page":page}) + dt=rt.get("data") or {} + if dt.get("stage")==2: + print(json.dumps(dt,ensure_ascii=False,indent=1)[:1800]); break + time.sleep(2) + +# 追加: cookie verify 兑换 +sess = getattr(pc,'session',None) or getattr(pc,'s',None) or getattr(pc,'_sess',None) +r=sess.post("https://udblgn.huya.com/web/cookie/verify",json={"appId":5002},timeout=15) +print('verify HTTP',r.status_code) +for h in r.headers.get('Set-Cookie','').split('\n') or [r.headers.get('Set-Cookie','')]: + if h: print('SET:',h[:110]) +print('cookie jar:') +for c in sess.cookies: print(' ',c.name,'=',c.value[:50]) diff --git a/tools/web_cookie_login.py b/tools/web_cookie_login.py new file mode 100644 index 0000000..6eaa26d --- /dev/null +++ b/tools/web_cookie_login.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""网页版密码登录 -> 直接拿全套长 cookie(udb_cred/udb_passdata/yyuid...)。 + +用法: python tools/web_cookie_login.py <账号> <密码> +""" +import sys, json, re, hashlib, time, uuid +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(ROOT)) +import requests +from core.huya.device_fingerprint import get_huya_sdid + +URL = "https://udblgn.huya.com/web/v2/passwordLogin" + + +def main(): + acct, pwd = sys.argv[1], sys.argv[2] + if not acct.startswith("hy_"): + acct = "hy_" + acct + sha1 = hashlib.sha1(pwd.encode()).hexdigest() + try: + sdid = get_huya_sdid(allow_fallback=True).sdid + except Exception: + sdid = "0UnHUgv0_qmfD4KAKlwzhqaKn105aUYt7oVTYd8Axc4iQSNyLE_nmgRB8tPxnndI8Th1nJ_003VaxeRFLVvpJcTJXFa3qhMVoHC9dykeCz3DWVkn9LtfFJw_Qo4kgKr8OZHDqNnuwg612sGyflFn1dutzDtufJ9ExmL1Pr7Bhq2nTk7vCmHfM2aTlTZvNeXfn" + ctx = f"WB-{uuid.uuid4().hex}-" + uuid.uuid4().hex.upper()[:24] + beh = json.dumps({ + "furl": "https://www.huya.com/", "curl": "https://www.huya.com/g", + "user_action": [{"id": "7", "d": 712, + "t": str(int(time.time() * 1000))}]}) + body = { + "uri": "30001", "version": "2.6", "context": ctx, + "appId": "5002", "appSign": "1ce3bf682483d03f146f58232ec10635", + "authId": "", "sdid": sdid, "lcid": "2052", "byPass": "3", + "requestId": str(int(time.time())%100000000), + "data": {"userName": acct, "password": sha1, "domainList": "", + "remember": "1", + "behavior": requests.utils.quote(beh, safe="")}} + s = requests.Session() + s.trust_env = False + r = s.post(URL, json=body, timeout=15, headers={ + "Content-Type": "application/json;charset=UTF-8", + "Origin": "https://www.huya.com", + "Referer": "https://www.huya.com/", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + "AppleWebKit/537.36 Chrome/150.0 Safari/537.36"}) + print("HTTP", r.status_code) + j = r.json() + print("returnCode:", j.get("returnCode"), "|", + j.get("description") or j.get("message")) + if j.get("returnCode") != 0: + print(json.dumps(j, ensure_ascii=False)[:400]) + return 1 + print("\n=== 全套 Cookie ===") + total = 0 + for c in s.cookies: + v = c.value or "" + total += len(c.name) + len(v) + 2 + mark = " ← 长" if len(v) > 100 else "" + print(f"{c.name:16s} = {v[:70]}{'...' if len(v)>70 else ''}{mark}") + ck = "; ".join(f"{c.name}={c.value}" for c in s.cookies) + (ROOT / "evidence/web_cookies.txt").write_text(ck) + print(f"\n总长 {len(ck)} 字符, 已存 evidence/web_cookies.txt") + print("用法: requests.get(url, headers={'Cookie': open('evidence/web_cookies.txt').read()})") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())