检测Apk中的代码篡改

时间:2018-05-02 03:37:02

标签: android security reverse-engineering signing tampering

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

2 个答案:

答案 0 :(得分: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;
 }
}

答案 1 :(得分:0)

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

方法如下:

使用Android SafetyNet。这就是Android Pay进行自我验证的方式。

基本流程是:

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

如果通过,您可以完全确定该用户正在未修改的系统上运行应用程序的正版版本。该应用程序启动时应获得证明,并随每个交易请求将其发送给您的服务器。

请注意,这意味着:

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

  • 无权访问Google Play服务的用户(例如Amazon) 设备,在中国的人)将无法通过这些检查

...,因此将无法使用您的应用。您的公司需要就是否可以接受这些限制(以及伴随的沮丧用户)做出业务决策。

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

Read an excellent analysis of how the internals of SafetyNet work here.