Flutter开发中如何防止经解包篡改重打包的应用运行?
Flutter应用防篡改校验实现说明
关于运行时校验MD5的可行性
- 从技术实现角度,完全可以在运行时读取本地安装包、核心二进制文件的MD5值做比对,但孤立的本地MD5校验不具备实际防篡改价值。
- 核心问题在于:MD5的校验逻辑、内置的合法基准值本身就和被校验的内容在同一个安装包内。攻击者完成解包、篡改、重打包后,可以同步删掉校验代码、把内置的基准MD5值替换为篡改后文件的实际MD5,让整个校验流程完全失效;甚至可以直接用hook工具篡改校验函数的返回结果,完全绕开真实计算过程。
- 另外MD5本身的抗碰撞能力已经不适合做高安全等级的完整性校验,优先选择SHA256这类更安全的哈希算法。
可落地的防篡改实现路径
1. 核心防线:原生层签名校验(不要放在Dart层实现)
Flutter应用的运行依赖原生壳的启动流程,最有效的第一道防线是把校验逻辑放在原生代码侧,而非易被篡改的Dart业务层:
- Android端:在应用启动最早期的Application生命周期阶段,通过系统API读取当前安装包的签名信息,计算签名的哈希值,和经过混淆加密存储的官方签名哈希做比对,一旦发现签名不一致,直接终止应用进程。绝对不要把签名校验逻辑写在Dart层,Dart层对应的编译产物
libapp.so是攻击者篡改时优先替换的目标,逻辑很容易被整体移除。 - iOS端:在启动阶段读取应用内嵌的
.mobileprovision描述文件信息,校验签名所属的Team ID、应用ID是否和官方发布版本一致,同时校验系统返回的代码签名有效性,阻断被重签名的篡改包启动。
2. 增强防护:二进制完整性校验
在签名校验的基础上,叠加核心二进制文件的完整性校验,提升攻击成本:
- 正式发布版本打包完成后,提前计算核心可执行文件(Android端的
libapp.so、libflutter.so;iOS端的主可执行Mach-O文件)的SHA256哈希值,不要以明文形式把基准哈希值存在代码里,要把哈希值做拆分、异或加密后散落在原生代码的不同位置,避免攻击者一次性定位所有基准值完成替换。 - 校验逻辑本身要做代码混淆、加固处理,增加攻击者逆向修改校验逻辑的难度。
3. 兜底机制:服务端联动校验
所有本地校验都存在被高成本逆向绕过的可能,涉及账号登录、数据上传、支付类的敏感操作时,不要仅依赖本地校验的结果:
- 客户端在发起敏感请求时,把当前获取到的应用签名哈希、核心二进制哈希值加密后随请求一起发送到服务端。
- 服务端侧校验上传的哈希值是否和官方发布版本匹配,不匹配的请求直接拒绝响应,从根源上阻断篡改包的核心功能。
内容的提问来源于stack exchange,提问作者Jacky
相关产品推荐
相关产品推荐

