王者营地英雄战力数据抓包实战:从 SSL Pinning 绕过到 Frida 动态插桩
背景:近期在研究王者荣耀英雄战力数据时,需要通过王者营地 App 获取官方战力榜接口参数。过程中遇到了 HTTPS 抓包失败、SSL Pinning 拦截等问题,最终通过 Frida 动态插桩成功绕过,完整记录下这次技术探索过程。
一、目标与需求
需要获取王者营地 App 中英雄战力榜的官方接口参数,用于查询:
- 全国/省/市/区各级榜单
- 英雄最低上榜战力
- 英雄排名数据
目标接口:
POST https://kohcamp.qq.com/honor/ranklist
二、初步尝试:直接抓包
2.1 环境准备
- 工具:Fiddler5.0 + HttpCanary + 雷电模拟器9(Android 9.0)
- 配置:模拟器 WiFi 代理指向 Fiddler(端口 8888)
- 证书:Fiddler 根证书已安装到模拟器用户证书目录
2.2 遇到的问题
抓包时发现所有 HTTPS 请求都显示为 CONNECT 隧道,无法解密(甚至都抓不到HTTPS的流量,这个我怀疑是抓包工具的问题,后面换成HttpCanary正常的):
CONNECT galileotelemetry.tencent.com:443 HTTP/1.1
Host: galileotelemetry.tencent.com:443
Connection: Keep-Alive
User-Agent: okhttp/4.9.1
A SSLv3-compatible ClientHello handshake was found...
原因分析:王者营地 App 使用了 SSL Pinning(证书锁定) 技术,检测到 Fiddler 的中间人证书后拒绝连接,导致 Fiddler 只能看到 TCP 握手层,无法获取应用层 HTTP 内容。
三、解决方案选择
| 方案 |
原理 |
难度 |
适用性 |
| Xposed + JustTrustMe |
模块绕过证书校验 |
中 |
需要 Root + Xposed |
| Frida 动态插桩 |
运行时 Hook 修改验证逻辑 |
中高 |
无需 Xposed,更灵活 |
| HttpCanary |
内置 SSL Pinning 绕过 |
低 |
部分版本需 Root |
| 降级 Android 版本 |
低版本默认信任用户证书 |
低 |
功能可能受限 |
最终选择 Frida,原因:
- 无需安装 Xposed 框架
- 可以精确 Hook 目标方法
- 对系统侵入性较小
四、Frida 环境搭建
4.1 安装 Frida 工具链
首先你的电脑环境得先安装了python。
# 电脑端安装 frida-tools
pip install frida-tools
# 验证版本
frida --version
# 输出:17.9.5
4.2 部署 frida-server 到手机
# 查看手机架构
adb shell getprop ro.product.cpu.abi
# 输出:x86_64
# 下载对应版本 frida-server
# https://github.com/frida/frida/releases
# frida-server-17.9.5-android-x86_64.xz
# 解压并重命名
xz -d frida-server-17.9.5-android-x86_64.xz
mv frida-server-17.9.5-android-x86_64 frida-server
# 推送到手机
adb push frida-server /data/local/tmp/
# 赋予执行权限
adb shell "chmod 755 /data/local/tmp/frida-server"
4.3 启动 frida-server
# 需要 Root 权限启动
adb shell
su
/data/local/tmp/frida-server &
常见问题:
Address already in use:frida-server 已在运行,无需重复启动
Permission denied:未获取 Root 权限
4.4 验证连接
frida-ps -U
看到手机进程列表说明连接成功。
五、编写 SSL Pinning 绕过脚本
5.1 脚本原理
SSL Pinning 绕过核心思想:Hook 住 App 中验证服务器证书的方法,让其永远返回"验证通过"。
王者营地使用的技术栈:
- HTTP 客户端:OkHttp 4.9.1
- SSL 验证:Android 系统 TrustManagerImpl
- 域名验证:HostnameVerifier
5.2 完整脚本(ssl-bypass.js)
Java.perform(function() {
console.log(" Hooking 王者营地 SSL");
// 1. Hook 系统级证书校验(核心)
var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");
var ArrayList = Java.use("java.util.ArrayList");
TrustManagerImpl.checkTrustedRecursive.implementation = function() {
console.log("[+] checkTrustedRecursive() bypassed");
// 直接返回空列表,跳过所有证书链校验
return ArrayList.$new();
};
// 2. Hook OkHttp 证书锁定
try {
var CertificatePinner = Java.use("okhttp3.CertificatePinner");
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {
console.log("[+] OkHttp CertificatePinner bypassed");
};
} catch(e) {
console.log("[-] OkHttp CertificatePinner not found");
}
// 3. Hook 域名验证
try {
var hostnameVerifier = Java.use("javax.net.ssl.HostnameVerifier");
var MyHostnameVerifier = Java.registerClass({
name: 'com.example.MyHostnameVerifier',
implements: [hostnameVerifier],
methods: {
verify: function(hostname, session) {
console.log("[+] Hostname verified: " + hostname);
return true; // 任何域名都通过
}
}
});
var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection");
HttpsURLConnection.setDefaultHostnameVerifier(MyHostnameVerifier.$new());
} catch(e) {
console.log("[-] HostnameVerifier hook failed");
}
console.log(" Hooks ready");
});
5.3 关键方法解析
| Hook 目标 |
原始功能 |
Hook 后效果 |
TrustManagerImpl.checkTrustedRecursive() |
递归验证证书链是否可信 |
直接返回空列表,跳过校验 |
CertificatePinner.check() |
OkHttp 验证证书指纹 |
空实现,不执行校验 |
HostnameVerifier.verify() |
验证域名与证书匹配 |
永远返回 true |
六、执行 Hook 与抓包
6.1 Attach 到运行中的进程
# 1. 先手动打开王者营地 App
# 2. 查看进程 PID
frida-ps -U | findstr 王者
# 输出:3987 王者营地
# 3. Attach 并加载脚本
frida -U -p 3987 -l "ssl-bypass.js"
成功后会看到:
[+] Hostname verified: galileotelemetry.tencent.com
[+] Hostname verified: galileotelemetry.tencent.com
6.2 配合 Fiddler 抓包
注意:Frida 绕过了 App 的证书校验,但 Fiddler 还需要被 Android 系统信任。
证书安装步骤:
# 导出 Fiddler 证书到桌面
# Tools → Options → HTTPS → Actions → Export Root Certificate
# 推送到系统证书目录(模拟器已 Root)
adb root
adb remount
adb push FiddlerRoot.cer /system/etc/security/cacerts/
adb shell "chmod 644 /system/etc/security/cacerts/FiddlerRoot.cer"
adb reboot
6.3 触发战力查询接口
在王者营地 App 中操作:
- 打开「工具箱」→「荣耀榜」
- 选择英雄
- 切换地区(全国/省/市/区)
七、获取到的接口参数
7.1 请求示例
POST https://kohcamp.qq.com/honor/ranklist HTTP/1.1
Host: kohcamp.qq.com
token: eyJhbGciOiJIUzI1NiIs...
userId: 123456789
openid: oABC123...
appid: 1104466820
version: 8.94.0417
Content-Type: application/json
{
"adcode": "310000", // 地区代码:上海
"roleId": "116581781", // 角色ID
"areaId": "3", // 大区:3=微信安卓
"heroId": "146", // 英雄ID:146=露娜
"recommendPrivacy": 0
}
7.2 关键参数说明
| 参数 |
位置 |
说明 |
token |
Header |
营地登录态令牌 |
userId |
Header |
营地用户ID |
openid |
Header |
微信/QQ OpenID |
roleId |
Body |
游戏角色ID |
areaId |
Body |
大区代码:1=QQ安卓, 2=iOS, 3=微信安卓, 4=微信iOS |
heroId |
Body |
英雄ID,可从 herolist.json 获取 |
adcode |
Body |
行政区划代码:100000=全国, 310000=上海等 |
八、完整技术总结
8.1 问题解决路径
直接抓包失败(CONNECT 隧道)
↓
识别 SSL Pinning 问题
↓
选择 Frida 动态插桩方案
↓
搭建 Frida 环境(frida-server + 客户端)
↓
编写 Hook 脚本(绕过证书校验)
↓
Attach 到目标进程
↓
配合 Fiddler 系统证书
↓
成功获取明文接口参数
8.2 核心知识点
- SSL Pinning:App 将服务器证书指纹硬编码,防止中间人攻击
- Frida 动态插桩:运行时修改内存中的方法实现,无需修改 APK
- TrustManagerImpl:Android 底层证书链验证核心类
- OkHttp CertificatePinner:应用层额外的证书指纹校验
8.3 注意事项
- 法律合规:仅供学习研究,勿用于商业或恶意用途
- 账号安全:token 等凭证有有效期,勿泄露
- 请求频率:避免高频调用,防止被封
- 接口变动:官方可能随时更新接口,需持续关注
九、参考资源
结语:这次探索从抓包失败到深入理解 SSL Pinning 机制,再到掌握 Frida 动态插桩技术,收获颇丰。移动安全领域还有很多值得深挖的方向,保持好奇心,持续学习。