某社交App协议分析之X-SIGN
字数 1328 2025-08-06 12:21:05

某社交App协议分析之X-SIGN生成全流程教学文档


一、环境准备与抓包配置

  1. 工具准备

    • Charles:用于HTTPS抓包(需安装根证书)。
    • Android设备:需Root或模拟器(如Genymotion)。
    • 证书配置
      • 导出Charles根证书(.cer格式)。
      • 计算证书哈希:openssl x509 -inform DER -subject_hash_old -in 证书名.cer
      • 重命名证书为哈希值.0,复制到Android系统证书目录:/system/etc/security/cacerts/
      • 在手机设置中信任Charles证书(系统凭据)。
  2. 代理设置

    • Charles开启SSL Proxying,设置*:*允许所有域名。
    • 手机配置代理:IP为PC本地IP,端口默认8888。

二、静态分析APK

  1. 反编译工具

    • 使用GDAEJADX反编译APK,搜索关键字符串X-SIGN
  2. 关键代码定位

    • 找到c()方法,其内部调用链:
      tj.put("X-SIGN", this.a(uoe, tj, this.d));
      
    • 参数分析:
      • uoe:通过Coded.getInstance().aesEncode()生成的字节数组。
      • tj:请求头Map(含User-AgentX-KV等)。
      • this.d:固定字符串(如pF5RkqjVJ4nPiR7i)。
  3. 核心方法a()分析

    • 调用Coded.getInstance().sign(uobyteArray, bytes)
      • uobyteArraya()方法的arg0(含请求数据)。
      • bytesa()方法的arg2(盐值)。

三、动态Hook关键函数

  1. Frida脚本编写

    • Hook目标:aesEncodeasign方法。
    • 难点处理
      • 字节数组输出:转换为Hex或Base64字符串。
      • Map遍历:通过keySet()迭代打印键值对。
    function bytes2hex(arrBytes) {
        return Array.from(arrBytes, byte => byte.toString(16).padStart(2, '0')).join('');
    }
    
    Java.perform(() => {
        // Hook aesEncode
        let Coded = Java.use('com.xxxxxx.util.jni.Coded');
        Coded.aesEncode.overload('[B', 'int', '[B', 'int', '[B').implementation = function(...args) {
            console.log('aesEncode Input:', bytes2hex(args[0]));
            let result = this.aesEncode(...args);
            console.log('aesEncode Output:', result);
            return result;
        };
    
        // Hook sign
        Coded.sign.overload('[B', '[B').implementation = function(arg0, arg1) {
            console.log('sign Input:', bytes2hex(arg0), bytes2hex(arg1));
            let result = this.sign(arg0, arg1);
            console.log('sign Output:', result);
            return result;
        };
    });
    
  2. 输出分析

    • aesEncode:生成加密后的字节数组(长度1543)。
    • sign:输入为User-Agent拼接请求数据+盐值前8字节,输出Base64编码的X-SIGN。

四、SO层逆向分析

  1. 模块定位

    • 静态代码块加载libcoded.so(通过System.loadLibrary)。
    • IDA分析
      • 函数sdbyecbu37x:JNI接口,调用sign函数。
      • sign函数逻辑:
        ptr = malloc(data_len + 8);          // 分配空间
        memcpy(ptr, data, data_len);         // 复制数据
        *(uint32_t*)(ptr + data_len) = salt; // 拼接盐值前8字节
        j_sha1(ptr, output, data_len + 8);   // SHA1哈希
        
  2. 加密流程

    • 输入User-Agent + 请求数据 + 盐值前8字节
    • 算法:SHA1哈希 → Base64编码 → 生成X-SIGN。

五、算法复现(Python示例)

import hashlib
import base64

def generate_xsign(user_agent: bytes, request_data: bytes, salt: bytes) -> str:
    # 拼接数据: User-Agent + 请求数据 + 盐值前8字节
    combined = user_agent + request_data + salt[:8]
    # SHA1哈希
    sha1 = hashlib.sha1(combined).digest()
    # Base64编码
    return base64.b64encode(sha1).decode()

