某大学生常用APP抓包数据加密流程分析
文章分析了一款大学生常用APP的数据加密流程,通过抓包发现请求参数仅包含一个加密后的d字段。作者通过逆向分析定位到登录接口的核心代码,并解决了三个关键问题:获取通用参数集合、密码加密方法及构建最终加密参数d。文章揭示了该APP的加密机制及其潜在安全风险。 2025-10-20 07:44:56 Author: www.freebuf.com(查看原文) 阅读量:1 收藏

freeBuf

主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

某大学生常用APP抓包数据加密流程分析

一、原始抓包

1.1抓包

1.2 抓包结果分析

  • 核心发现:请求参数仅存在1个——参数d,且整个数据包已被加密,无法直接读取原始业务数据(如账号、密码),需通过逆向分析还原加密流程。

二、逆向分析:定位核心代码与参数

2.1 登录接口定位

通过搜索登录相关关键词(如“login/phone”),定位到APP源码中登录功能的核心常量与请求发送方法:

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

// 登录接口URL常量
public static final String f6071I4 = "login/phone";

// 登录请求发送方法:str=账号,str2=原始密码,httpCallBack=回调对象
public static void m10245e(String str, String str2, HttpCallBack httpCallBack) {
    HashMap<String, String> hashMap = C2165k.getHashMap();
    hashMap.put("account", str); // 存入账号参数
    hashMap.put("pwd", C2428c.m6288d(str2)); // 存入经加密处理的密码
    // 发送POST请求:传入接口URL、参数集合、回调函数
    BaseRequest.post(C2165k.getHostUrlV2(InterfaceC2418c.f6071I4), hashMap, httpCallBack.mCallback);
}

2.2 逆向核心目标

需解决3个关键问题,逐步还原加密流程:

  1. 1.

    C2165k.getHashMap():获取的通用参数集合包含哪些内容?

  2. 2.

    C2428c.m6288d(str2):该方法对原始密码(str2)进行了何种加密处理?

  3. 3.

    BaseRequest.post():如何利用传入的hashMap构建最终加密参数d?

三、关键参数解析:通用hashMap集合

3.1 C2165k.getHashMap()方法源码

该方法用于封装APP所有请求的通用参数,源码如下:

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

public static HashMap<String, String> getHashMap() {
    HashMap<String, String> hashMap = new HashMap<>();
    // 未登录状态下,uid和token为空(登录后会添加)
    if (C5772a.m10514g() != null && !TextUtils.isEmpty(C5772a.m10509b()) && !TextUtils.isEmpty(C5772a.m10513f())) {
        hashMap.put(InterfaceC2417b.f5966a, C5772a.m10509b()); // 添加uid(未登录时无值)
        hashMap.put("token", C5772a.m10513f()); // 添加用户凭证token(未登录时无值)
    }
    // 添加极光推送ID(jPushId),推测用于推送服务(如广告、通知)
    String registrationID = JPushInterface.getRegistrationID(App.getContext());
    if (!TextUtils.isEmpty(registrationID)) {
        hashMap.put("jPushId", registrationID);
        InterfaceC2423h.f6552e.mo6554c("jpush_registrationID = " + registrationID, new Object[0]);
    }
    // 添加APP版本号
    hashMap.put("version", C2108a.f5088e);
    return hashMap;
}

3.2 未登录状态下的hashMap值获取(Hook脚本)

因未登录时uidtoken为空,仅需获取jPushIdversion,可通过Hook脚本直接捕获方法返回值:

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

setTimeout(function() {
    Java.perform(function() {
        console.log("开始Hook C2165k.getHashMap()");
        const KClass = Java.use("你的类名"); // 需替换为实际C2165k类名
        KClass.getHashMap.implementation = function() {
            const app = this.getHashMap(); // 执行原方法并获取返回值
            console.log("原始通用hashmap:" + app);
            return app;
        };
    });
}, 8000); // 延迟8秒执行,避免APP未加载完成

原始通用hashmap:{jPushId=100d8559086045b508a, version=4.8.3}

四、密码加密逻辑:C2428c.m6288d()方法解析

4.1 方法源码与核心问题

该方法用于处理原始密码,源码中存在关键错误,需结合逻辑分析修正:

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class C2428c {
    private static final String f6621a = "514345744E41596C4E41496C"; // 24字节3DES密钥(示例)
    private static final String f6622b = "DESede/ECB/PKCS7Padding"; // 3DES加密配置(算法+模式+填充)
    private static C2428c f6623c;

    // 密码加密方法:调用m6299e()实现加密
    public static String m6288d(String str) {
        try {
            return m6291i().m6299e(str, f6621a);
        } catch (Exception e2) {
            e2.printStackTrace();
            return str; // 异常时返回原始密码(安全性缺陷)
        }
    }

    // 单例模式获取C2428c实例,添加BouncyCastle加密提供者
    public static C2428c m6291i() {
        if (f6623c == null) {
            synchronized (C2428c.class) {
                if (f6623c == null) {
                    Security.addProvider(new BouncyCastleProvider());
                    f6623c = new C2428c();
                }
            }
        }
        return f6623c;
    }

    // 密钥创建方法(核心错误点)
    private Key m6292j(String str) {
        // 错误:SecretKeySpec需传入纯算法名("DESede"),而非含模式/填充的完整字符串
        return new SecretKeySpec(str.getBytes(), f6622b); 
    }

    private Key m6293k(byte[] bArr) {
        // 同上述错误:算法参数传入错误
        return new SecretKeySpec(bArr, f6622b); 
    }

    // 加密核心逻辑:3DES加密+十六进制转换
    public String m6299e(String str, String str2) throws Exception {
        Cipher.getInstance(f6622b).init(1, m6292j(str2));
        return m6296n(m6300f(str.getBytes(), str2.getBytes()));
    }

    // 字节数组转十六进制字符串
    private String m6296n(byte[] bArr) {
        return new String(m6295m(bArr));
    }

    private byte[] m6295m(byte[] bArr) {
        byte[] bArr2 = new byte[bArr.length * 2];
        for (int i2 = 0; i2 < bArr.length; i2++) {
            byte b = (byte) ((bArr[i2] >> 4) & 15);
            byte b2 = (byte) (bArr[i2] & 15);
            int i3 = i2 * 2;
            bArr2[i3] = (

已在FreeBuf发表 0 篇文章

本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)


文章来源: https://www.freebuf.com/articles/mobile/453346.html
如有侵权请联系:admin#unsafe.sh