3

我对应用程序开发特别陌生,最近了解了 apk 的整个签名过程,为什么它是强制性的,以及防止未经授权和篡改应用程序的重要性。Signature 的著名检查之一是使用 PackageManager 类进行签名验证。是否有任何其他方法可以检查 apk 本身中的 META-INF 目录是否存在篡改或其他滥用活动,以验证应用程序未被篡改且其原始签名完好无损?

4

2 回答 2

0

最佳实践是无法修补的服务器端篡改检测。

方法如下:

使用安卓安全网。这就是 Android Pay 自我验证的方式。

基本流程是:

  • 您的服务器会生成一个随机数并将其发送到客户端应用程序。
  • 该应用通过 Google Play 服务发送带有 nonce 的验证请求。
  • SafetyNet 验证本地设备未修改并通过 CTS。
  • Google 签名的响应(“证明”)会返回到您的应用,其中包含通过/失败结果以及有关您应用的 APK(哈希和签名证书)的信息。
  • 您的应用程序将证明发送到您的服务器。
  • 您的服务器验证 nonce 和 APK 签名,然后将证明提交到 Google 服务器进行验证。Google 检查证明签名并告诉您它是否真实。

如果通过了,您可以相当确信用户正在未修改的系统上运行您的应用程序的正版版本。该应用程序应在启动时获得一个证明,并将其与每个事务请求一起发送到您的服务器。

但是请注意,这意味着:

  • 已root 手机的用户不会通过这些检查 安装了自定义或第三方ROM/固件/操作系统(例如Cyanogen)的用户将不会通过这些检查

  • 无法访问 Google Play 服务的用户(例如亚马逊设备、中国人)将不会通过这些检查

...因此将无法使用您的应用程序。您的公司需要就这些限制(以及随之而来的不安用户)是否可以接受做出商业决策。

最后,意识到这不是一个完全密封的解决方案。通过 root 访问权限和 Xposed,可以修改 SafetyNet 库以欺骗 Google 的服务器,告诉他们“正确”的答案以获得 Google 签署的验证通过结果。实际上,SafetyNet 只是移动了球门柱,让恶意行为者更难对付。由于这些检查最终必须在您无法控制的设备上运行,因此设计一个完全安全的系统确实是不可能的。

在此处阅读有关 SafetyNet 内部如何工作的出色分析。

于 2020-04-10T13:21:17.380 回答
0

此代码获取 Classes.dex 文件的 CRC 校验和,并将其与提供的文件进行比较。

private void crcTest() throws IOException {
    boolean modified = false;
    // required dex crc value stored as a text string.
    // it could be any invisible layout element
    long dexCrc = Long.parseLong(Main.MyContext.getString(R.string.dex_crc));

    ZipFile zf = new ZipFile(Main.MyContext.getPackageCodePath());
    ZipEntry ze = zf.getEntry("classes.dex");

    if ( ze.getCrc() != dexCrc ) {
        // dex has been modified
        modified = true;
    }
    else {
        // dex not tampered with
        modified = false;
    }
}
于 2018-12-04T08:18:08.217 回答