Android admob 防止通过反编译 apk 移除广告

Android admob prevent remove ads by decompile apk

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

更改它:

<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。我的横幅广告和插页式广告没有显示。如何修复这个硬错误?

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

2 在 运行 时间

验证您应用的签名证书

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

简而言之,开发人员必须先使用他们的私有 key/certificate(包含在 .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 的值:

private static final String SIGNATURE = "478yYkKAQF+KST8y4ATKvHkYibo=";

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

现在,当您 运行 在您的应用程序上检查 AppSignature 时 - 当使用您的发布开发者证书签名时 - 您应该看到它 returns 0,即有效。此硬编码签名是 DexGuard 字符串加密的理想候选者。


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

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 下载的。 (参见:"Verifying the installer" 来自我发布的 link)。 但遗憾的是,您无法确定这是否适用于所有设备。我在 Google Play 中部署了此类检查并发布给 Alpha,但 9 台设备中有 2 台没有 return 字符串。我无法弄清楚,如果 Google Play 商店坏了,或者设备真的没有 return 这些字符串中的任何一个。 (在这里查看我的问题:Is it possible that getInstallerPackageName() is null when app downloaded from Google Play Store?