feat(huya): isNative定案NativeBridge纯Java + GUID值流还原(服务端sGuid签发) + unidbg金测试恢复
- dex直读判定: NativeBridge.b/a/c/g/h/klog全为Java(classes5), NativeEntry全native; .data描述符块=GetStaticMethodID反向调Java的name/sig常量表 - GUID值流完整还原: native getGUID=纯缓存getter(pref hydeviceid_guid -> WupHelper.getGuid() -> b(100) -> 回写) YYProtoSdkModule.initHuyaUdbSdk(classes17)->HyDeviceProxy.j(appid,WupHelper.getGuid(),mid)->pnc.a WupHelper.getGuid->HalImpl.getGuid->sGuidProperty<--live-launch服务端LiveLaunchRsp.sGuid(32hex硬校验) - 修正结论: GUID非本地指纹公式, 铸币=服务端doLaunch/device_register按虚拟设备指纹签发sGuid - unidbg: 新harness回归根因=C++ locale/facet在unidbg libc++上ABI崩溃; 旧harness+当前merged恢复金测试MATCH, 实证native缓存写回流 - 新工具: tools/dex_probe_native.py(dex access_flags判定), tools/dex_scan_calls.py(跨dex调用点扫描)
This commit is contained in:
@@ -237,3 +237,65 @@ lib 内置大量模拟器检测串(qemu_pipe / mumuvmm / genymotion / windroye
|
||||
b 一旦真注册,`(ANDROID_ID → GUID)` 差分对即可在 unidbg 内批量生成 → MD5/SHA1/AES 对拍。
|
||||
3. b 的 fnPtr 兜底获取:运行期 dump hydeviceid .data 时同时读 JNINativeMethod 运行期构造表
|
||||
(spawn+bypass 一次抓全,附 base 校验)。
|
||||
|
||||
## 十一、静态还原定案(2026-08-29 凌晨,PC 侧完成,无需 SPAWN/真机)
|
||||
|
||||
### 11.1 isNative 判定 = 纯 Java(dex 直读,比 SPAWN 更硬)
|
||||
- 工具 `tools/dex_probe_native.py`(dex 解析器)扫全部 18 个 classes*.dex:
|
||||
- `NativeBridge`(classes5.dex):`b(I)L..;`、`a/c/g/h/klog/i1/i2/j` **全部为 Java**(有 code_off),
|
||||
**无任何 native 方法** —— 10.1 的怪象全部解释:JNI_OnLoad 只 FindClass+NewGlobalRef 是因为
|
||||
没有任何 native 需要注册;.data@0x3e31e4(vaddr 0x3e41e4) 的描述符块(klog/b/c/h/g/getDataDir/getPath
|
||||
+类名 com/huya/security/hydeviceid/NativeBridge + com/duowan/biz/wup/WupHelper) =
|
||||
**native 代码运行期 GetStaticMethodID 反向调用 Java 的 name/sig 常量表**。
|
||||
- `NativeEntry`:getGUID/getCDID/getHDID/getMID/getSDID/init 全部 native(code_off=0,RN 19 条已实锤)。
|
||||
- `NativeBridge.b(I)` = `fj3.c(I)` 分发器(DeviceInfo.java),`b(100)` → `pnc.c()` → 静态 `pnc.a`。
|
||||
|
||||
### 11.2 GUID 值流完整还原(GUID ≠ 本地指纹公式!)
|
||||
- **native getGUID = 纯缓存 getter**(unidbg 旧配置金测试实证):
|
||||
`pref hydeviceid_guid` → 空则 Java `WupHelper.getGuid()` → `NativeBridge.b(100)` → 回写 pref 并返回。
|
||||
即 unidbg 金测试的"GUID 一致"= Java 桩直喂 golden 的闭环,**从未验证过本地公式**。
|
||||
- Java 链(每环唯一调用者/写入者,交叉验证):
|
||||
```
|
||||
YYProtoSdkModule.initHuyaUdbSdk (classes17.dex, code@0x3834d0)
|
||||
→ HyDeviceProxy.j(HY_APPID, WupHelper.getGuid(), mid) (setAppInfoId)
|
||||
→ pnc.k(guid) → pnc.a
|
||||
→ NativeBridge.b(100) → fj3.c(100) → pnc.c()
|
||||
WupHelper.getGuid() (classes12.dex) = ((IHal)hlf.i(IHal.class)).getGuid()
|
||||
→ HalImpl.getGuid() = sGuidProperty.get()
|
||||
→ sGuidProperty 仅两处写入: initCache() 与 initialInner 网络回调 →
|
||||
LiveLaunchRsp.sGuid (live-launch/doLaunch 服务端响应, 32hex 硬校验: 非32位触发 mIllegalGuidCallBack)
|
||||
```
|
||||
- **结论修正(推翻 §9.3"GUID=f(androidId密, config, MID)")**:铸币本体不是本地算法,而是
|
||||
**服务端 doLaunch/device_register 按设备指纹签发 sGuid**。doLaunch 请求携带
|
||||
`LiveUserbase{tUAEx.sDeviceId(Config 持久化), sIMEI, sMId} + tId(userId.sGuid=当前guid, lUid)}`;
|
||||
响应 `sGuid` 即后续所有登录帧 tag0 的 32hex hdid。
|
||||
- 与既有认知吻合:旧实验"改 ANDROID_ID/全清数据 GUID 不变"(服务端签发+本地缓存)、
|
||||
`tools/` 注记"hdid 服务端硬锚/不可铸造"。
|
||||
|
||||
### 11.3 新工具(PC 侧,无设备依赖)
|
||||
- `tools/dex_probe_native.py`:dex 类/方法 access_flags 判定(含 class_data fields 跳过修复)。
|
||||
- `tools/dex_scan_calls.py`:跨 dex 指令级扫描指定方法的调用点(找 setAppInfoId→j() 即用此)。
|
||||
- 用法:`python3 tools/dex_probe_native.py work/apk_extract` /
|
||||
`python3 tools/dex_scan_calls.py work/apk_extract Lcom/hy/HyDeviceProxy; j "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"`
|
||||
|
||||
### 11.4 unidbg 金测试回归修复(重要教训)
|
||||
- 症状:新 harness(加入 libudbauthunify 第二库 + 扩展桩)后 getGUID/getCDID/… 全 null,
|
||||
init 阶段 Dynarmic "assertion failed" 崩溃(PC 跳 libc++ 零区)。
|
||||
- 根因:**C++ locale/facet 路径**(`std::locale::use_facet`、`ios_base::getloc` 等)在 unidbg
|
||||
内置 libc++ 上 ABI 不兼容;第二库加载改变了执行路径触达该处。
|
||||
- 修复/验证:**14:16 金测试同款 harness(无 udb 第二库,git 70621cf)+ 当前 merged so →
|
||||
getGUID = 0a7dfaa882938a6ab502511452142c57 MATCH**,并首次实证 native 缓存写回流程
|
||||
(WupHelper.getGuid→null → b(100)→golden → prefs-put hydeviceid_guid → return)。
|
||||
- dump 真实运行基址 = **0x7814200000**(非 probe 记录的 0x7813211000);merge v3 重定位结果
|
||||
正确(merged = dump - 0x7814200000 = 模块内偏移)。
|
||||
|
||||
### 11.5 铸币路径重定义(下一步蓝线)
|
||||
1. **服务端签发复现**:用现有纯 Python WUP 链(tools/huya_wup_encoder.py 等)构造虚拟设备指纹的
|
||||
`doLaunch`/`device_register` 请求(deviceId/IMEI/mid 取自虚拟 profile)→ 收 sGuid →
|
||||
**先验确定性**:同一指纹多次请求 sGuid 是否一致 / sGuid 是否 = f(请求设备字段)。
|
||||
2. 若确定性签发:`device_mint.py` = 虚拟指纹 → doLaunch → sGuid →(可选 dfpReport 注册)
|
||||
→ 现有 WUP 登录链验证服务端接受度(用户既有"每账号一套全新虚拟身份"验收口径不变)。
|
||||
3. 若 sGuid 随机签发(仅库内下发),则评估"锁定身份"的现实等价物:设备指纹→注册→登录
|
||||
全链路用同一份虚拟 profile 保持一致性,铸币=整套身份模板随机化。
|
||||
- 真机/未决项:sGuid 签发是否依赖 qimei16/36、hdid/cdid/sdid 上报(采集器还是把设备信息上报
|
||||
给 dfpReport 侧),这些在 §六 的注册链实测中一并验证。
|
||||
|
||||
Reference in New Issue
Block a user