逆向实战:手把手教你用Frida Hook某购物App的AES-ECB签名算法(附完整脚本)
逆向工程实战深度解析移动应用AES-ECB签名机制与Frida动态Hook技术在移动应用安全研究领域签名算法逆向分析一直是核心课题。当我们面对一个黑盒系统时如何通过技术手段还原其加密逻辑本文将以某电商平台App为例完整演示从抓包分析到Native层Hook的全套逆向工程方法论。不同于基础教程我们将重点关注三个技术深水区ECB模式下的AES特征识别、Java与Native层加密的衔接逻辑以及稳定Hook的工程化实现。1. 逆向分析环境搭建与初始侦查逆向工程的首要原则是建立可复现的实验环境。建议使用物理设备Google Pixel 4配合Android 10系统其优势在于完整的ARM指令集支持原生Google服务框架稳定的Root权限管理必备工具链配置# Frida服务端安装 adb push frida-server-15.2.2-android-arm64 /data/local/tmp/ adb shell chmod 755 /data/local/tmp/frida-server-15.2.2-android-arm64 adb shell /data/local/tmp/frida-server-15.2.2-android-arm64 # 抓包环境配置 echo export CHARLES_PROXY192.168.1.100:8888 ~/.bashrc iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination $CHARLES_PROXY在目标App启动阶段我们注意到强制更新检测机制。这里采用网络隔离法绕过启动前关闭设备WiFi和移动数据进入App主界面后立即开启飞行模式通过adb转发特定域名的流量# Python脚本实现流量过滤 import subprocess def allow_traffic(domain): subprocess.run(fiptables -A OUTPUT -p tcp -d {domain} -j ACCEPT, shellTrue, checkTrue) allowed_domains [api.targetapp.com, cdn.static.com] for domain in allowed_domains: allow_traffic(domain)2. 签名参数定位与静态分析技巧通过Charles抓包观察到关键现象当请求参数包含lastId分页字段时服务端返回403错误提示newSign验证失败。这暗示签名算法具有参数敏感性特征。使用Jadx进行静态分析时推荐以下高效定位策略关键代码定位路径com.targetapp.network → RequestUtils.class → generateSign() → AESEncrypt.encode() → NativeMethod: encodeByte()在RequestUtils类中发现典型的三段式签名生成逻辑public class RequestUtils { private static String generateSign(MapString, String params) { String sortedParams sortAndConcat(params); // 参数排序拼接 String aesEncrypted AESEncrypt.encode(secretKey, sortedParams); return MD5Utils.hash(aesEncrypted); // 最终newSign } }AES模式识别技巧ECB模式特征无IV参数、固定密钥密钥处理逻辑中的位翻转操作StringBuilder sb new StringBuilder(); for (char c : originalKey.toCharArray()) { sb.append(c 0 ? 1 : 0); // 二进制密钥混淆 }3. Frida动态Hook技术深度应用3.1 Java层Hook实战完整的Frida脚本应包含错误处理和类型转换Java.perform(() { const AESEncrypt Java.use(com.targetapp.crypto.AESEncrypt); // 重载方法选择技巧 const encodeOverloads AESEncrypt.encode.overloads; encodeOverloads.forEach(overload { overload.implementation function(obj, str) { console.log([Java Hook] Input: ${str}); // 保持原始调用栈 const result this.encode(obj, str); // 结果验证逻辑 if (str.includes(lastId)) { console.log([Critical Path] ${result}); } return result; }; }); });Hook调试技巧使用Frida-trace快速定位方法frida-trace -U -p PID -j *AESEncrypt!encode*内存敏感数据打印时添加过滤if (str.length 50) { console.log(hexdump(str.getBytes())); }3.2 Native层逆向突破通过libJNIEncrypt.so的动态分析我们发现关键函数JNIEXPORT jstring JNICALL Java_com_targetapp_crypto_AESEncrypt_encodeByte( JNIEnv *env, jobject thiz, jbyteArray data, jstring key ) { const char *keyStr (*env)-GetStringUTFChars(env, key, NULL); // 实际调用AES_128_ECB_PKCS5Padding_Encrypt }IDA Pro分析要点在JNI_OnLoad定位动态注册函数跟踪RegisterNatives调用栈分析off_6008处的函数指针表高级Hook脚本示例Interceptor.attach(Module.findExportByName( libJNIEncrypt.so, AES_128_ECB_PKCS5Padding_Encrypt), { onEnter: function(args) { this.plaintext args[0].readUtf8String(); this.key args[1].readUtf8String(); console.log([Native] Key: ${this.key}); }, onLeave: function(retval) { const result retval.readUtf8String(); console.log([Native] Output: ${result}); // 验证加密结果 if (this.plaintext.includes(test)) { send({ stage: native_encrypt, output: result }); } } });4. 工程化逆向解决方案4.1 自动化签名生成系统基于逆向结果构建Python实现from Crypto.Cipher import AES from Crypto.Util.Padding import pad import hashlib class SignGenerator: def __init__(self): self.key self._transform_key(010101...) # 原始密钥 def _transform_key(self, original): return .join([1 if c 0 else 0 for c in original]) def generate(self, params): sorted_str .join(f{k}{v} for k,v in sorted(params.items())) cipher AES.new( self.key.encode(), AES.MODE_ECB ) encrypted cipher.encrypt(pad(sorted_str.encode(), 16)) return hashlib.md5(encrypted).hexdigest()4.2 反检测策略目标App可能采用以下防护措施代码混淆控制流扁平化、字符串加密环境检测Root检查、Frida端口扫描签名校验APK完整性验证对抗方案示例// 绕过Frida检测 Java.perform(() { const File Java.use(java.io.File); File.exists.implementation function(path) { if (path.contains(frida)) return false; return this.exists(path); }; });5. 密码学安全深度探讨虽然ECB模式存在安全隐患但在签名场景下的风险相对可控优势计算效率高、实现简单缺陷相同明文产生相同密文改进方案建议开发者采用HMAC-SHA256替代密钥安全评估矩阵风险维度ECB模式改进方案密钥泄露高危中危重放攻击中危低危数据篡改高危低危性能开销低中等在实际项目中我们发现超过60%的电商App仍在使用AES-ECB进行请求签名。这种方案的优势在于服务端无需维护状态加密结果长度固定兼容老旧硬件设备