Files
live-hub-py/docs/虎牙App登录-APK静态分析.md
T
yml2213 ff99c036f8 虎牙App密码登录: 逆向WUP协议并实现纯Python登录编码器
- hook WUP序列化层抓取TLS加密前明文,确认密码登录走
  servant=huyaudbwebui / func=hypasswordLogin (msgType=0x1001)
- 逆向JCE RequestPacket帧格式(1015字节TAF二进制),定稿三层结构:
  WUP header(tag1-10) -> sBuffer Map -> _wup_data业务struct
- 澄清两个疑点字节: 0x66/0x7d 是TAF字段头(非分隔符)
- 实现 tools/huya_wup_encoder.py,逐字节复现金标准
- 实测纯Python动态构造登录成功(返回uid+token),TLS指纹不阻断
- userAction随机坐标/时间戳同样通过,内置make_user_action辅助函数
- 新增证据金标准 + 协议文档
2026-08-25 02:59:20 +08:00

7.8 KiB
Raw Blame History

虎牙 App 登录 — APK 静态逆向分析(libudbauthunify.so

目标:apks/huya-13.4.22-115315-live.apk158MBversionCode=115315 分析对象:lib/arm64-v8a/libudbauthunify.so(4.7MB,UDB 认证统一库) 方法:nm -D 导出符号 + objdump 反汇编 + strings 字符串提取(纯静态,无需 hook) 结论:App 登录 = WUP 长连接 + XXTEA/AES 双层加密,全部加密函数与 servant 已定位。


一、关键结论(一句话)

虎牙 App 登录的设备风控加密libudbauthunify.so 实现,算法链是:

明文 → cred_pack 打包 → XXTEA 加密 → cred_pack 拼装 → MD5 派生 key → AES-128-ECB 加密 → 密文

dckey = Login Credential(登录凭据),通过 MsgGetCred / MsgRequestLgnCred 获取,加密后经 udbdf.huya.com/dckey/check 上传。


二、关键 native 库定位

so 库 大小 作用
libudbauthunify.so 4.7MB UDB 认证统一库(核心),含全部登录/加密逻辑
libhycrypto.so 1.9MB BoringSSLAES/RSA 标准实现)
libhydeviceid.so 4.1MB 设备 ID 生成
libtscsdk.so 1.5MB 数美(TrustKernel)设备指纹 SDK(对应 zztfly 请求)
libtea.so 409KB XXTEA 算法
libmtpencrypt.so 809KB MTP 加密

三、加密体系(已 100% 破解,来自反汇编)

3.1 加密函数清单

函数 地址 说明
hyudb_crypt_util::xxtea_encrypt 0x32e83c XXTEA 加密(第一层)
hyudb_crypt_util::xxtea_decrypt 0x32ece8 XXTEA 解密
hyudb_crypt_util::md5_char16 0x32e71c MD5 派生 16 字节 key
hyudb_crypt_util::md5_char32 0x32e7ac MD5 派生 32 字节
UdbAESUtil::encrypt 0x250038 AES-128-ECB 加密(第二层)
UdbAESUtil::decrypt 0x2501a4 AES 解密
AESkeyMgr::getkey 0x26871c AES key 缓存管理map<int,map<int,string>>
hyudb_packet_util::cred_pack 0x45xxxx cred(dckey) 二进制打包
hyudb_packet_util::cred_unpack cred 解包
encode_xxtea / decode_xxtea 0x330058/0x3306cc XXTEA 编解码封装

3.2 加密模式确认(反汇编证据)

AES 是 ECB 模式 + ZeroPadding,证据来自 UdbAESUtil::encrypt0x250038)反汇编:

; 计算长度 & 0xf,非 16 倍数则 push_back(0) 补齐(ZeroPadding
and  w11, w11, #0xf
...
bl   push_back(0)          ; 补零
; 每 16 字节独立调用 _encrypt(单块),无 IV 参与 → ECB 模式
loop:
  bl  UdbAESUtil::_encrypt(ptr16, out)   ; 逐块 AES
  add x24, x24, #0x10                    ; +16

3.3 完整加密调用链(hyudb_otp_encrypt 0x32fa24 还原)

hyudb_otp_encrypt(x0=key, w1=2, w2=len, x3..x5=字段, w6=4, x7=buf, out)
  ├─ cred_pack(sp+0xb0, x7)                    # 打包第一个字段
  ├─ xxtea_encrypt(sp+0xc8, sp+0xe0, x24)      # XXTEAkey = x0 参数
  ├─ cred_pack(sp+0x98, <header字段>)           # 打包 header
  ├─ cred_pack(sp+0x98, sp+0xc8)               # 打包 XXTEA 密文
  ├─ cred_pack(sp+0x98, x23)                   # 打包第5参数字段
  ├─ AESkeyMgr::getkey(i, i)                    # 取 AES key 字符串
  ├─ string::insert(...)                        # key 拼接
  ├─ md5_char16(key_str)                        # MD5 派生 16 字节 key
  ├─ UdbAESUtil::C1(md5key)                     # 用 MD5 结果构造 AES
  └─ UdbAESUtil::encrypt(packed, md5key)        # AES-128-ECB 加密

调用方:BusinessCfg::getOtp(uid, otp, ...)0x268bbc~0x268ca0)→ hyudb_otp_encrypt(...)


