某鱼自定义协议请求抓包+加密参数分析
字数 1217 2025-09-01 11:26:17
某鱼自定义协议请求抓包与加密参数分析教学文档
1. 背景介绍
某些淘系APP(如某鱼)使用私有协议(如SPDY)进行网络通信,导致传统抓包工具(如Charles、Fiddler)无法直接抓取数据包。本文档将详细介绍如何绕过该私有协议,并分析其请求参数的生成过程。
2. 私有协议绕过方法
2.1 定位私有协议开关
- 使用jadx打开APK文件
- 搜索关键词"spdy",可以找到多个与私有协议相关的类和方法
- 查找传入布尔值的函数,这些通常是控制SPDY协议开关的函数
2.2 Hook方法
有三种主要Hook方法可以绕过私有协议:
- Frida Hook:动态修改函数参数
- Xposed Hook:系统级Hook框架
- 其他Hook框架
2.3 具体Hook实现
找到控制SPDY开关的函数后,通过Hook修改传入参数为false,强制使用HTTP协议:
// Frida Hook示例
Interceptor.attach(targetFunction, {
onEnter: function(args) {
// 修改传入参数为false
args[1] = ptr(0); // 假设第二个参数是布尔值
}
});
3. 请求参数分析
3.1 关键参数识别
成功Hook后,可以在Charles中看到以下关键参数:
x-t:时间戳相关x-c-traceid:追踪IDx-sign:签名参数x-sgext:扩展参数x_mini_wua:设备信息相关x_umt:用户标识相关
3.2 参数定位方法
- 修改法:逐个修改或去掉参数,观察请求响应变化
- 比较法:不同请求间比较参数差异
- Hook法:Hook HashMap的put方法,跟踪参数构造过程
// Hook HashMap.put方法示例
Java.perform(function() {
var HashMap = Java.use("java.util.HashMap");
HashMap.put.implementation = function(key, value) {
if (key.toString().indexOf("x-") === 0) {
console.log("Header Param: " + key + " = " + value);
console.log(Java.use("android.util.Log").getStackTraceString(
Java.use("java.lang.Throwable").$new()));
}
return this.put.call(this, key, value);
};
});
4. 加密参数生成分析
4.1 定位关键函数
通过堆栈分析发现可疑函数getUnifiedSign,这是生成加密参数的核心函数。
4.2 Hook关键函数
使用jadx找到getUnifiedSign函数,右键选择"复制为Frida片段"快速生成Hook代码:
Java.perform(function() {
var targetClass = Java.use("com.xxx.xxx.SignUtils");
targetClass.getUnifiedSign.implementation = function(map, str) {
console.log("getUnifiedSign called with:");
console.log("map: " + JSON.stringify(map));
console.log("str: " + str);
var result = this.getUnifiedSign.call(this, map, str);
console.log("result: " + result);
return result;
};
});
4.3 参数生成方式
有两种方式获取加密参数:
- 逆向分析:分析代码逻辑,逆向出加密算法
- RPC调用:直接调用原函数获取加密参数
5. RPC方式实现加密参数生成
5.1 RPC原理
RPC(Remote Procedure Call)允许外部程序(如Python)通过Frida调用目标应用内部的函数。
5.2 实现步骤
- 在JS脚本中导出加密函数
- Python构造请求参数
- 通过Frida调用JS导出的函数获取加密参数
- 使用加密参数发起请求
5.3 示例代码
JS部分(Frida脚本):
rpc.exports = {
generateSign: function(headerJson, dataJson) {
Java.perform(function() {
var HashMap = Java.use("java.util.HashMap");
var headerMap = HashMap.$new();
for (var key in headerJson) {
headerMap.put(key, headerJson[key]);
}
var SignUtils = Java.use("com.xxx.xxx.SignUtils");
var result = SignUtils.getUnifiedSign(headerMap, dataJson);
return result;
});
}
};
Python部分:
import frida
import json
import requests
# 连接Frida
device = frida.get_usb_device()
session = device.attach("com.xxx.xxx")
# 加载JS脚本
with open("script.js", "r") as f:
js_code = f.read()
script = session.create_script(js_code)
script.load()
# 构造请求参数
headers = {
"User-Agent": "xxx",
"Content-Type": "application/json"
}
data = {
"keyword": "手机",
"page": 1
}
# 调用RPC获取加密参数
sign_result = script.exports.generate_sign(headers, json.dumps(data))
# 更新请求头
headers.update({
"x-sign": sign_result["x-sign"],
"x-sgext": sign_result["x-sgext"],
"x_mini_wua": sign_result["x_mini_wua"],
"x_umt": sign_result["x_umt"]
})
# 发起请求
response = requests.post("https://api.xxx.com/search", headers=headers, json=data)
print(response.text)
6. 总结
- 私有协议绕过:通过Hook SPDY开关函数强制使用HTTP协议
- 参数分析:使用HashMap.put Hook定位关键参数生成位置
- 加密分析:通过Hook getUnifiedSign函数分析加密参数生成
- RPC实现:直接调用原函数获取加密参数,避免逆向算法
7. 注意事项
- 不同版本APP可能使用不同的加密方式,需要重新分析
- 频繁调用RPC可能影响性能,生产环境建议逆向算法
- 注意法律合规性,仅用于安全研究和授权测试