# 虎牙 32hex hdid 生成逆向研究(真机 M2102J2SC) > 目标:搞清楚 WUP 登录帧 t1.t0 / field1.tag0 的 32hex hdid(金样本 `ed0db8334cadd236c00cadf7e11ab5a5`) > 如何生成、是否能在同一台设备上铸造新值(实现"每账号独立设备")。 > 时间:2026-08-28(真机稳定注入通道打通后进行)。**已定位 32hex = NativeEntry.getGUID()。** ## 一、最终结论(决定性) **32hex hdid(WUP 登录帧 field1.tag0)= `com.huya.security.hydeviceid.NativeEntry.getGUID()` 的返回值。** - 金样本 `ed0db8...` 是**金样本设备**的 getGUID() 值; - **当前真机 M2102J2SC 的 getGUID() = `0a7dfaa882938a6ab502511452142c57`**(32hex,交叉验证稳定: 在 5 个设备上报帧中出现 + Java 主动调用一致)。 **getGUID() 每台设备唯一且稳定(硬锚硬件,同 getCDID/getHDID 一样),可被 `NativeEntry` 的 native 方法直接可靠读取。** 因此**"生成 32hex hdid" 无需逆向算法**:每台真机天然由 libhydeviceid.so 生成并提供它独有的 32hex getGUID()。多真机设备池 = 每台调 getGUID() 采集各自唯一值。 ### 单机不可铸造(3 个决定性实验) 改 `ro.serialno` / `ANDROID_ID` / 删 `files/hydevice/` 持久化后重启,设备标识(UUID 文件名 + getGUID 等)**全部不变** —— 因 libhydeviceid.so 基于底层硬件(SoC/IMEI)稳定生成,刷不掉。 ## 二、NativeEntry 全部字段(已可靠读取) 通过 dlopen 拦截 → JNI_OnLoad(0x22c4c8) → RegisterNatives(JNIEnv 函数表索引 215),dump 出 `com.huya.security.hydeviceid.NativeEntry` 的 19 个 native 方法,Java 主动调用实测值: | NativeEntry 方法 | 真机实测值 | 对应 WUP 登录帧字段 | |---|---|---| | **getGUID()** | **`0a7dfaa882938a6ab502511452142c57`** | **field1.tag0 = hdid(32hex)** | | getCDID() | `02df398797432eadefcc12767119ad5e80999389` | field2.tag2 = device_id(40hex) | | getHDID() | `7c5387e0539c023c31c4ff0e807e7256117385ee` | field2.tag8 = 另一设备ID(40hex) | | getMID() | `1e8bdf7d4f7a01d3` | MID(16hex) | | getSDID() | `PQwemAN9...`(base64 180B) | safedeviceid | - Java 类 `com.huya.security.hydeviceid.NativeEntry` 注册 method 地址(libhydeviceid.so 偏移): getCDID@0x20eb08 / getSDID@0x20ede8 / **getHDID@0x20f0c8** / init@0x20e6e4 / getGUID@0x20f8c8 / getMID@0x20fba8 / linkId@0x20fe88(其余 setPhoneInfo/setMotionEvent/上报类略)。 - 另有 `com.huyaudb.HuyaAuthCore` 注册 `init/unInit/sendMsg/receiveNet`(WUP 消息收发)。 ### hdid 名称混淆(已彻底澄清) 项目里"hdid"对应**多个不同值**: 1. **32hex(WUP 登录帧 field1.tag0)= getGUID()** —— 设备 GUID,硬锚,每台唯一; 2. 40hex `7c5387` = getHDID() = huyaudb 上报里被命名为 "hdid"(**同名不同值**); 3. 40hex `02df39` = getCDID() = device_id; 4. 16hex `1e8bdf7d4f7a01d3` = getMID(); 5. 凭据文件 `files/hydevice/`(`64a33427...`)持久化加密凭据。 ## 三、libhydeviceid.so 加壳(静态逆向极难,但已绕过) - **OLLVM 混淆**(`based on Obfuscator-LLVM 9.0.9svn`)+ **datadiv 运行时壳**(~70 个 `.datadiv_decode*` 解密函数 + `hy_fopen64/hy_read/hy_syscall/hy_write/hyftell` 文件 I/O 壳 + 读 TracerPid 反调试)。 - 用 **dlopen→JNI_OnLoad→RegisterNatives** 动态拿到方法表,绕开混淆,无需反汇编。 - 已 dump 解密后代码:`evidence/diag_phone/libhydeviceid_dump.so`(内存态)+ 原始 `libhydeviceid_original.so`。 ## 四、可行方向(服务于"每账号独立设备")——**推荐,已具备采集能力** **多真机采集设备池**:每台真机用真机注入通道(spawn+art_callsite bypass)读 `{getGUID(32hex), getCDID(40hex), getHDID(40hex), getMID(16hex), getSDID(base64)}`, 这些值每台唯一、稳定、被服务端认可。采集多台建设备池轮换,即可实现每账号独立设备。 **无需逆向铸造算法**,直接读 NativeEntry 即可。 ## 五、实验脚本(真机) - `scripts/phone_probe_registernatives2.py`(v7:dlopen→JNI_OnLoad→RegisterNatives 注册表 + get* 地址) - `scripts/phone_java_call_nativeentry.py`(**Java 主动调 NativeEntry get* 全家桶,读取 32hex GUID**) - `scripts/phone_read_hdid.py`(v8:native hook get* 用原生 JNI GetStringUTFChars 解码) - `scripts/phone_dump_hydev.py`(dump 解密后的 libhydeviceid.so) - `scripts/phone_probe_hdid*.py`(早期符号 / 属性 / 文件探针,过程记录) - 证据:`evidence/diag_phone/{hdid_regtable,hdid_read,java_nativeentry,login_frames}.json` / `libhydeviceid_{original,dump}.so`