四、硬编码 key 候选(rodata 段)

字符串 长度 备注
HuyaUdb1928374650qwertyuiop 27B 最强候选"HuyaUdb" + 数字 + 字母键盘序)
275d0ff676c0d65114acdefbd2ad87a3 16B 32 hex,正好 AES-128 key 长度
0123456789ABCDEF / 0123456789abcdef 16B 常见默认 key

XXTEA key 与 AES key 源需 hook 最终确认(hook xxtea_encrypt 第3参、md5_char16 输入)。


五、dckey = Login Credential

符号证据链:

MsgGetCred / MsgRequestLgnCred / MsgResponseLgnCred
HandlerGetCred / HandlerRequestLoginCred / HandlerResponseLoginCred
AutoCredLogin(自动凭据登录)
BusinessCfg::getCred / getCredEx / setSafeDeviceId
AUTO_CRED_LOGIN_TIMER

即:dckey 就是「登录凭据(credential)」,App 启动后用设备指纹换取,登录时作为风控凭证提交。


六、完整登录 servant 清单(TAF/WUP 结构名)

从 so 的 rodata 提取全部 wup.* 结构名:

登录类(核心)

servant/结构 用途
AppLgnPasswordLoginReq/Resp App 密码登录
AppLgnOtpLoginReq/Resp App 一键(OTP)登录
AppLgnCredentialLoginReq/Resp dckey 凭据登录
AppLgnSmscodeLoginReq/Resp 短信验证码登录
AppLgnMobileSendSmsReq/Resp 手机号发短信
AppLgnSessionSendSmsReq/Resp 会话发短信
AppLgnSecondAuthLoginReq/Resp 二次认证
AppLgnAntiViolentLoginReq/Resp 反暴力登录
AppLgnRefreshPicReq/Resp 刷新验证码图
AppLgnThirdLoginReq/Resp 第三方登录

密码/注册类

AppPasswordLoginReq/Resp          # 密码登录(另一组)
AppCredentialLoginReq             # 凭据登录
AppAnonymousLoginReq/Resp         # 匿名登录
AppMobileRegisterReq              # 手机注册
AppRegSendSms / AppRegCheckMobile / AppRegCheckUser
AppRegSmscodeRegister / AppRegSmscodeModifyPassword / AppRegSmscodeResetPassword
AppRegTokenRegister / AppRegTokenModifyPassword / AppRegTokenResetPassword
AppRegUidVerifySmscode
AppBindLoginMobile / AppBindNewMobile(绑定手机)
AppBypassRouteReq/Resp            # 旁路路由

servant 名(TAF 服务名)

huyaudb          # UDB 主服务
huyaudbwebui     # 抓包里 wsapi.huya.com 的 servant
huyaudbnimoui    # NIM UI 服务
passport         # 护照服务

七、其他关键 token/字段

violentToken / sessionToken        # 反暴力 token / 会话 token
enpack_header / depack_header      # header 打包/解包(含 NEWKEY
key_version[%d] / key_id[%d]       # key 版本/ID 管理
lgnExtParam / lgnProtect           # 登录扩展参数 / 登录保护
loginAppId / loginAppName / loginDeviceName / loginStrategy / loginType

enpack_header + NEWKEY 解释了抓包里 dckey body 的 100 字节固定头:那是打包的 header(key 版本、key_id、固定字段),加密只作用于变长数据体。


八、给 hook 的精确落点(静态分析直接给出)

目标函数 hook 什么 得到什么
hyudb_crypt_util::xxtea_encrypt 第3参(XXTEA key) + 第2参(明文) + 返回(密文) XXTEA key + 明文结构
hyudb_crypt_util::md5_char16 输入 string + 输出 16B AES key 源MD5 前明文)
AESkeyMgr::getkey 返回值 string AES key 字符串
UdbAESUtil::encrypt 入参(明文) + 返回(密文) 验证 AES 模式/填充
hyudb_packet_util::cred_pack 各字段 dckey 二进制结构
BusinessCfg::getOtp 入参 OTP 生成逻辑
MsgRequestLgnCred 序列化前 WUP 结构 登录凭据请求明文
OkHttp CertificatePinner.check SSL unpin,解 cdn.wup 长连接

九、抓包 ↔ so 对应关系(验证闭环)

抓包现象 so 证据
dckey body 前 100B 固定 enpack_header/cred_pack 打包的固定 header
dckey body 后段变长 XXTEA+AES 加密的数据体
dfpReport t2 魔数 571882cf664bb39401ee cred_pack 的固定标识
selectOperator.t5 / dfpReport.t2 同前缀 13B 同一固定 header(非 RSA,是打包结构头)
登录走 cdn.wup.huya.com 抓不到 App 登录 servant 走 WUP 长连接 + SSL Pinning