Files
live-hub-py/docs/HUYA_HDID_RESEARCH.md
T
yml2213 0c6aff6a6d docs(huya): 逆向定位 32hex hdid = NativeEntry.getGUID() + 真机注入通道证据
核心结论:
- 32hex hdid (WUP 登录帧 field1.tag0) = com.huya.security.hydeviceid.NativeEntry.getGUID()
- 金样本 ed0db8 为金样本设备 GUID; 当前真机 M2102J2SC getGUID()=0a7dfaa882938a6ab502511452142c57(稳定)
- NativeEntry 全字段: getGUID(32hex)/getCDID(40hex)/getHDID(40hex)/getMID(16hex)/getSDID(base64 safedeviceid)
- 单机不可铸造: 改 serialno/ANDROID_ID/删files/hydevice持久化 均不变(硬锚底层硬件)
- libhydeviceid.so 为 OLLVM+datadiv 壳; 用 dlopen->JNI_OnLoad->RegisterNatives(env表索引215) 绕开混淆

脚本: phone_probe_registernatives2(注册表)/phone_java_call_nativeentry(Java读getGUID)/phone_read_hdid(native hook)
      phone_dump_hydev(dump解密so)/phone_probe_login_frame(登录帧)/arm64_disasm(反汇编)
证据: hdid_regtable/java_nativeentry/hdid_read/login_frames/hdid_probe* + libhydeviceid_{original,dump}.so
2026-08-28 12:30:34 +08:00

75 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 虎牙 32hex hdid 生成逆向研究(真机 M2102J2SC)
> 目标:搞清楚 WUP 登录帧 t1.t0 / field1.tag0 的 32hex hdid(金样本 `ed0db8334cadd236c00cadf7e11ab5a5`
> 如何生成、是否能在同一台设备上铸造新值(实现"每账号独立设备")。
> 时间:2026-08-28(真机稳定注入通道打通后进行)。**已定位 32hex = NativeEntry.getGUID()。**
## 一、最终结论(决定性)
**32hex hdidWUP 登录帧 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 = hdid32hex** |
| getCDID() | `02df398797432eadefcc12767119ad5e80999389` | field2.tag2 = device_id40hex |
| getHDID() | `7c5387e0539c023c31c4ff0e807e7256117385ee` | field2.tag8 = 另一设备ID40hex |
| getMID() | `1e8bdf7d4f7a01d3` | MID16hex |
| 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. **32hexWUP 登录帧 field1.tag0= getGUID()** —— 设备 GUID,硬锚,每台唯一;
2. 40hex `7c5387` = getHDID() = huyaudb 上报里被命名为 "hdid"**同名不同值**);
3. 40hex `02df39` = getCDID() = device_id
4. 16hex `1e8bdf7d4f7a01d3` = getMID()
5. 凭据文件 `files/hydevice/<UUID>``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`v7dlopen→JNI_OnLoad→RegisterNatives 注册表 + get* 地址)
- `scripts/phone_java_call_nativeentry.py`**Java 主动调 NativeEntry get* 全家桶,读取 32hex GUID**
- `scripts/phone_read_hdid.py`v8native 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`