pdd搜索请求分析+加密参数部分分析
字数 1493 2025-09-01 11:26:17
PDD App搜索请求加密参数anti-token逆向分析教学文档
1. 分析背景与目标
分析PDD(拼多多)App搜索请求中的加密参数anti-token,目标是通过逆向工程技术定位并获取该参数,实现搜索请求的复现。
2. 工具准备
- jadx: Java反编译工具,用于分析APK代码
- Charles: 网络抓包工具,用于捕获和分析HTTP请求
- frida: 动态分析工具,用于运行时Hook和RPC调用
- IDA Pro: 反汇编工具,用于分析native层代码
3. 请求分析流程
3.1 抓包分析
- 使用Charles抓取PDD App的搜索请求
- 观察请求参数,发现存在加密参数
anti-token - 确认
anti-token为必要参数,缺失时无法获得正确响应
3.2 Java层分析
3.2.1 定位参数生成位置
- Hook HashMap.put方法:
- 由于header构造通常使用HashMap,可以Hook其put方法
- 当参数为
anti-token时打印调用堆栈
// frida hook代码示例
Java.perform(function() {
var HashMap = Java.use('java.util.HashMap');
HashMap.put.implementation = function(key, value) {
if (key === 'anti-token') {
console.log('anti-token:', value);
console.log(Java.use("android.util.Log").getStackTraceString(
Java.use("java.lang.Throwable").$new()));
}
return this.put.call(this, key, value);
};
});
- 通过堆栈定位关键类:
- 对比抓包结果和堆栈信息,定位到
com.xunmeng.pinduoduo.secure.DeviceNative类
- 对比抓包结果和堆栈信息,定位到
3.2.2 反编译分析
- 使用jadx打开APK,搜索
anti-token相关信息 - 定位到关键方法
getAntiToken(),发现其调用了native方法deviceInfo2()
// 伪代码
public String getAntiToken() {
try {
return deviceInfo2(context, System.currentTimeMillis());
} catch (Throwable unused) {
return "";
}
}
- 查找实现类:
- 由于直接跟进会跳转到接口定义,需要搜索方法名
f(需重命名后搜索) - 最终定位到实现类
com.xunmeng.pinduoduo.secure.DeviceNative
- 由于直接跟进会跳转到接口定义,需要搜索方法名
4. RPC调用方案
4.1 RPC原理
无需了解具体生成逻辑,直接动态调用内部函数获取返回值作为请求参数。
4.2 实现代码
// frida RPC代码
rpc.exports = {
getAntiToken: function() {
var result = "";
Java.perform(function() {
var DeviceNative = Java.use("com.xunmeng.pinduoduo.secure.DeviceNative");
var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
var context = currentApplication.getApplicationContext();
var timestamp = Java.use("java.lang.System").currentTimeMillis();
result = DeviceNative.deviceInfo2(context, timestamp);
});
return result;
}
};
4.3 Python调用示例
import frida
def get_anti_token():
session = frida.get_usb_device().attach("com.xunmeng.pinduoduo")
script = session.create_script(open("rpc.js").read())
script.load()
return script.exports.getantitoken()
5. Native层分析
5.1 定位动态加载的so文件
- Hook JNI注册过程:
- 拦截
RegisterNatives函数调用 - 获取native方法注册时的so模块信息
- 拦截
// frida hook RegisterNatives代码
Interceptor.attach(addrRegisterNatives, {
onEnter: function(args) {
var java_class = args[1];
var class_name = Java.vm.tryGetEnv().getClassName(java_class);
if (class_name.indexOf("com.xunmeng.pinduoduo.secure.DeviceNative") !== -1) {
var methods_ptr = args[2];
var method_count = args[3].toInt32();
for (var i = 0; i < method_count; i++) {
var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
var name = Memory.readCString(name_ptr);
var sig = Memory.readCString(sig_ptr);
var mod = Process.findModuleByAddress(fnPtr_ptr);
console.log("name:", name, "sig:", sig, "module:", mod.name, "offset:", fnPtr_ptr.sub(mod.base));
}
}
}
});
- 运行结果:
- 定位到
deviceInfo2函数位于libpddsecure.so中
- 定位到
5.2 IDA静态分析
- 使用IDA打开
libpddsecure.so - 定位到
deviceInfo2函数 - 发现使用了OLLVM混淆,反混淆难度大
5.3 函数逻辑分析
初步分析表明:
- 函数会读取大量设备信息
- 结合时间戳生成一个与设备和时间相关的值
- 该值作为
anti-token用于请求验证
6. 总结与建议
6.1 技术总结
-
参数定位:
- 通过Hook常用类方法定位关键代码
- 结合堆栈分析和字符串搜索缩小范围
-
RPC方案:
- 适用于快速获取参数值而不关心生成逻辑
- 需要保持运行环境一致性
-
Native分析:
- 动态注册的native方法需要通过Hook JNI注册过程定位
- 混淆代码增加了静态分析难度
6.2 实践建议
- 对于数据爬取需求,优先考虑RPC方案
- 对于安全研究,可深入分析so文件的反混淆
- 注意法律合规性,仅用于授权研究
7. 扩展知识
-
JNI动态注册:
- 通过
JNI_OnLoad和RegisterNatives实现 - 比静态注册更灵活且更安全
- 通过
-
OLLVM混淆:
- 常见的代码保护技术
- 包括控制流平坦化、指令替换、虚假分支等
-
Frida高级用法:
- 内存搜索和修改
- 主动调用与RPC
- 多线程处理
8. 参考资料
- Frida官方文档
- Android JNI编程指南
- OLLVM反混淆技术研究
- 移动安全逆向分析实战