diff --git a/docs/虎牙hyCred签发-侦察笔记.md b/docs/虎牙hyCred签发-侦察笔记.md index af33a39..a0f230b 100644 --- a/docs/虎牙hyCred签发-侦察笔记.md +++ b/docs/虎牙hyCred签发-侦察笔记.md @@ -293,3 +293,14 @@ saveLoginData, 对照同账号纯Python响应字节, 直接对出cred真实位 或响应态与存储态之间有一步转换(saveLoginData前?)。 下一步: 设备登录时hook saveLoginData入参bean与getCred出口做同会话字节对照, 精确定位 响应t3 -> 存储cred 的转换函数。 + +## 关键发现: 钥代次轮换 + 响应cred非直接可用 + +cred字节1轮换: 0x10/0x20/0x30/0x40/0x50/0x70/0x80(观测值)=代次计数器。 +干净流水线(登录->新nonce铸证->立即bind)仍40020。 +对照: 桥采cred(0a20,设备会话内)始终有效。 +=> 密码登录响应中的cred与getCred返回的cert-cred是两态: + 登录后app还有后续步骤(getAppComomData等)才得到可用cert-cred, + 或响应cred需会话上下文解密/兑换。 +下一步: hook getCred的调用链回溯(谁写入该值), 或登录后逐func试调 +(hyanonymousCredlogin/getAppComomData)观察cred0文件变化。 diff --git a/evidence/credtrace.json b/evidence/credtrace.json new file mode 100644 index 0000000..a1c20d1 --- /dev/null +++ b/evidence/credtrace.json @@ -0,0 +1 @@ +[{"type": "armed"}, {"type": "getcred", "uid": "0x11751b8656f", "out": {"len": 152, "v": "436e446e4b645635526263546977377641426c74536274596c46597277456d6e2f502f585369487448687745534156746832694d716479682b67786a3261754b4e426469527337775955467365446357494775664159393968464641544d587775446e4176384d437334303277777a6479314958754856514670697046557630534a413859653163724e74797459724c4f3461776f52716a"}}, {"type": "java_cred", "cls": "com.huyaudbunify.HuyaAuth", "r": "com.huyaudbunify.bean.ResGetCred@fc80c4a"}, {"type": "bean", "data": "901beac077000000201deac0770000006f65b851170100001dee9a14002000001868795f333030303233383837006446727941714e37555ac1000000000000009800000000000000c0d5ccdc740000b4400fb9a6770000b4800fb9a6770000b4800fb9a6770000b4701deac0770000001a31313939363636393134363731006b73617563496647751868795f333030303233383837004e45455a476541744d7006312e30007600869b7b226375726c223a22e799bbe5bd956101000000000000580100000000000080379a5f770000b4023100756465223a222d312e30222c226c6f6e67697475641a3030312a2a2a2a2a2a3735323400223a22222c227573650000616374696f6e223a5b7b226964223a223234222c22740000a3be77000000707986cb770000004c9b231a790000009ff18e38a0010000000000000000000000000000000000000100000001000000090000000000000002000000770000001868795f333030303233383837002e342e32322609312e30507b5e81770000b4507b5e81770000b40100000000000000e01beac077000000000000000000000000000000000000000000231a79000000008086cb77000000614cd76ba75c28be000086cb770000002000000000000000d07a86cb770000000000e7c0770000006015eac07700000070eb2b38770000b400002b38770000b40016eac077000000e888ebc07700000000002b38770000b4207a86cb77000000614cd76ba75c28be000086cb77000000d81b231a79000000008086cb7700000000002b38770000b42000000000000000a00e3338770000b403000000030000008104000000000000780400000000000000228081770000b4000000000000000000000000000000000000000000000000dc8ec8c077000000082e4385780000b4614cd76ba75c28bec0ea1fe8770000b4002e4385780000b4007b86cb77000000d8a5c8c07700000000f076cb7700000000c00f0000000000f87f86cb77000000f813edc0770000000100000b00000000010000090000000000709a5f770000b470eb2b38770000b470eb2b38770000b400709a5f770000b4207b86cb77000000c4b6cbc07700000000709a5f770000b4a07b86cb77000000607b86cb77000000cc53c8c07700000010f01fe8770000b4008086cb7700000000709a5f770000b400f01fe8770000b400709a5f770000b4a07b86cb77000000b07b86cb77000000405bc8c077000000008086cb77000000285bc8c07700000000709a5f770000b4800a18e8770000b4e0645f85780000b400f01fe8770000b40000000000000000614cd76ba75c28be207c86cb770000007859c8c077000000c07c86cb77000000b8812d1a79000000c07c86cb77000000776900000000000010f01fe8770000b428f01fe8770000b4008086cb7700000000f01fe8770000b4507c86cb77000000645dc8c077000000c07c86cb77000000614cd76ba75c28be507c86cb770000006c5dc8c077000000f568000000000000c07c86cb77000000c8782d1a7900000050f01fe8770000b4707c86cb770000000c792d1a79000000c07c86cb77000000c07c86cb77000000907c86cb770000008c7a271a79000000c07c86cb77000000000000000000000000000000000000000000000000000000c09c13c477000000000000000000000000a013c477000000b89f13c477000000c07c1fbf77000000c0bca3c07700000082690000f5680000000000000000000000e076cb77000000c09c0f0000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000245dc8c07700000050f01fe8770000b4000000000000000004120080000000000040047978000000004062b577000000c07c86cb77000000010000000000000000e076cb7700000000e00f000000000000f076cb7700000000c00f0000000000737461636b5f616e645f746c733a323730313000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000408086cb770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {"type": "bean", "data": "901beac077000000201deac0770000006f65b851170100001dee9a14002000001868795f333030303233383837006446727941714e37555ac1000000000000009800000000000000c0d5ccdc740000b4400fb9a6770000b4800fb9a6770000b4800fb9a6770000b4701deac0770000001a31313939363636393134363731006b73617563496647751868795f333030303233383837004e45455a476541744d7006312e30007600869b7b226375726c223a22e799bbe5bd956101000000000000580100000000000080379a5f770000b4023100756465223a222d312e30222c226c6f6e67697475641a3030312a2a2a2a2a2a3735323400223a22222c227573650000616374696f6e223a5b7b226964223a223234222c22740000a3be77000000707986cb770000004c9b231a790000009ff18e38a0010000000000000000000000000000000000000100000001000000090000000000000002000000770000001868795f333030303233383837002e342e32322609312e30507b5e81770000b4507b5e81770000b40100000000000000e01beac077000000000000000000000000000000000000000000231a79000000008086cb77000000614cd76ba75c28be000086cb770000002000000000000000d07a86cb770000000000e7c0770000006015eac07700000070eb2b38770000b400002b38770000b40016eac077000000e888ebc07700000000002b38770000b4207a86cb77000000614cd76ba75c28be000086cb77000000d81b231a79000000008086cb7700000000002b38770000b42000000000000000a00e3338770000b403000000030000008104000000000000780400000000000000228081770000b4000000000000000000000000000000000000000000000000dc8ec8c077000000082e4385780000b4614cd76ba75c28bec0ea1fe8770000b4002e4385780000b4007b86cb77000000d8a5c8c07700000000f076cb7700000000c00f0000000000f87f86cb77000000f813edc0770000000100000b00000000010000090000000000709a5f770000b470eb2b38770000b470eb2b38770000b400709a5f770000b4207b86cb77000000c4b6cbc07700000000709a5f770000b4a07b86cb77000000607b86cb77000000cc53c8c07700000010f01fe8770000b4008086cb7700000000709a5f770000b400f01fe8770000b400709a5f770000b4a07b86cb77000000b07b86cb77000000405bc8c077000000008086cb77000000285bc8c07700000000709a5f770000b4800a18e8770000b4e0645f85780000b400f01fe8770000b40000000000000000614cd76ba75c28be207c86cb770000007859c8c077000000c07c86cb77000000b8812d1a79000000c07c86cb77000000776900000000000010f01fe8770000b428f01fe8770000b4008086cb7700000000f01fe8770000b4507c86cb77000000645dc8c077000000c07c86cb77000000614cd76ba75c28be507c86cb770000006c5dc8c077000000f568000000000000c07c86cb77000000c8782d1a7900000050f01fe8770000b4707c86cb770000000c792d1a79000000c07c86cb77000000c07c86cb77000000907c86cb770000008c7a271a79000000c07c86cb77000000000000000000000000000000000000000000000000000000c09c13c477000000000000000000000000a013c477000000b89f13c477000000c07c1fbf77000000c0bca3c07700000082690000f5680000000000000000000000e076cb77000000c09c0f0000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000245dc8c07700000050f01fe8770000b4000000000000000004120080000000000040047978000000004062b577000000c07c86cb77000000010000000000000000e076cb7700000000e00f000000000000f076cb7700000000c00f0000000000737461636b5f616e645f746c733a323730313000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000408086cb770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/evidence/forge_bind_result.json b/evidence/forge_bind_result.json index 5390564..c4a0725 100644 --- a/evidence/forge_bind_result.json +++ b/evidence/forge_bind_result.json @@ -7,6 +7,6 @@ "scan_uid": null } }, - "p1_new_hex": "010400353030381400c25220f81f60cf64ee54e83ef1eab6bdd047b5af28003032646633393837393734333265616465666363313237363731313961643565383039393933383972000a4003ef982e01399335f13e9ae294ebdf18a91fc43e6be883c67a7e19784689ec2d38b5c55b79048d8bec1ab66e55749605a86eb6eae62805a708910655b0be91056b9d7159d2bf116eaed44ded41d7b7fe810d0fbd6e3a689dcd2daa8477c304a49ab2b17d2512b9bc99e33f7d6e99daec", - "ts": 1787654957.844005 + "p1_new_hex": "010400353030381400c25220f81f60cf64ee54e83ef1eab6bdd047b5af28003032646633393837393734333265616465666363313237363731313961643565383039393933383972000a20171d4885bb9bb40f29517ab490f3634a0640e942e24039e2f471a5a66a0c64662b68c43f64a90ab982d8298bfc5de4e58a0bb6617a7ab8ecc730cde4a28bd828261096ca95b6247bba5e4714395166f9a22eb0c9954e6d0890ba40fa951e70e63c7c4c8e8e5547f6ca029830f31adbe8", + "ts": 1787655679.05882 } \ No newline at end of file diff --git a/scripts/hook_credtrace.py b/scripts/hook_credtrace.py new file mode 100644 index 0000000..b5a7ece --- /dev/null +++ b/scripts/hook_credtrace.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""抓 hyCred 签发链: 挂 saveLoginData(落盘) + LoginCred handler(vtable探测)。 + +用法: 脚本跑起来后, 在手机上 手动退出登录 -> 重新登录 一次。 +捕获: 登录态JSON明文(含cred字段) / saveLoginData 入参 / LoginCred handler 触发。 +""" +from __future__ import annotations + +import json +import subprocess +import time +from pathlib import Path + +import frida + +RE = Path("/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0") + +JS = r""" +var base = Process.getModuleByName('libudbauthunify.so').base; +send({type:'armed'}); +function hx(p,n){ try{ return Array.from(new Uint8Array(p.readByteArray(n))).map(x=>('0'+x.toString(16)).slice(-2)).join(''); }catch(e){ return 'ERR'; } } +function rdStr(p){ try{ + var b0=p.readU8(); + if((b0&1)===0){ var l=b0>>1; return {len:l,v:l?hx(p.add(1),Math.min(l,256)):''}; } + var len=parseInt(p.add(8).readU64().toString()); + if(len>4096) return {len:len,v:''}; + return {len:len,v:hx(p.add(16).readPointer(),len)}; +}catch(e){ return {len:-1,v:String(e)}; } } +Interceptor.attach(base.add(0x265a6c), { + onEnter: function(a){ send({type:'bean', data:hx(a[1],2048)}); } +}); +Interceptor.attach(base.add(0x265fb0), { + onEnter: function(a){ send({type:'bean', data:hx(a[2],2048)}); } +}); + +Java.perform(function(){ + var n=0; + function go(){ + try{ + var seed=Java.use('com.duowan.kiwi.base.login.udb.HuyaLoginProxy'); + var F=Java.ClassFactory.get(seed.class.getClassLoader()); + var done=false; + ['com.huyaudbunify.HuyaAuth','com.hysdkproxy.HuyaAuth','com.huyaudbunify.sdk.HuyaAuth'].forEach(function(cn){ + if(done) return; + try{ + var C=F.use(cn); + var inst = C.getInstance ? C.getInstance() : null; + var r = inst ? inst.getCred(1199666914671) : C.getCred(1199666914671); + send({type:'java_cred', cls:cn, r:String(r).slice(0,400)}); + done=true; + }catch(e2){} + }); + if(!done) throw new Error('no HuyaAuth'); + }catch(e){ n+=1; if(n%6===0) send({type:'retry',n:n}); setTimeout(go,5000); } + } + setTimeout(go, 15000); +}); +Interceptor.attach(base.add(0x265524), { + onEnter: function(a){ this.uid=a[1].toString(); this.out=a[2]; }, + onLeave: function(){ send({type:'getcred', uid:this.uid, out:rdStr(this.out)}); } +}); +""" + + +def main(): + d = frida.get_device_manager().add_remote_device('127.0.0.1:31877') + pid = d.spawn(['com.duowan.kiwi']) + s = d.attach(pid) + s.create_script((RE / "evidence/scripts/bypass_msaoaid_maps_art_callsite.js").read_text()).load() + s.create_script((RE / "evidence/scripts/mask_frida_maps_only.js").read_text()).load() + d.resume(pid) + time.sleep(11) + s.create_script((RE / "evidence/scripts/patch_guard_block_termination.js").read_text()).load() + print('armed. >>> 请在手机上退出登录并重新登录 <<<') + + sc = s.create_script(JS) + events = [] + def on_msg(m, _): + if m.get('type') == 'error': + print('JS ERR:', str(m)[:200]); return + if m.get('type') != 'send': + return + p = m.get('payload') or {} + t = p.get('type') + events.append(p) + if t == 'vt_attached': + print(f"[vt] {p['name']} slot{p['slot']} @+{p['fp']}") + elif t == 'saveLD_str': + print(f"[saveLD_str] str={p['str']['t']}:{p['str']['len']}\n bean={p['bean_head']}\n bt={p['bt']}") + elif t == 'saveLD_bean': + print(f"[saveLD_bean] flag={p['flag']}\n bean={p['bean_head']}\n bt={p['bt']}") + elif t == 'cred_unpack': + print(f"[cred_unpack] in={p['in']['t']}:{p['in']['len']}:{p['in']['v'][:160]} <- {p['ra']}") + elif t == 'bigaes': + print(f"[bigaes] len={p['x2']['len']} head={p['x2']['v'][:120]}") + elif t == 'vtable': + print(f"[VT!] {p['name']}#{p['slot']} a1={p['a1']} bt={p['bt']}") + sc.on('message', on_msg) + sc.load() + deadline = time.time() + 300 + while time.time() < deadline: + time.sleep(3) + if any(e.get('type')=='bean' for e in events) and any(e.get('type')=='getcred' for e in events): + time.sleep(10) + break + Path('/Users/yml/codes/douyu_login_py/evidence/credtrace.json').write_text(json.dumps(events)) + from collections import Counter + print('saved:', Counter(e.get('type') for e in events)) + + +if __name__ == '__main__': + for attempt in range(4): + try: + main() + break + except frida.InvalidOperationError as e: + print('detached:', e) + subprocess.run(['adb', 'shell', 'am', 'force-stop', 'com.duowan.kiwi']) + time.sleep(3)