本文记录了对某企业通讯APP的完整逆向分析过程,涉及国密算法、融云SDK、Frida动态调试等技术。仅供技术学习交流,请勿用于非法用途。
一、起因
最近拿到一款企业内部通讯APP,基于融云SDK二次开发,使用了国密加密体系。出于技术研究目的,我决定深入分析其通讯协议和加密实现。
二、整体架构分析
2.1 技术栈识别
通过APK反编译,发现该应用采用了三层架构:
┌─────────────────────────────────────┐│ 业务层(自定义消息协议) │├─────────────────────────────────────┤│ 融云 IM SDK (第三方即时通讯) ││ ├─ Java API 层 ││ └─ Native 层 (libRongIMLib.so) │├─────────────────────────────────────┤│ 加密层(SM2 + SM4 国密算法) │└─────────────────────────────────────┘关键发现:
• 主要代码使用 Java/Kotlin 编写 • 核心通讯基于融云SDK的TCP长连接 • HTTP接口采用国密SM2+SM4混合加密 • 本地存储使用AES加密
2.2 网络通讯方式
该应用使用了两种通讯方式:
1. TCP长连接:用于即时消息收发(融云SDK实现) 2. HTTPS接口:用于业务API调用(国密加密)
三、加密体系解密
3.1 HTTP通信加密(国密体系)
硬编码的SM2公钥
在 ParamsBuilder.java 中发现硬编码的SM2公钥:
publicstaticfinalStringSM2_PUBLIC_KEY="fdsafsdfsdafsdfasdfasdfasdfasdfasdfasdfadsasdfdas."加密流程
1. 生成32字节随机密钥 2. 使用SM2公钥加密随机密钥 3. 使用SM4/ECB模式加密消息体 4. HTTP Header 标记: hdc-encryption-enabled: true
关键代码片段:
// SM4加密实现Ciphercipher= Cipher.getInstance("SM4/ECB/PKCS5Padding", BouncyCastleProvider.INSTANCE);cipher.init(Cipher.ENCRYPT_MODE, newSecretKeySpec(keyBytes, "SM4"));byte[] encrypted = cipher.doFinal(plainText.getBytes());3.2 本地存储加密(AES)
敏感数据(Token、密码等)使用AES加密存储:
• 算法: AES/ECB/PKCS5Padding• 密钥处理:原始key补齐到32字节(不足部分填充"0") • 编码方式:Base64 (NO_WRAP)
3.3 特殊发现:硬编码SM4密钥
在 CacheTask.java 中发现一个硬编码的SM4密钥:
privatestaticfinalStringSECRET_KEY="64536456345634565434565463";用于特定字段的SM4解密。
四、消息协议分析
4.1 消息类型体系
所有自定义消息通过 @MessageTag 注解注册:
4.2 消息JSON结构
基础消息体包含以下字段:
{"mentionedInfo":{"type":1,"userIdList":[],"mentionedContent":"..."},"user":{"id":"...","name":"...","portrait":"..."},"extra":"...","isBurnAfterRead":false,"audit":{"auditType":1,"project":"..."}}4.3 端到端加密会话
融云SDK支持端到端加密,通过 RCEncryptedSession 维护:
classRCEncryptedSession { String encKey; // 加密密钥 String encXA; // 密钥交换参数 String remoteEncId; // 对端会话标识int encStatus; // 状态码}状态码含义:
• -1: NOT_FOUND • 1: REQUEST • 2: RESPONSE • 3: ENCRYPTED • 4: CANCELED
五、动态调试实战
5.1 初次尝试与问题
最初编写的Frida脚本只能Hook到部分信息:
// 只能看到这些[RongIMClient.sendMessage] objectName=null convType=PRIVATE targetId=10007585问题分析:
• msg.getObjectName()返回null• Native方法签名不匹配导致Hook失败 • 消息内容在传递到Native层前就被序列化
5.2 解决方案
关键突破点在于:在Java层直接调用 encode() 方法主动序列化
// 修改后的Hook代码RongIMClientImpl.sendMessage.implementation = function() {var msg = arguments[0];var mc = msg.getContent(); // 获取MessageContent对象if (mc) {var encoded = mc.encode(); // 主动序列化console.log("明文内容:");console.log(bytesToString(encoded)); // 输出明文JSON }returnthis.sendMessage.apply(this, arguments);};5.3 多层防御策略
最终采用了多点拦截策略:
1. API入口层: RongIMClient.sendMessage()2. 序列化层:各消息类型的 encode()方法3. 持久化层: NativeObject.SaveMessage()4. Native入口层: sendMessageWithOption()
这样即使某一层Hook失败,其他层也能捕获到明文。
5.4 最终效果
运行脚本后的输出示例:
══ SEND conv=PRIVATE target=10007585 [10:23:45] ═════ Class: io.rong.message.TextMessage [156B] 明文 JSON:{ "content": "测试消息", "user": { "id": "user123", "name": "张三" }, "extra": ""} [HEX] 7b 22 63 6f 6e 74 65 6e 74 22 3a 22 ...六、关键技术要点总结
6.1 加密向量汇总
6.2 Frida Hook技巧
1. 处理方法重载
var overloads = Class.method.overloads;for (var i = 0; i < overloads.length; i++) { (function(idx) { overloads[idx].implementation = function() {// Hook逻辑return overloads[idx].apply(this, arguments); }; })(i);}2. 主动调用对象方法
var obj = arguments[0];var result = obj.someMethod(); // 直接调用Java对象方法3. 字节数组转字符串
functionbytesToString(bytes) {returnJava.use("java.lang.String") .$new(bytes, "UTF-8") .toString();}6.3 常见坑点
❌ 错误做法:
// 直接Hook native方法容易失败NativeObject.sendMessageWithOption.implementation = ...✅ 正确做法:
// 在Java层拦截并主动序列化var mc = msg.getContent();var plaintext = mc.encode();七、安全建议
作为开发者,从这次逆向分析中可以得到以下安全启示:
7.1 不要硬编码密钥
// ❌ 危险privatestaticfinalStringKEY="bb218d79ddd211cf...";// ✅ 安全// 使用密钥派生函数(KDF)从用户密码/设备特征动态生成7.2 加强代码混淆
• 使用ProGuard/R8进行深度混淆 • 对关键类名、方法名进行字符串加密 • 使用Native层实现核心加密逻辑
7.3 实施多层防护
• Root/越狱检测 • Frida检测(检查端口、进程、特征文件) • 完整性校验(签名验证、DEX校验) • 运行时环境检测
八、技术延伸
8.1 如何防御类似逆向
1. 使用VMP/Ollvm等加固方案 2. 关键逻辑下沉到Native层 3. 实施SSL Pinning防止中间人攻击 4. 动态密钥协商(避免硬编码) 5. 代码自校验(检测Hook痕迹)
8.2 进一步研究方向
• 融云SDK的Native层协议分析 • TLS层的流量解密 • 端到端加密的密钥交换机制 • 消息存储数据库的加密实现
九、总结
通过本次逆向分析,我们完整梳理了一款企业IM应用的:
✅ 整体架构设计✅ 国密加密实现✅ 消息协议结构✅ 动态调试方法
核心收获:
1. 硬编码密钥是重大安全隐患 2. Java层的加密在Frida面前形同虚设 3. 多层Hook策略能有效应对各种防护 4. 国密算法的正确实施同样重要

免责声明
本文所有内容仅供技术研究和学习交流使用,请勿将相关技术用于非法用途。对他人系统进行未授权的渗透测试属于违法行为,后果自负。
关键词: #逆向工程 #移动安全 #Frida #国密算法 #Android安全 #即时通讯 #加密协议
![]() | ![]() |
夜雨聆风
