安卓逆向—一款企业IM的加密协议逆向全过程

admin 2026-05-22 02:09:09 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细记录了对某企业IM应用的完整逆向分析过程,涵盖整体架构、国密加密体系(SM2/SM4)、消息协议解析及Frida动态调试技术。关键发现包括硬编码密钥的安全隐患、Java层加密的脆弱性,并提供了避免硬编码、加强代码混淆等安全建议。通过多层Hook策略成功获取明文消息,为移动应用安全防护提供了实战参考。 综合评分: 88 文章分类: 移动安全,逆向分析,加密协议,安全工具,安全建设


cover_image

安卓逆向 — 一款企业IM的加密协议逆向全过程

原创

yushao yushao

逆向有你

2026年5月21日 10:57 河南

在小说阅读器读本章

去阅读

#

本文记录了对某企业通讯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. 1. TCP长连接:用于即时消息收发(融云SDK实现)
  2. 2. HTTPS接口:用于业务API调用(国密加密)

三、加密体系解密

3.1 HTTP通信加密(国密体系)

硬编码的SM2公钥

在 ParamsBuilder.java 中发现硬编码的SM2公钥:

public static final String SM2_PUBLIC_KEY =
    "fdsafsdfsdafsdfasdfasdfasdfasdfasdfasdfadsasdfdas."

加密流程

  1. 1. 生成32字节随机密钥
  2. 2. 使用SM2公钥加密随机密钥
  3. 3. 使用SM4/ECB模式加密消息体
  4. 4. HTTP Header 标记:hdc-encryption-enabled: true

关键代码片段:

// SM4加密实现
Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding",
                                   BouncyCastleProvider.INSTANCE);
cipher.init(Cipher.ENCRYPT_MODE,
           new SecretKeySpec(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密钥:

private static final String SECRET_KEY =
    "64536456345634565434565463";

用于特定字段的SM4解密。

四、消息协议分析

4.1 消息类型体系

所有自定义消息通过 @MessageTag 注解注册:

| 消息类型 | Tag标识 | 用途 | | — | — | — | | TextMessage | RC:TxtMsg | 文本消息 | | ApprovalMessage | RCE:ApprovalMsg | 审批消息 | | SecretChatPromptMessage | RCE:SCPM | 密聊提示 | | GroupCommandMessage | RCE:GrpCmd | 群指令 | | PinMessage | RCE:PinMsg | 公告消息 |

4.2 消息JSON结构

基础消息体包含以下字段:

{
  "mentionedInfo":{
    "type":1,
    "userIdList":[],
    "mentionedContent":"..."
},
"user":{
    "id":"...",
    "name":"...",
    "portrait":"..."
},
"extra":"...",
"isBurnAfterRead":false,
"audit":{
    "auditType":1,
    "project":"..."
}
}

4.3 端到端加密会话

融云SDK支持端到端加密,通过 RCEncryptedSession 维护:

class RCEncryptedSession {
    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
    }

    return this.sendMessage.apply(this, arguments);
};

5.3 多层防御策略

最终采用了多点拦截策略:

  1. 1. API入口层RongIMClient.sendMessage()
  2. 2. 序列化层:各消息类型的 encode() 方法
  3. 3. 持久化层NativeObject.SaveMessage()
  4. 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 加密向量汇总

| 参数 | 值 | 用途 | | — | — | — | | SM2公钥 | 04c945cb7cc… | HTTP密钥交换 | | SM4密钥 | bb218d79ddd… | 特定字段解密 | | AES模式 | ECB/PKCS5 | 本地存储 | | API地址 | https://域名:173/rce-api | 业务接口 |

6.2 Frida Hook技巧

1. 处理方法重载

var overloads = Class.method.overloads;
for&nbsp;(var&nbsp;i =&nbsp;0; i < overloads.length; i++) {
&nbsp; &nbsp; (function(idx) {
&nbsp; &nbsp; &nbsp; &nbsp; overloads[idx].implementation&nbsp;=&nbsp;function() {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// Hook逻辑
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;overloads[idx].apply(this,&nbsp;arguments);
&nbsp; &nbsp; &nbsp; &nbsp; };
&nbsp; &nbsp; })(i);
}

2. 主动调用对象方法

var&nbsp;obj =&nbsp;arguments[0];
var&nbsp;result = obj.someMethod(); &nbsp;// 直接调用Java对象方法

3. 字节数组转字符串

function&nbsp;bytesToString(bytes) {
&nbsp; &nbsp;&nbsp;return&nbsp;Java.use("java.lang.String")
&nbsp; &nbsp; &nbsp; &nbsp; .$new(bytes,&nbsp;"UTF-8")
&nbsp; &nbsp; &nbsp; &nbsp; .toString();
}

6.3 常见坑点

❌ 错误做法:

// 直接Hook native方法容易失败
NativeObject.sendMessageWithOption.implementation&nbsp;= ...

✅ 正确做法:

// 在Java层拦截并主动序列化
var&nbsp;mc = msg.getContent();
var&nbsp;plaintext = mc.encode();

七、安全建议

作为开发者,从这次逆向分析中可以得到以下安全启示:

7.1 不要硬编码密钥

// ❌ 危险
private&nbsp;static&nbsp;final&nbsp;String&nbsp;KEY&nbsp;=&nbsp;"bb218d79ddd211cf...";

// ✅ 安全
// 使用密钥派生函数(KDF)从用户密码/设备特征动态生成

7.2 加强代码混淆

  • • 使用ProGuard/R8进行深度混淆
  • • 对关键类名、方法名进行字符串加密
  • • 使用Native层实现核心加密逻辑

7.3 实施多层防护

  • • Root/越狱检测
  • • Frida检测(检查端口、进程、特征文件)
  • • 完整性校验(签名验证、DEX校验)
  • • 运行时环境检测

八、技术延伸

8.1 如何防御类似逆向

  1. 1. 使用VMP/Ollvm等加固方案
  2. 2. 关键逻辑下沉到Native层
  3. 3. 实施SSL Pinning防止中间人攻击
  4. 4. 动态密钥协商(避免硬编码)
  5. 5. 代码自校验(检测Hook痕迹)

8.2 进一步研究方向

  • • 融云SDK的Native层协议分析
  • • TLS层的流量解密
  • • 端到端加密的密钥交换机制
  • • 消息存储数据库的加密实现

九、总结

通过本次逆向分析,我们完整梳理了一款企业IM应用的:

✅ 整体架构设计 ✅ 国密加密实现 ✅ 消息协议结构 ✅ 动态调试方法

核心收获:

  1. 1. 硬编码密钥是重大安全隐患
  2. 2. Java层的加密在Frida面前形同虚设
  3. 3. 多层Hook策略能有效应对各种防护
  4. 4. 国密算法的正确实施同样重要

免责声明

本文所有内容仅供技术研究和学习交流使用,请勿将相关技术用于非法用途。对他人系统进行未授权的渗透测试属于违法行为,后果自负。


关键词: #逆向工程 #移动安全 #Frida #国密算法 #Android安全 #即时通讯 #加密协议


| | | | — | — | | | |


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:逆向有你 yushao yushao《安卓逆向 — 一款企业IM的加密协议逆向全过程》

评论:0   参与:  0