Hybrid Android协议加解密分析
字数 1367 2025-08-22 12:22:24
Hybrid Android协议加解密分析教学文档
一、前言
本文档基于对Hybrid Android应用中加解密协议的分析,详细记录了从抓包分析到逆向工程的全过程。该应用采用了React Native混合开发模式,加解密逻辑主要在前端JavaScript中实现。
二、抓包分析
1. 请求包结构
POST /app/fsOrder/getAllFsOrderListByUser/ HTTP/1.1
accept: application/json
authorization: Bearer
timestamp: 1567065637961
Content-Type: application/json; charset=utf-8
Content-Length: 256
Host: xxx.com
Connection: close
User-Agent: okhttp/3.6.0
{
"data":"WmPKAOqVK3nmj2751oQM/1fyZJ/QQIMe2itv4LufWyk87WgwkJScqu68J/IQX1Pr",
"key":"LywemIhGqlzqDBOXOPxdY+nifhoq2lBILu2N6WUpJ/4Hrp5W4ihHO1vQuw0joHV6JiiFNzP1+j9hqp1VzmZoboHqRa411BltsuxjEmEMyIJqWK/zDKK+jBreRLH5bXCQOm4gYzHMFY6rob7aC8NhfFhc1r9hfIozhoIK2vbzIUc="
}
2. 响应包结构
HTTP/1.1 200 OK
Date: Thu, 29 Aug 2019 08:00:22 GMT
Content-Type: application/json;charset=UTF-8
Content-Length: 216
Connection: close
{
"data":"nt4BMbi2d7oZ/bFg5mwe2w==",
"key":"o72x8DRL62zUVojRxEsUEP5w2Aa6BXWAZqo8sAFSK9sK47YiGewIIl9LCa1OQ6JgoXn+jVUdENfPSilBBEVwyaJeFFiJ/H24/flwqV/6nVT7YXdvly5dtdXeU6b6iHdpAHtDuaTxy7YJBstNQMo+mB4F6tGvx5D4TK7zpXIMAZk="
}
3. 初步分析
data字段:加密的请求/响应数据key字段:加密data的密钥- 密钥长度明显长于数据,表明使用了不同的加密算法
三、逆向分析
1. Java层分析
-
应用架构识别:
- MainActivity继承自ReactActivity
- assets目录结构表明采用Hybrid开发模式
-
搜索关键词:
- 搜索路由
getAllFsOrderListByUser无结果 - 搜索"key"和"data"结果过多且多为第三方SDK引用
- 搜索路由
-
方法剖析(Method Profiling):
- 定位到可疑函数
com.loc.n.a - 发现疑似加解密操作但无法确定
- 定位到可疑函数
-
动态调试:
- 下断点未触发,表明加解密可能不在Java层
2. JavaScript层分析
-
定位关键文件:
- 发现
jsencrypt.js和utils.js文件 - 全局搜索定位到加解密函数
- 发现
-
加解密函数实现:
// AES加密
function AESencrypt(text, key) {
var result = CryptoJS.AES.encrypt(
CryptoJS.enc.Utf8.parse(text),
CryptoJS.enc.Utf8.parse(key),
{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
}
);
return result.toString();
};
// AES解密
function AESdecrypt(text, key) {
var result = CryptoJS.AES.decrypt(
text,
CryptoJS.enc.Utf8.parse(key),
{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
}
);
return result.toString(CryptoJS.enc.Utf8);
};
// RSA加密
function RSAencrypt(text) {
var rsaEn = new JSEncrypt();
rsaEn.setPrivateKey(rsaPubKey); // 注意:使用公钥作为私钥
var enc = rsaEn.encrypt(text);
return enc;
};
// RSA解密
function RSAdecrypt(text) {
var rsaDn = new JSEncrypt();
rsaDn.setPublicKey(rsaprivateKey2); // 注意:使用私钥作为公钥
var dec = rsaDn.decrypt(text);
return dec;
}
- 加解密流程:
请求加密流程:
- 生成时间戳
timeS = new Date().getTime() - 构造AES密钥:
key = timeS + '123sadsof313r24rsd',截取前16位 - 使用RSA加密AES密钥:
rsaKey = RSAencrypt(key) - 使用AES加密请求体:
value = AESencrypt(body, key) - 构造最终请求体:
{data: value, key: rsaKey}
响应解密流程:
- 使用RSA解密响应中的
key字段获取AES密钥:aaPwd = RSAdecrypt(data.key) - 使用AES解密
data字段:aaData = AESdecrypt(data.data, aaPwd) - 解析解密后的JSON数据
四、关键发现
-
密钥生成:
- 基于时间戳加上固定字符串
- 截取前16位作为AES密钥
-
RSA使用异常:
RSAencrypt中使用公钥作为私钥RSAdecrypt中使用私钥作为公钥- 这种用法非常规,可能是实现错误
-
加密模式:
- AES使用ECB模式和PKCS7填充
- ECB模式安全性较低,建议使用CBC等更安全的模式
五、安全建议
-
密钥管理:
- 避免使用时间戳等可预测值作为密钥
- 考虑使用更安全的密钥派生方式
-
加密算法使用:
- 避免使用ECB模式,改用CBC等更安全模式
- 确保IV(初始化向量)随机且唯一
-
RSA使用:
- 修正公钥/私钥使用方式
- 考虑使用更标准的RSA加密实现
-
代码混淆:
- 对JavaScript代码进行混淆处理
- 避免硬编码密钥在客户端
六、总结
该Hybrid Android应用采用了前端JavaScript实现加解密的方案:
- 使用AES加密业务数据
- 使用RSA加密AES密钥
- 密钥基于时间戳生成
- 加解密逻辑完全暴露在前端代码中
这种实现方式虽然方便,但存在多个安全隐患,建议按照上述安全建议进行改进。