移动端加密协议逆向实战从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-tools12.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特征其他字段多为明文传输定位关键算法的四步法动态追踪Hook系统加密函数如OpenSSL的EVP系列调用栈分析通过JNI接口回溯到Native层字符串监控拦截NewStringUTF等字符串转换函数内存扫描搜索特征常量如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-116轮Feistel网络结构子密钥生成过程中的左循环移位典型的8字节块加密MD5算法特征四个初始化常量A0x67452301等64元素正弦函数表四轮主循环操作F,G,H,I函数结果拼接为128位哈希值Hook示例检测MD5function 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加密还原实战通过动态分析定位到加密函数后静态逆向的关键步骤密钥处理分析定位密钥扩展函数通常包含28位左移操作提取轮密钥生成逻辑验证PC-1和PC-2置换表加密模式识别CBC模式会存在IV向量ECB模式无IV且块独立观察初始xor操作判断模式数据流追踪// 典型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常采用多层加密策略典型处理流程可能包含原始密码经过DES/CBC加密输出进行Base64编码与其他字段拼接后做MD5哈希最终结果作为sign参数参数提取技巧使用Frida的Memory.scan搜索硬编码密钥Hook libc的malloc/free分析内存分配监控系统时间相关函数获取时间戳参数5. 完整协议逆向案例演示以某App登录协议为例完整还原流程密码加密环节DES密钥7A24432646294AIV向量0xEFCDAB9078563412模式CBC with PKCS5Padding输出编码Base64签名生成环节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()完整请求构造import pyDes import base64 def encrypt_password(pwd): des pyDes.des( key7A24432646294A, iv\xEF\xCD\xAB\x90\x78\x56\x34\x12, modepyDes.CBC, padmodepyDes.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值过于简单缺乏时效性验证机制
逆向登录协议:如何用Frida快速定位并还原SO层中的DES和MD5算法(以某App为例)
移动端加密协议逆向实战从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-tools12.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特征其他字段多为明文传输定位关键算法的四步法动态追踪Hook系统加密函数如OpenSSL的EVP系列调用栈分析通过JNI接口回溯到Native层字符串监控拦截NewStringUTF等字符串转换函数内存扫描搜索特征常量如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-116轮Feistel网络结构子密钥生成过程中的左循环移位典型的8字节块加密MD5算法特征四个初始化常量A0x67452301等64元素正弦函数表四轮主循环操作F,G,H,I函数结果拼接为128位哈希值Hook示例检测MD5function 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加密还原实战通过动态分析定位到加密函数后静态逆向的关键步骤密钥处理分析定位密钥扩展函数通常包含28位左移操作提取轮密钥生成逻辑验证PC-1和PC-2置换表加密模式识别CBC模式会存在IV向量ECB模式无IV且块独立观察初始xor操作判断模式数据流追踪// 典型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常采用多层加密策略典型处理流程可能包含原始密码经过DES/CBC加密输出进行Base64编码与其他字段拼接后做MD5哈希最终结果作为sign参数参数提取技巧使用Frida的Memory.scan搜索硬编码密钥Hook libc的malloc/free分析内存分配监控系统时间相关函数获取时间戳参数5. 完整协议逆向案例演示以某App登录协议为例完整还原流程密码加密环节DES密钥7A24432646294AIV向量0xEFCDAB9078563412模式CBC with PKCS5Padding输出编码Base64签名生成环节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()完整请求构造import pyDes import base64 def encrypt_password(pwd): des pyDes.des( key7A24432646294A, iv\xEF\xCD\xAB\x90\x78\x56\x34\x12, modepyDes.CBC, padmodepyDes.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值过于简单缺乏时效性验证机制