逆向登录协议:如何用Frida快速定位并还原SO层中的DES和MD5算法(以某App为例)
2026/6/15 17:05:34 网站建设 项目流程

移动端加密协议逆向实战:从Frida Hook到算法还原全解析

在移动应用安全分析与数据抓取领域,协议逆向始终是技术攻坚的核心环节。当面对一个经过多重加密的登录请求时,如何快速定位关键算法、识别加密特征并完整还原协议逻辑,成为每位逆向工程师的必修课。本文将聚焦Android平台,以某典型App登录协议为例,系统性地演示从抓包分析到SO层算法还原的全套实战方法。

1. 逆向工程环境搭建与工具链配置

工欲善其事,必先利其器。在开始逆向分析前,需要搭建稳定的调试环境并配置高效的工具组合:

基础环境要求

  • 已root的Android测试设备或模拟器(推荐Android 7.1-9.0版本)
  • Python 3.8+环境用于脚本管理
  • Frida 15.1.17+服务端与客户端
  • IDA Pro 7.5+或Ghidra用于静态分析
  • Jadx-gui或JEB用于Java层逆向

关键工具链配置技巧

# 安装frida-tools pip install frida-tools==12.1.1 # 推送frida-server到设备 adb push frida-server-15.1.17-android-arm64 /data/local/tmp/fs adb shell "chmod 755 /data/local/tmp/fs" adb shell "/data/local/tmp/fs -l 0.0.0.0:27042"

提示:为避免检测,建议修改frida-server文件名并使用非默认端口。部分厂商ROM会对/data/local/tmp目录进行监控,可考虑将服务端部署到应用私有目录。

常见检测与绕过方案对比

检测类型特征表现绕过方案成功率
进程名检测检查frida-server重命名二进制文件95%
端口扫描检测27042端口修改监听端口90%
D-Bus协议探测发送认证消息验证Hook libc的strstr函数80%
内存映射检查扫描maps中的frida特征过滤maps文件内容85%
线程名检测检查gum-js-loop等线程修改线程名或延迟注入70%

2. 协议抓包与关键字段定位

使用Burp Suite或Charles抓取登录请求样本,典型请求示例如下:

{ "username": "testuser", "password": "FfQn1pwmgRY=", "sign": "a3d5e7f9b2c4d6a8f0e1b3c5d7e9f2a4", "captcha": "1234", "deviceId": "abcdef123456" }

通过字段分析可初步判断:

  • password字段的Base64编码特征表明存在二次编码
  • sign字段的32位十六进制字符串符合MD5特征
  • 其他字段多为明文传输

定位关键算法的四步法

  1. 动态追踪:Hook系统加密函数(如OpenSSL的EVP系列)
  2. 调用栈分析:通过JNI接口回溯到Native层
  3. 字符串监控:拦截NewStringUTF等字符串转换函数
  4. 内存扫描:搜索特征常量(如MD5初始化向量)

3. Frida动态Hook实战技巧

3.1 JNI关键函数拦截

通过Hook JNIEnv的NewStringUTF函数,可以捕获所有从Native层返回Java层的字符串:

function hookNewStringUTF() { const libart = Process.findModuleByName("libart.so"); const symbols = libart.enumerateSymbols(); symbols.forEach(sym => { if (sym.name.includes("NewStringUTF") && !sym.name.includes("Check")) { Interceptor.attach(sym.address, { onEnter: function(args) { const str = args[1].readCString(); console.log(`[NewStringUTF] ${str}`); console.log('Call stack:\n' + Thread.backtrace(this.context, Backtracer.FUZZY) .map(DebugSymbol.fromAddress).join('\n')); } }); } }); }

3.2 加密算法特征识别

当定位到可疑函数后,需要快速识别算法类型:

DES算法特征

  • 初始置换表(IP)和逆初始置换表(IP-1)
  • 16轮Feistel网络结构
  • 子密钥生成过程中的左循环移位
  • 典型的8字节块加密

MD5算法特征

  • 四个初始化常量(A=0x67452301等)
  • 64元素正弦函数表
  • 四轮主循环操作(F,G,H,I函数)
  • 结果拼接为128位哈希值

Hook示例(检测MD5):

function detectMD5(module) { const patterns = [ "67452301", "EFCDAB89", "98BADCFE", "10325476" ]; module.enumerateRanges('r-x').forEach(range => { Memory.scan(range.base, range.size, patterns.join(" "), { onMatch: function(address, size) { console.log(`Potential MD5 found at ${address}`); } }); }); }

4. SO层算法逆向深度解析

4.1 DES加密还原实战

通过动态分析定位到加密函数后,静态逆向的关键步骤:

  1. 密钥处理分析

    • 定位密钥扩展函数(通常包含28位左移操作)
    • 提取轮密钥生成逻辑
    • 验证PC-1和PC-2置换表
  2. 加密模式识别

    • CBC模式会存在IV向量
    • ECB模式无IV且块独立
    • 观察初始xor操作判断模式
  3. 数据流追踪

// 典型DES加密伪代码 void des_encrypt(uint8_t *plain, uint8_t *cipher, des_key *key) { uint64_t block = bytes_to_long(plain); block = initial_permutation(block); uint32_t left = block >> 32; uint32_t right = block & 0xFFFFFFFF; for (int i = 0; i < 16; i++) { uint32_t next_left = right; right = left ^ feistel(right, key->subkeys[i]); left = next_left; } block = ((uint64_t)right << 32) | left; block = final_permutation(block); long_to_bytes(block, cipher); }

4.2 复合算法处理流程

现代App常采用多层加密策略,典型处理流程可能包含:

  1. 原始密码经过DES/CBC加密
  2. 输出进行Base64编码
  3. 与其他字段拼接后做MD5哈希
  4. 最终结果作为sign参数

参数提取技巧

  • 使用Frida的Memory.scan搜索硬编码密钥
  • Hook libc的malloc/free分析内存分配
  • 监控系统时间相关函数获取时间戳参数

5. 完整协议逆向案例演示

以某App登录协议为例,完整还原流程:

  1. 密码加密环节

    • DES密钥:"7A24432646294A"
    • IV向量:0xEFCDAB9078563412
    • 模式:CBC with PKCS5Padding
    • 输出编码:Base64
  2. 签名生成环节

import hashlib def generate_sign(params): components = [ params['captcha'], params['captchaId'], params['dateline'], params['deviceId'], params['info'], params['password'], params['username'], "ef2vx#sf*^FlklSD*9sdf(m$&qw%d7po" # salt ] plaintext = ''.join(components) return hashlib.md5(plaintext.encode()).hexdigest()
  1. 完整请求构造
import pyDes import base64 def encrypt_password(pwd): des = pyDes.des( key="7A24432646294A", iv="\xEF\xCD\xAB\x90\x78\x56\x34\x12", mode=pyDes.CBC, padmode=pyDes.PAD_PKCS5 ) encrypted = des.encrypt(pwd) return base64.b64encode(encrypted).decode() def build_request(username, pwd): params = { "username": username, "password": encrypt_password(pwd), "deviceId": "abcdef123456", # 其他字段... } params['sign'] = generate_sign(params) return params

在实际项目中,我们发现大多数加密漏洞源于以下设计缺陷:

  • 使用固定IV导致CBC模式可预测
  • 密钥硬编码在so文件中
  • 签名salt值过于简单
  • 缺乏时效性验证机制

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询