安卓逆向签名破解:从Fiddler抓包到JPype调用JAR还原Signature算法

📅 2026/7/8 20:05:42 👁️ 阅读次数 📝 编程学习
安卓逆向签名破解:从Fiddler抓包到JPype调用JAR还原Signature算法

安卓逆向工程实战:从网络请求签名破解到算法还原

在移动应用安全研究和数据爬取领域,逆向工程是一项至关重要的技能。本文将深入探讨如何破解安卓应用中常见的网络请求签名机制,并以一个实际案例(引力播App)为例,展示从抓包定位到算法还原的完整流程。

1. 逆向工程基础与环境准备

逆向工程的核心目标是理解应用程序的内部工作机制,尤其是那些未公开的通信协议和数据加密方式。对于安卓应用来说,这通常涉及以下几个关键步骤:

1.1 工具链配置

进行安卓逆向需要准备以下工具环境:

  • 抓包工具:Fiddler/Charles(HTTP/HTTPS)、Wireshark(底层协议)
  • 反编译工具:Jadx(Java反编译)、Apktool(资源文件解析)
  • 动态调试工具:Frida/Xposed(运行时注入)、IDA Pro(Native层分析)
  • 开发环境:Python 3.x + JPype(Java交互)、Android Studio(代码验证)
# Python环境依赖 pip install frida-tools jpype1 requests

1.2 应用初步分析

拿到目标APK后,首先需要进行静态分析:

  1. 使用Apktool解包查看资源文件
  2. 通过Jadx查看反编译的Java代码
  3. 检查lib目录下的.so文件(可能存在核心算法)

注意:许多应用会使用加固技术(如腾讯乐加固、360加固等),需要先脱壳才能获取真实代码。

2. 网络协议逆向实战

2.1 抓包定位关键参数

使用Fiddler配置手机代理后,观察应用发出的网络请求。重点关注以下特征:

  • 每个请求都变化的参数(如timestamp、nonce)
  • 名称包含"sign"、"sig"、"token"等字段
  • 参数值呈现规律性变化(长度固定、字符集有限)

在引力播案例中,我们发现每个请求都携带一个signature参数,其值类似:

a3f5d8e2c1b7f409e6d825c47a1b2d3f

2.2 静态代码分析

通过Jadx搜索关键词"signature",定位到核心代码段:

public class C2628d implements C0157u { public C0110ac mo26a(C0157u.C0158a aVar) throws IOException { // 获取设备唯一标识 String udid = MyApplication.getInstance().getUDID(); // 获取时间戳 String timestamp = String.valueOf(System.currentTimeMillis() / 1000); // 构造请求参数 C0104aa a2 = a.mo284e() .mo295b("sys", "Android") .mo295b("sysVersion", Build.VERSION.RELEASE) .mo295b("appVersion", MyApplication.getInstance().getAppVersion()) .mo295b("udid", udid) .mo295b("timestamp", timestamp) .mo295b("signature", m12059a(udid, timestamp)) // 关键签名方法 .mo293a(); return aVar.mo104a(a2); } // 签名生成方法 public static String m12059a(String str, String str2) { return C2387a.m11218a( String.format("%s&&%s&&%s", new Object[]{str, str2, "f1190aca-d08e-4041-8666-29931cd89dde"}) ); } }

2.3 算法还原

分析可知签名生成流程为:

  1. 拼接字符串:UDID + "&&" + 时间戳 + "&&" + 固定UUID
  2. 对拼接结果进行某种加密(跟踪m11218a方法发现是MD5)

3. Python实现签名生成

由于算法涉及Java代码,我们可以通过JPype直接调用扣出来的Java方法:

3.1 准备Java代码

将关键算法类保存为MySig.java

import java.security.MessageDigest; public class MySig { public static String generateSignature(String input) { if (input == null) return null; StringBuilder sb = new StringBuilder(); try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(input.getBytes()); for (byte b : md.digest()) { sb.append(Integer.toString((b >>> 4) & 0xF, 16)) .append(Integer.toString(b & 0xF, 16)); } } catch (Exception e) { e.printStackTrace(); } return sb.toString(); } }

编译并打包为JAR:

javac MySig.java jar cvf MySig.jar MySig.class

3.2 Python调用实现

from jpype import * import time import requests # 初始化JVM jvm_path = getDefaultJVMPath() jpype.startJVM(jvm_path, "-ea", "-Djava.class.path=MySig.jar") # 加载Java类 MySig = JClass("MySig") def generate_signature(udid, timestamp): fixed_uuid = "f1190aca-d08e-4041-8666-29931cd89dde" original_str = f"{udid}&&{timestamp}&&{fixed_uuid}" return MySig.generateSignature(original_str) # 示例调用 udid = "IMEI863254012240478-IMSI460072240477434" timestamp = str(int(time.time())) signature = generate_signature(udid, timestamp) print(f"生成的签名: {signature}") # 关闭JVM jpype.shutdownJVM()

4. 进阶技巧与问题排查

在实际逆向过程中,可能会遇到以下挑战及解决方案:

4.1 对抗加固技术

加固类型特征脱壳方法
腾讯乐加固libshellx-*.soFrida内存Dump
360加固libjiagu.soXposed Hook ClassLoader
百度加固libbaiduprotect.so动态调试Dex加载

4.2 常见问题处理

  1. 混淆处理

    • 使用JADX的"重命名"功能恢复有意义的方法名
    • 通过调用关系推断关键方法
  2. Native层加密

    • IDA Pro分析.so文件
    • Frida Hook JNI方法
  3. 证书校验

    • 使用JustTrustMe模块绕过SSL Pinning
    • 修改smali代码移除校验逻辑

提示:对于复杂的加密算法,可以考虑使用Unidbg模拟执行Native代码。

5. 法律与道德考量

在进行任何逆向工程前,必须注意:

  • 仅对拥有合法权限的应用进行分析
  • 不得用于商业牟利或破坏服务
  • 遵守《网络安全法》及相关法律法规

逆向工程的价值在于提升应用安全性,促进技术交流。我曾在一个金融类App的分析中发现,其签名算法存在重放攻击漏洞,通过 responsibly disclosure 帮助厂商修复了该问题。