Shopee App加密算法逆向实战:从抓包到SO层分析

📅 发布时间:2026/7/8 12:34:40 👁️ 浏览次数:
Shopee App加密算法逆向实战:从抓包到SO层分析
1. 抓包定位核心加密参数第一次接触Shopee App逆向时我花了整整三天才搞明白它的加密逻辑。这个电商App的接口防护比想象中复杂得多特别是那组看似随机的加密参数。先说说我是怎么通过抓包找到突破口的。用Charles配置好手机代理后打开Shopee App随便搜索个商品立刻就能在抓包记录里看到几个关键字段。最显眼的是x-sap-ri这个32位哈希值还有4个4字节的短键值对。GET请求会出现3组键值POST则多出一个与表单内容相关的参数。有意思的是这些参数的值每次请求都会变化但变化规律并非完全随机——后来发现它们和URL存在某种映射关系。这里有个坑要注意直接修改这些参数重放请求十次有九次会触发风控。有次我连续测试时突然收到403错误后来发现是参数生成逻辑没摸透。建议大家在测试时控制请求频率最好间隔10秒以上。2. 逆向分析Java层调用链定位到加密参数后我用Frida写了个Hook脚本追踪参数生成过程。关键代码是这样的Java.perform(function(){ let HashMap Java.use(java.util.HashMap); HashMap.put.implementation function(key, value){ if(key x-sap-ri){ console.log(Java.use(android.util.Log) .getStackTraceString( Java.use(java.lang.Throwable).$new() )); } return this.put(key, value); } });打印的调用栈显示参数最终来自com.shopee.shpssdk.SHPSSDK这个类。继续往上追发现核心逻辑在native方法vuwuuwvw属于com.shopee.shpssdk.wvvvuwwu类。这命名风格真是让人哭笑不得活像键盘随机敲出来的。Hook这个native方法时要注意两点第一个参数是URL的字节数组第二个参数GET请求时为nullPOST时是表单内容的字节数组3. 动态加载的SO文件分析通过JNI动态注册信息很快定位到关键so文件libshpssdk.so。但解压APK后我懵了——lib目录下空空如也。后来用Frida hook系统加载函数才发现玄机Interceptor.attach(Module.findExportByName(null, dlopen), { onEnter: function(args){ var path ptr(args[0]).readCString(); if(path.includes(libshpssdk)){ console.log([*] SO加载路径:, path); } } });日志显示so文件被压缩在split_config.arm64_v8a.apk这个分包里。解压后得到so文件用IDA打开直奔0x995DC偏移地址——这就是之前看到的native方法注册位置。4. 算法还原与模拟执行分析so文件发现核心算法有9套变体通过URL哈希值决定具体使用哪3套组合。这个哈希计算也很有意思def get_url_hash(url): tmp 0 for c in url.encode(): tmp (tmp * 0x334B c) 0xFFFFFFFF return tmp 0x7FFFFFFF比如URL/api/v4/pages/bottom_tab_bar的哈希结果是0x1A9EC9B9。这个值对应的密钥在多次请求中保持稳定而其他参数则会变化。为了验证算法我用Unidbg搭建模拟环境。刚开始直接调用so函数就崩溃后来发现需要绕过so内部的异常检测// 关键patch代码 UnidbgPointer pointer UnidbgPointer.pointer(emulator, module.base 0x9A208); pointer.write(new byte[]{0x1F, 0x20, 0x03, 0xD5}); // NOP指令替换异常触发补全环境后成功获取到与App一致的加密结果。整个过程最费时的其实是处理so中的随机数生成逻辑——它们部分来自/dev/urandom设备需要精确模拟才能得到预期结果。