应用核心信息概览
应用类型: React Native
入口文件: 应用Library/Application Support/HotJs/{packagehash}/{bundlepath}/main.jsbundle
加密算法: RSA
请求体基础字段
以下是发送请求前,原始 JSON 请求体中包含的关键字段及其功能描述:
| 字段 | 含义 | | netWork | 当前网络状态 | | userAgent | uA | | idfa | 应用安装目录 UUID | | jsversion | React Native 桥接器版本 | | toolversion | 当前应用版本 | | osversion | 系统版本 | | model | 设备标识符 | | bundleid | 当前应用包名 | | idfv | 应用储存目录 UUID | | packagehash | 当前更新包的 Hash | | istest | 状态码* | | userId | 用户 ID | | token | 用户鉴权 Token | | username | 用户名 | | ncolor | 未知 | | sappid | 更新包版本* | * 标记为存疑
加密机制 实际负责加密的代码位于应用原生代码 | 参数 | 值 | | 算法 | RSA | | 密钥长度 | 1024 位 | | 填充方式 | PKCS#1 v1.5 Padding | | 明文块大小 | 117 字节 | | 公钥 Base64 | MIGfMA0GCSqGSIb3DQEBAQ……* |
* 完整 Base64 为 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCptf+4baKW65aC8xgq6fM+nnULZY75fuz5GQCm5YpSBbQpYoc+drBEXxMucZxR59EuzuIElgiKRYK2eTd5lcMKbE6ZtWkGd36gu8kPokMXnusv3nHge7wJnPST1VwE1qSkBn9SAzpY8CG1M12uQdN+WNV7N1DuCcazoBEN/D6e3wIDAQAB
原生代码中加密函数位于(IDA Pro 9.0):
| 函数名称 | 区段 | 起始 | 长度 | 局部变量 | | sub_100035F04 | __text | 0000000100035F04 | 0000040C | 000000C0
|
此函数的主要目的是将一个较长的输入字符串(a1, a2)进行分块处理,对每个块执行 RSA 公钥加密,然后将所有加密后的结果数据块拼接起来,返回一个完整的加密数据对象。具体步骤为:
获取 Swift 元数据,并初始化栈变量 v48,将此栈充当最终拼接结果的 Data 容器。 ↓ 通过一个 do-while 循环遍历输入字符串,每次循环,函数都会尝试取出最大 117 个字符(v6 + 117)的子串 然后调用 sub_100035978(v6, v8, a1, a2) 完成字符串的切片操作,获取当前待加密的子字符串。 ↓ 切片后的子字符串通过 StringProtocol.data(using:allowLossyConversion  转换为 Data 对象 调用核心加密函数 static RSAUtils.encryptWithRSAPublicKey(_:pubkeyBase64:keychainTag  ↓ 加密后的结果数据块(v18, v20)被立即通过 Data.append(_  拼接到结果容器 v48 中 ↓ 循环结束后,函数将调用 sub_1000355A4 对最终数据 v48 进行封装,并返回包含所有加密数据的最终对象。
JS 中加密逻辑位于代码 56874-56900 行(格式化后)
buildJson
该函数旨在为网络请求准备 加密后的请求体。它获取通用的客户端参数,将这些参数与业务数据合并,然后对合并后的 JSON 对象通过桥接方法传给原生代码进行加密,
| 变量参数 | 含义 | | t | 业务数据 | | p | 函数接收的所有参数数组 | | n | 控制函数的最终返回值格式 | | u | 传递给底层加密模块的额外参数 |
Case 0 负责从 arguments 数组中提取可选参数 n 和 u,完成后等待调用 this.getCommonParams() 方法,来获取通用字段。由 Case 4 接收到异步调用的结果,并赋值给变量 o 。接着将获取到的公共参数对象 o 增加一个固定的字段 sappid,并赋值为 2891。然后使用扩展操作符将对象进行合并,将合并后值赋给变量 l,最后将 l n u 传给原生代码加密。Case 9 接收到加密操作的结果,并赋值给变量 f,最后根据 n 的值来决定返回值格式。
|