某luo数据包加密逆向分析
字数 1408 2025-08-22 12:23:30
某数据包AES加密逆向分析教学文档
1. 环境准备
1.1 应用信息
- 应用名称/版本:
5ZOI5ZWwdjYuNzQuMQ==(Base64解码后为"某应用v6.74.1") - 测试设备:
cGl4ZWwyIGFuZHJvaWQxMA==(Base64解码后为"pixel2 android10")
1.2 工具准备
- Frida:用于动态Hook和算法自吐
- Jadx:用于静态反编译APK
- IDA Pro:用于分析native层代码
- 抓包工具:如Charles或Fiddler
2. 初步分析
2.1 抓包观察
- 大部分请求包和返回包都经过加密
- 加密数据示例(未提供具体数据,但可推测为Base64编码的密文)
2.2 Frida检测绕过
该应用实现了Frida检测机制,位于libmsaoaidsec.so库中。提供两种绕过方法:
方法一:使用修改版Frida-server
- 推荐使用Floridahook
- 修改特征后的Frida-server可避免被检测
方法二:直接删除检测库
- 定位到应用安装目录
- 删除
libmsaoaidsec.so库文件 - 重新启动应用即可正常使用Frida
3. 加密算法分析
3.1 加密流程
- 应用调用
encrypt函数对数据进行加密 encrypt函数内部调用genEAS函数进行AES加密- 将
genEAS返回的结果进行Base64编码
3.2 genEAS函数分析
- 功能:使用AES算法对输入字符串数据进行加密
- 参数:
src:需要加密的原始字符串- 另一个字符串参数(具体用途需进一步分析)
- 返回:加密后的字节数组
3.3 AES加密细节
- 加密模式:CBC
- 填充方式:PKCS5Padding
- 完整算法标识:
AES/CBC/PKCS5Padding
4. 密钥生成分析
4.1 密钥来源
- 密钥生成函数:
m87066a - 该函数调用native层的
m87064m函数生成密钥
4.2 Native层分析
使用IDA反编译native-lib库:
- 搜索
l_m找到静态注册的函数 - 分析
m87064m函数逻辑:- 参数
i决定密钥类型:- 当
i=1时,返回固定字符串:1234567890123456657aec76a8c97f98f08f - 当
i=0时,返回xmmword_A8AF0指向的内容转换的字符串:0199bec97dfa5e0d
- 当
- 参数
5. 完整加密流程总结
- 应用准备待加密数据
- 调用Java层的
encrypt函数 encrypt函数调用genEAS进行AES加密- 使用
m87066a获取密钥 m87066a通过JNI调用native层的m87064m- 根据传入参数获取不同密钥
- 使用
- 对加密结果进行Base64编码
- 发送加密后的数据
6. 解密实现参考
基于分析结果,可编写解密代码:
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class Decryptor {
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
// 根据i的值选择密钥
public static String getKey(int i) {
return i == 1 ? "1234567890123456657aec76a8c97f98f08f" : "0199bec97dfa5e0d";
}
public static String decrypt(String encryptedData, int keyType) throws Exception {
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
String key = getKey(keyType);
// 假设IV全为0,实际情况可能需要从数据中提取或使用固定值
byte[] iv = new byte[16];
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes);
}
}
7. Hook脚本示例
使用Frida Hook加密函数:
Java.perform(function() {
// Hook genEAS函数
var targetClass = Java.use("com.example.encrypt.EncryptUtils");
targetClass.genEAS.implementation = function(src, key) {
console.log("genEAS called:");
console.log(" src: " + src);
console.log(" key: " + key);
var result = this.genEAS(src, key);
console.log(" result: " + result);
// 打印hex
var hexResult = Array.prototype.map.call(result, function(x) {
return ('00' + (x & 0xFF).toString(16)).slice(-2);
}).join('');
console.log(" hex: " + hexResult);
return result;
};
// Hook native密钥生成函数
var nativeLib = Module.findExportByName("libnative-lib.so", "Java_com_example_encrypt_EncryptUtils_m87064m");
if (nativeLib) {
Interceptor.attach(nativeLib, {
onEnter: function(args) {
console.log("Native key generator called with i=" + args[2]);
},
onLeave: function(retval) {
console.log("Key generated: " + retval.readUtf8String());
}
});
}
});
8. 注意事项
- 实际分析时IV可能不是全0,需要进一步确认
- 密钥可能有动态生成的部分,需要验证所有调用路径
- 不同版本应用加密实现可能有变化
- 本文仅用于技术交流,请勿用于非法用途
9. 扩展分析建议
- 分析其他加密函数,确认是否有不同的加密路径
- 检查网络请求中是否传输了IV或盐值
- 验证不同API接口是否使用相同的加密方式
- 分析签名机制,防止仅解密无法完成完整请求