当前位置 博文首页 > 卤蛋实验室:🙈 如何隐藏你的热更新 bundle 文件?

    卤蛋实验室:🙈 如何隐藏你的热更新 bundle 文件?

    作者:卤蛋实验室 时间:2021-01-30 15:46

    其实这个问题蛮复杂的,因为它不单纯是一个技术问题,还涉及到各种复杂的商业利益,在诸多的限制条件下,你很难去找到一个最优解。而且这个问题也比较敏感,我也只能大致讲一下我的思路,具体的代码实现本文也不会提供。
    ??

    如果你喜欢我写的文章,可以把我的公众号设为星标 ??,这样每次有更新就可以及时推送给你啦。

    前段时间我们公司的一个大佬从一些渠道得知了一些小道消息,某国民级 APP 因为 Apple App Store 审核人员检测出 React Native 热更新的内容,被拒审了三个月。我们的热更新平台和出事的 APP 原理相似,所以也存在着拒审危险。那么我们就要想一些办法,隐藏热更新 bundle,不被审核人员发现。

    其实这个问题蛮复杂的,因为它不单纯是一个技术问题,还涉及到各种复杂的商业利益,在诸多的限制条件下,你很难去找到一个最优解。而且这个问题也比较敏感,我也只能大致讲一下我的思路,具体的代码实现本文也不会提供。

    ??

    郑重声明:若有人按本文思路隐藏热更新数据导致应用拒审或下架,本人概不负责

    一、商业利益

    Apple 公司对 iPhone 生态有着非常严格的管控:App 上架必须走 App Store,动态链接库要参与签名,带 JIT 功能的虚拟机不能用......

    对于热更新技术,Apple 在 2017 年封杀过一次 JSPatch 这个热更新框架,导致很多的 APP 被拒审,根据 Apple 官方给出的理由,主要有三点:

    • 热更新代码没有做好加密和校验,有可能被第三方破解劫持
    • JSPatch 权限过高,可能会调用私有 API,改变原有的 APP 功能
    • 对于 Apple 官方来说,JSPatch 自由度太大,会绕过 App Store 这个 iOS 上的唯一流量分发平台更新应用,影响商业利益

    俗话说得好,断人财路如杀人父母,这种涉及商业利益的事情无论放在谁都头上都忍不了,而且很多应用又不是微信,有庞大的用户基数可以和 Apple 官方谈判(微信小程序生态就是谈出来的,但是小程序支付权限就没谈妥),所以说这个问题还是很复杂的。


    其实对于 Apple 官方来说,对与动态化热更新的态度向来是不赞成也不反对,和 JSPatch 比起来,React Native 和游戏热更新这两种应用场景还是被允许的,主要还是体现在三点:

    • 网游这种重运营的场景还是需要热更新维持活动热度的,每周都有新活动,让用户主动去 App Store 下载更新包很不合理,App 活动运营同理
    • React Native/Lua 等热更新技术是在一个容器里进行动态化的,不像 JSPatch 有那么大的修改权限
    • 苹果官方在商业利益上和游戏厂商/互联网巨头达到一些微妙的平衡

    说实话苹果审核一直很迷,拒审有时候和打太极一样,给出的规范各路解读都不一样,不过为了保险起见,我们还是要研究一下相关的平台规范。

    二、解读规范

    2015 年苹果发过一篇协议——《Apple Developer Program License Agreement》,文中第 3.3.2 节有一段关于热更新的内容:

    ??

    Except as set forth in the next paragraph, an Application may not download or install executable code. Interpreted code may only be used in an Application if all scripts, code and interpreters are packaged in the Application and not downloaded. The only exceptions to the foregoing are scripts and code downloaded and run by Apple's built-in WebKit framework or JavascriptCore, provided that such scripts and code do not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store.

    这一段话大概就是说除了 Webkit 和 JavascriptCore 可以动态执行下发的脚本和文件,其它所有脚本/代码/解释器都必须打包在 APP 内部。这句话其实就给 React Native 留了一个口子:React Native 就是用 JavascriptCore 执行 JS 脚本文件的,那么动态下发也是合理的。


    ??

    Interpreted code may be downloaded to an Application but only so long as such code: (a) does not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store, (b) does not create a store or storefront for other code or applications, and (c) does not bypass signing, sandbox, or other security features of the OS.

    这一段话大概就是说,我允许你热更新,但是必须遵循我这三条规定:

    • 不能大的修改 APP 功能,导致应用实际功能和 APP Store 的宣传不符(这个地方就很打太极,评判标准全靠审核人员心情)
    • 不能动态创建应用商店(应该是不能绕过 IAP 支付的意思,要不然怎么收苹果税)
    • 不能绕过签名/沙箱/OS 的安全功能(这个可以理解,维护系统和生态安全)

    这样解读下来,貌似只要按照规范当个良民就可以解决问题了。但是说实话,动态化规范更多的是君子协议,如果双方都讲武德,那大家其乐融融都挺好;万一哪个人跳出来要坏规矩,说实话大家都很难堪。在未来,热更新技术肯定还是要以微妙的平衡状态存在下去。

    三、技术实现

    每次设计一些工程方案时,我个人的习惯都是先从理论上找答案。就拿隐藏热更新 bundle 这个例子来说,我们主要是想在信息传输这里找到突破口,实际上香农老爷子 1949 年就提出了一个「香农一韦弗通信模型」。这个模型里把通信分为五个部分:信息源发射器信道接收器信息接受者噪音

    香农一韦弗通信模型
    香农一韦弗通信模型

    那么结合这个通信模型,我们隐藏/加密通讯信息的答案就呼之欲出了:

    • 对信源加密:在信息的收发终端发送消息时加密,接受消息时解密
    • 对信道加密:信息在信道传输时,经过信道时进行加密

    那么我们下面就对这两个大方向进行扩展和探讨。


    1.对消息本身加密/混淆

    1.1 隐写术——当代特洛伊木马

    隐写术是一个非常非常古老的技术,这个技术的关键就是把想要传递的数据隐藏/伪装一下,不让第三方看出来真实想要传递的数据。

    隐写术的例子非常多,比如说特洛伊木马,你从外面看是个木马,但运到城里,士兵就跑出来了;我们看的一些影视剧里,也有类似原理的桥段:主角收到一份无字信纸,在蜡烛上一烤,文字就显现出来。如今的数字时代肯定不会用无字信纸秘密传递消息,我们肯定有些更加赛博的方法,比如说图种技术——把消息隐写到图片文件里

    如果大家玩过一段时间贴吧,对图种技术肯定不会陌生,有些大神会发个贴,把种子文件隐藏在图片里,大家把图片下载下来,把 .jpg 的后缀改为 .zip or .rar,然后解压文件就能得到隐藏的种子文件,然后在贴吧留下「楼主好人」的美誉。

    那么图种技术的原理是啥?其实很简单,它只是单纯的把一个 jpg 文件和一个 rar 文件合并在一起,但是图片查看器会忽略附加的 rar 文件数据,这样在感官上这是一张图片,但是从二进制的角度看这个图片文件里隐藏了一些数据。

    下面我们看看图种文件的原理。


    首先我用图片编辑器生成一个 2x2 4 个像素大小的图片——RGBY.jpg。颜色我参考 Google logo 配了一下:

    RGBY-image
    RGBY-image

    然后我们用二进制查看工具(我这里用的是