# 示例数据
user_agent = b"MomoChat/8.31.6 Android/7075 (IN2020; Android 7.1.2; Gapps 1; zh_CN; 14; OnePlus)"
request_data = b"...抓包中的请求体..."
salt = b"pF5RkqjVJ4nPiR7i"

xsign = generate_xsign(user_agent, request_data, salt)
print("X-SIGN:", xsign)  # 输出: gB0dO33VfWkQyOWE7++tv/EBrtc=

六、总结与防护建议

  1. 关键点

    • X-SIGN由User-Agent + 请求数据 + 固定盐值经SHA1和Base64生成。
    • 盐值硬编码在SO层,需逆向提取(如pF5RkqjVJ4nPiR7i)。
  2. 防护建议

    • App端:动态盐值、代码混淆、Native层校验。
    • 服务端:限制高频请求、多因素验证。
  3. 延伸风险

    • 协议逆向可导致批量注册/登录攻击,建议加强风控策略。

附录

(完)

某社交App协议分析之X-SIGN生成全流程教学文档 一、环境准备与抓包配置 工具准备 Charles :用于HTTPS抓包(需安装根证书)。 Android设备 :需Root或模拟器(如Genymotion)。 证书配置 : 导出Charles根证书( .cer 格式)。 计算证书哈希: openssl x509 -inform DER -subject_hash_old -in 证书名.cer 。 重命名证书为 哈希值.0 ,复制到Android系统证书目录: /system/etc/security/cacerts/ 。 在手机设置中信任Charles证书(系统凭据)。 代理设置 Charles开启 SSL Proxying ,设置 *:* 允许所有域名。 手机配置代理:IP为PC本地IP,端口默认8888。 二、静态分析APK 反编译工具 使用 GDAE 或 JADX 反编译APK,搜索关键字符串 X-SIGN 。 关键代码定位 找到 c() 方法,其内部调用链: 参数分析: uoe :通过 Coded.getInstance().aesEncode() 生成的字节数组。 tj :请求头Map(含 User-Agent 、 X-KV 等)。 this.d :固定字符串(如 pF5RkqjVJ4nPiR7i )。 核心方法 a() 分析 调用 Coded.getInstance().sign(uobyteArray, bytes) : uobyteArray : a() 方法的 arg0 (含请求数据)。 bytes : a() 方法的 arg2 (盐值)。 三、动态Hook关键函数 Frida脚本编写 Hook目标: aesEncode 、 a 、 sign 方法。 难点处理 : 字节数组输出 :转换为Hex或Base64字符串。 Map遍历 :通过 keySet() 迭代打印键值对。 输出分析 aesEncode :生成加密后的字节数组(长度1543)。 sign :输入为 User-Agent 拼接请求数据+盐值前8字节,输出Base64编码的X-SIGN。 四、SO层逆向分析 模块定位 静态代码块加载 libcoded.so (通过 System.loadLibrary )。 IDA分析 : 函数 sdbyecbu37x :JNI接口,调用 sign 函数。 sign 函数逻辑: 加密流程 输入 : User-Agent + 请求数据 + 盐值前8字节 。 算法 :SHA1哈希 → Base64编码 → 生成X-SIGN。 五、算法复现(Python示例) 六、总结与防护建议 关键点 X-SIGN由 User-Agent + 请求数据 + 固定盐值 经SHA1和Base64生成。 盐值硬编码在SO层,需逆向提取(如 pF5RkqjVJ4nPiR7i )。 防护建议 App端 :动态盐值、代码混淆、Native层校验。 服务端 :限制高频请求、多因素验证。 延伸风险 协议逆向可导致批量注册/登录攻击,建议加强风控策略。 附录 Charles证书配置指南 Frida官方文档 IDA逆向技巧 (完)