首页 > 解决方案 > Android admob通过反编译apk防止删除广告

问题描述

APK Easy Tool使用和编辑AndroidManifest.xml文件反编译 apk 后:

更改:

<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:exported="false" android:name="com.google.android.gms.ads.AdActivity" android:theme="@android:style/Theme.Translucent"/>

--> “com.google.android.gms.ads.AdActivity”

至:

<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:exported="false" android:name="hacked_com.google.android.gms.ads.AdActivity" android:theme="@android:style/Theme.Translucent"/>

--> “hacked_com.google.android.gms.ads.AdActivity”

或编辑:

<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-0000000000000000~123456789"/> // change app id

并再次保存并编译为apk。我的横幅和插页式广告没有显示。如何修复这个硬错误?

标签: androidadmobapk

解决方案


从这个来源试试这个:https ://www.airpair.com/android/posts/adding-tampering-detection-to-your-android-app :

2 在运行时验证您的应用程序的签名证书

先决条件:Android 开发者博客上有一篇关于签署应用程序的精彩文章。我建议先阅读这篇文章,因为这种技术依赖于这些知识。

简而言之,开发人员必须使用他们的私钥/证书(包含在 .keystore 文件中)对应用程序进行签名,然后才能将应用程序安装到用户设备上。签名证书必须在应用程序的整个生命周期内保持一致,并且通常具有未来 25 年的到期日期。

Android 系统在处理应用升级时依赖开发者签名证书的一致性。例如,虽然我可以创建一个与 Facebook 具有相同 App ID 的应用程序,但我无法欺骗用户升级到我的版本,因为它没有使用 Facebook 的证书签名。作为开发人员,我们必须将此证书保密,否则我们会冒其他人能够像我们一样签署应用程序的风险。

提示:将您的私钥(.keystore 文件)置于源代码控制之外,并保存在单独保护和备份的系统中。

如果 .apk 以任何方式更改,则应用签名将被破坏——通常无法安装未签名的应用。例如,我们可以想象攻击者删除许可证检查代码以启用完整的应用程序功能而无需付费。一个更危险的例子是更改 .apk 以在合法应用程序中包含恶意软件以获取敏感的用户数据。为了安装更改后的 .apk,攻击者必须将其退出。

该技术详细说明了如何确保您的 .apk 已使用您的开发人员证书进行签名,并利用了证书保持一致且只有您可以访问它的事实。

我们可以将这项技术分解为 3 个简单的步骤:

找到您的开发者证书签名。将您的签名嵌入到应用程序的字符串常量中。检查运行时的签名是否与我们的嵌入式开发人员签名匹配。

  private static final int VALID = 0;

  private static final int INVALID = 1;

  public static int checkAppSignature(Context context) {

    try {

      PackageInfo packageInfo = context.getPackageManager()

          .getPackageInfo(context.getPackageName(),

              PackageManager.GET_SIGNATURES);

      for (Signature signature : packageInfo.signatures) {

        byte[] signatureBytes = signature.toByteArray();

        MessageDigest md = MessageDigest.getInstance("SHA");

        md.update(signature.toByteArray());

        final String currentSignature = Base64.encodeToString(md.digest(), Base64.DEFAULT);

Log.d("REMOVE_ME", "Include this string as a value for SIGNATURE:" + currentSignature);

        //compare signatures

        if (SIGNATURE.equals(currentSignature)){

          return VALID;

        };

      }

    } catch (Exception e) {

//assumes an issue in checking signature., but we let the caller decide on what to do.

    }

    return INVALID;

  }

首先,我们需要找到我们证书的签名,以便我们可以将其嵌入到应用程序中。我已经包含了一行来计算并将其记录到系统日志中——不用说,一旦你有了副本,就应该删除它。

检查您的 logcat 输出是否有类似以下的消息:

10-10 17:37:11.483: D/REMOVE_ME:(111): 478yYkKAQF+KST8y4ATKvHkYibo=

记下编码签名并替换静态常量 SIGNATURE 的值:

私有静态最终字符串签名=“478yYkKAQF+KST8y4ATKvHkYibo=”;

在运行时,PackageManager 允许我们查询应用程序的签名。我们遍历这个签名数组并将其与我们的签名进行比较。

现在,当您在您的应用程序上运行 checkAppSignature 时(使用您的发布开发者证书进行签名),您应该会看到它返回 0,即有效。这种硬编码签名是 DexGuard 字符串加密的理想候选者。


或者,您可以计算签名。如果有超过 1 个 -> 中止:

public final String checkSignature()
{
    Log.i(TAG, "executeSignatureCheck()");

    Signature[] sigs;
    try
    {
        sigs = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
    }
    catch (PackageManager.NameNotFoundException e)
    {
        throw new RuntimeException("PackageManager name not found.");
    }

    String signature = null;
    int sigCount = 0;
    for (Signature sig : sigs)
    {
        signature = getSHA1(sig.toByteArray());
        Log.i(TAG, "Signature: " + signature);
        sigCount++;
    }

    if (sigCount > 1)
    {
        throw new RuntimeException("Invalid signature.");
    }

    return signature;
}

您还应该考虑检查该应用程序是否是从 Google Play 下载的。(请参阅:我发布的链接中的“验证安装程序”)。但不幸的是,您不能确定这适用于每台设备。我部署了这样的检查并在 Google Play 中发布到 Alpha,但 9 台设备中有 2 台没有返回字符串。我无法弄清楚,如果 Google Play 商店坏了,或者设备真的没有返回任何这些字符串。(在这里查看我的问题:从 Google Play 商店下载应用程序时 getInstallerPackageName() 是否可能为空?


推荐阅读