当前位置: 首页 > news >正文

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方法时要注意两点:

  1. 第一个参数是URL的字节数组
  2. 第二个参数GET请求时为null,POST时是表单内容的字节数组

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设备,需要精确模拟才能得到预期结果。

http://www.jsqmd.com/news/568464/

相关文章:

  • 从概率到似然:用Python手把手实现LLR算法(附完整代码)
  • Stable-Diffusion-v1-5-archive企业级应用:基于Java的SpringBoot后端集成方案
  • 陶瓷气体放电管(GDT)的主要参数
  • Obsidian PDF++:提升PDF区域标注效率的全攻略
  • HTinySPI:ATtiny48超轻量SPI主机库实现与应用
  • 15个实战403绕过技巧:从协议层到认证体系的突破
  • 从RoPE到Yarn:手把手解析LLM上下文扩展的5种位置编码技术
  • 深度解析TouchGAL:一站式Galgame文化社区的技术架构与用户体验
  • Python无GIL并发不是银弹!3类必踩的部署陷阱(附Prometheus监控告警规则+火焰图定位模板)
  • 软考软件评测师备考攻略:2024年机考新规下,如何高效拿下那45分及格线?
  • NES手柄嵌入式驱动原理与Arduino实现
  • 智能编程伙伴:如何利用快马AI模型辅助开发与优化无名小站
  • Cursor Pro免费激活终极指南:3步突破试用限制,永久享受AI编程助手
  • RWKV7-1.5B-g1a保姆级教程:从账号开通、实例选择到服务验证的全路径
  • 【源码深度】BroadcastReceiver 广播机制全解析|有序/本地广播、ANR 防范、静态动态注册与版本限制|Android全栈体系150讲-07
  • 记录模式重构必读,Java 21+高效编码规范与7类反模式避坑清单(含JIT内联失效预警)
  • 避坑指南:在Ubuntu 20.04上从源码编译SimpleElastix(解决sitk导入冲突)
  • 3步让旧Mac重生:OpenCore Legacy Patcher完整升级指南
  • 3步掌控Windows右键菜单:ContextMenuManager效率优化完全指南
  • VLC与Fiddler实战:网络流视频保存与下载全攻略
  • NoSleep防休眠工具:让系统时刻在线的轻量级解决方案
  • DamoFD与数据结构优化:提升人脸检测效率50%的实战技巧
  • 别再只盯着灵敏度了!深入解读电阻应变片的‘隐形’特性:疲劳寿命、蠕变与动态响应到底多重要?
  • KIHU快狐|32寸户外落地广告机国产麒麟十四核强光清晰广场宣传屏
  • 【科技实话】“免费_Wi-Fi”_的陷阱:黑客如何_1_分钟
  • 大模型产品经理学习路线(2026最新)神仙级大模型产品经理教程分享,不用感谢,请叫我活雷锋_大模型产品经理 学习路线
  • 避坑指南:nRF52840蓝牙DFU配置中那些官方文档没细说的‘坑’(基于SDK 17.1.0)
  • 基于VIC-3D的大尺度DIC数字图像相关技术的桥梁修复解决方案
  • 别再手动搬砖了!用n8n+硅基流动API,5分钟搞定你的第一个AI自动化工作流
  • 嵌入式系统中不定长协议帧的高效解析方法