# TNG eWallet 滑动验证码(阿里云 Captcha)逆向笔记(2026-08-03) ## 现象 注册/登录手机号页点「继续」→ 弹阿里云滑动拼图验证 → 滑块拖对通过 → **不返回**(TTCaptcha 未回调 TNG 业务层)→ 手动点「继续」→ 再次弹验证 → 循环。 ## 回调链(1.9.10 dex 逆向) ``` 用户滑动成功 → JS postMessage → CaptchaWebViewDialog$2.a (action=sendAliyunCaptchaVerifyData, data 含 success/message) → Captcha.generateResult(char, zzbfs) → JSON {code, retCode, message, certifyId} → setVerifyResult(true) → Captcha$1(Handler) → VerificationCallback.onSuccess(result) → TTCaptcha 反射 Proxy → TTCaptchaCallback.callBack(result) → parseJson → TTCaptchaResponse{code, certifyId} code==0 且 certifyId 非空 ? → notifySuccess(certifyId) → TTInListener.success → TNG 业务层提交 RPC → notifyFailure(code) / handleFailure("Result is null"|"Invalid code or certifyId") → 服务端二次校验 certifyId 失败 → quake 抛 CaptchaNeededException("Captcha needed") / CaptchaNotPassedException("Captcha not passed") → 验证拦截器再弹滑块 → 循环 ``` ## 关键类(dex 定位) | 类 | 作用 | |----|------| | `com.aliyun.captcha.Captcha`(classes10) | 单例,verify/generateResult/showDialog | | `com.aliyun.captcha.CaptchaWebViewDialog` + `$2` | 滑块 WebView + JS postMessage 桥 | | `com.aliyun.TigerTally.captcha.api.TTCaptcha` | TigerTally 封装,**反射**调 aliyun Captcha | | `com.aliyun.TigerTally.captcha.core.TTCaptchaCallback` | 解析 result,code==0 且 certifyId 非空才 success | | `my.com.tngdigital.captcha.TigerTallyApiWrapper` | TNG 业务侧封装(Kotlin 协程 showCaptcha) | | `...aliservice.quake.CaptchaNeededException` / `CaptchaNotPassedException` | 服务端要验证 / 验证未通过 | | `...amcs.CaptchaConfigCenter` / `CaptchaInitializer` | 远程下发 wafCaptchaKey / captcha_switch | | `...opmpaasexpress.interceptor.OpMpVerifyInterceptor` 等 | RPC 验证拦截器,触发滑块 | ## 判定点(本次 hook 已打点) 1. `Captcha.generateResult` 返回的 JSON —— **certifyId 是否为空**(滑块是否真正拿到服务端签发) 2. `CaptchaWebViewDialog$2.a` —— JS postMessage 的 data 内容 3. `TTCaptchaCallback.callBack/notifySuccess/notifyFailure` —— TNG 是否拿到 certifyId 4. `CaptchaNeeded/NotPassedException` 构造 message —— 服务端二次校验失败原因 5. `TTCaptcha.verifyByReflect/buildParams` —— captcha 参数(region/appKey 等) ## 根因候选 - **TigerTally 设备指纹(umidToken)异常**:`hookTigerTally` 短路了 `TigerTallyAPI.init/initCommon` 与 `t.B.genericNt1`(防 ANR fork 卡死)。 若 captcha 服务端用 umidToken 校验设备,缺失/变化会导致 certifyId 校验失败。 - **captcha 全量方法打点拖慢 JS 桥回调**(已修复:改为精准打点)。 - **region 错误**:`TTCaptcha.buildParams` 用 `t.B.genericNt14()` 取 region。 ## 抓 logcat 判定 ```powershell powershell -File scripts/logcat-tng.ps1 ``` 复现滑块 → 观察: - `captcha JS postMessage` 后是否有 `captcha RET generateResult`(含 certifyId) - `captchaCb CALL notifySuccess` 是否出现(成功)还是 `notifyFailure` - `captcha EXC ...CaptchaNotPassedException` 的 msg