如何从Unity开发的Android应用中提取RSA私钥?
提取Unity Android应用中的RSA私钥:Frida与Ghidra的实践方案
可行性说明
只要RSA私钥是存储在应用本地(内存或文件系统),而非硬件加密模块(如TEE/Android Keystore且不可导出),使用Frida、Ghidra这类逆向工具完全可以实现提取。Unity应用分两种编译类型:基于Mono运行时的C#字节码,或IL2CPP编译后的原生so文件,两者都有对应的逆向路径。
Frida动态提取方案
Frida擅长从运行时内存中抓取私钥,针对不同编译类型的Unity应用,思路不同:
- Mono编译应用:Unity默认用Mono托管C#代码,可hook
.NET加密相关API,比如System.Security.Cryptography.RSA的FromXmlString、ImportParameters或Decrypt方法,在调用时直接dump内存中的私钥内容。
简化版Frida脚本示例:const RSA = Mono.ClassFactory.load("System.Security.Cryptography.RSA"); Interceptor.attach(RSA.prototype.FromXmlString.implementation, { onEnter: function(args) { const privateKeyXml = args[1].readUtf8String(); console.log("Loaded RSA Private Key:\n", privateKeyXml); } }); - IL2CPP编译应用:这类应用会将C#代码编译为原生so文件(如
libil2cpp.so),需定位加密逻辑对应的原生函数——比如调用OpenSSL的PEM_read_RSAPrivateKey或自定义的私钥加载函数,hook这些函数来捕获私钥数据。
Ghidra静态逆向分析
Ghidra适合静态定位私钥存储位置或解密逻辑:
- Mono应用:先从APK中提取
Managed目录下的DLL文件(如Assembly-CSharp.dll),用Ghidra的Mono插件或配合dnSpy反编译,查找硬编码的私钥、读取私钥的文件路径(如assets目录下的加密文件),或SharedPreferences中的存储键值。 - IL2CPP应用:先提取
libil2cpp.so和global-metadata.dat,用Il2CppDumper导出伪代码后导入Ghidra,分析私钥加载流程——比如追踪从文件读取数据、解密私钥的函数逻辑,定位私钥的存储形式或解密密钥。
针对你MITM失败的补充建议
你之前尝试MITM+禁用SSL固定未成功,大概率是以下原因:
- 应用使用Unity自带的
UnityWebRequest网络栈,常规Android SSL固定绕过脚本(如通用反钉钩脚本)不生效,需针对性hook Unity的证书验证逻辑,比如UnityWebRequest.CertificateHandler的验证方法。 - 私钥并非用于SSL握手,而是用于本地数据加密、签名验证等场景,这种情况下MITM完全碰不到私钥,必须直接从应用内存或文件系统中提取。
关键注意事项
- 若私钥存储在Android Keystore且设置了不可导出属性(
KeyProperties.EXPORTABLE为false),常规逆向工具无法直接提取,只能尝试绕过Keystore限制(难度极高,且受系统版本影响)。 - 部分应用会对私钥进行二次加密存储(比如用AES加密后存在assets或SharedPreferences),此时需先找到解密密钥和逻辑,才能还原出原始RSA私钥。
内容的提问来源于stack exchange,提问作者Xinon
相关产品推荐
相关产品推荐

