7

我即将发布一个应用程序,不希望它被盗版......即使你有许可,也有像luckypatcher这样的应用程序可以为你破解应用程序......

任何人都知道如何防止这种情况?

4

8 回答 8

12

要阻止您的应用程序以破解形式分发和重新打包,请参阅下面的签名检查。那么,至少只有那些安装了 LuckyPatcher 的人才能让你的应用正常运行。一旦 LuckyPacher 创建了一个修改过的 APK,签名就会改变。

当您运行发布版本时,您需要找出您的签名是什么。在下面的示例中,它是 -343553346 。

String sigChk = MySigCheck.MySigCheck(context);
if (sigChk.equalsIgnoreCase("Y")){
    handle signature pass
}

创建一个类

public class MySigCheck {
public static String MySigCheck(Context context) {
    String sigChk = "B";

    Signature[] signature = new Signature[0];

    try {
        signature = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;

        Log.d("yourapp", Integer.toString(signature[0].hashCode())); << Prints your signature. Remove once you know this and have changed it below.

    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }

    if (signature[0].hashCode() == -343553346){
        sigChk = "Y";
    }

        return sigChk;
    }
}
于 2014-06-26T22:34:10.400 回答
11

简短的回答不是真的。

您可以观看关于使用许可 API 等Google IO Anti Pirate的一些最佳实践的 google IO 聊天

我知道还有另一个关于阻止懒惰海盗的一般模式的讨论,但似乎找不到 URL。

一般来说,如果您的保护依赖于 if/then 逻辑,那么某人所要做的就是修补代码并反转该逻辑或一起绕过它,这在 Java 中非常容易。

您可以通过混淆您在哪里执行此操作、在许多地方执行此操作、随机执行此操作以及添加 pro-guard 混淆等来阻止临时黑客,从而使其变得更加困难。

即使服务器端逻辑也很容易绕过,除非以某种方式使用返回包(例如与用户或电话信息同步以解锁内容的加密令牌,或访问在线社区内容所需的用户 ID 验证方案等) .)

最后,如果有人下定决心并拥有技能,他们就可以解决所有问题,除非您损失了可观的收入,否则在我看来几乎不值得失眠,这是我们所有人都需要解决的问题!

在做了 20 年(商业开发)之后,我的方法是通过使用上述模式使其变得困难,并偶尔更改它。这淘汰了懒惰的海盗。

然后忘掉它,专注于制作一个值得盗版者窃取的应用程序。

我的方法

我的应用程序主要是内容驱动的。

一般来说,如果有人购买内容,它会使用令牌服务器端加密并使用相同的未加密(不存储但使用设备和用户令牌生成每个会话,这只会使诚实欺骗变得有点困难)

然后我可以通过用户/设备配对跟踪访问。黑客的缺点是他们必须支付一次,如果他们的代币突然被使用超出合理限制,它会提醒我注意这一事实,如果我愿意,我可以关闭该帐户(我已经)

我发现社交上的人不太可能让某人使用与他们相关的信息作弊(尽管它已经发生了)并且它会回到他们身上。

我仍然遵循来自 IO/Dev Blog 等的所有建议,如果我检测到篡改,我会通知用户,然后让它离开 N 段时间,以便他们可以联系我或自我纠正。

我也从不杀死应用程序,但我确实告诉用户他们正在使用恶意软件,并询问他们是否真的信任窃取数据的人等。这些弹出窗口的消息有点简单,所以简单的字符串搜索就赢了't work etc. 并吓到人们

我还有一种方法可以向设备发送毒物令牌集,这实际上会锁定他们在设备上积累的任何数据,除非我解锁它,但你最好在你对它们进行核攻击之前真正确定他们是小偷。

也不要忽视分析作为一种检测方式,并在检测到盗版时确定要采取的适当措施。

遵循博文和 IO 提到的指导方针,然后创造性地应用它们,并混合一些独特的解决方案,然后不时更改它以适应海盗。

于 2012-05-14T15:37:25.740 回答
6

基于 LuckyPatcher 使用 odex 替换来进行黑客攻击的事实。我认为打败其当前实现的适度方法是在单独的 dex 中编译您的重要代码,并通过 DexClassLoader 加载它。

参考:http ://android-developers.blogspot.pt/2011/07/custom-class-loading-in-dalvik.html

于 2013-12-04T17:08:23.547 回答
3

我这样做的方法是密切关注幸运修补程序的包名称,以防他们更改它。所以在运行时我检查它是否已安装,如果这个应用程序实际安装在手机上,我根本不允许使用我的应用程序,即使他们购买了该应用程序。我警告用户并杀死我的应用程序。所以他将不得不找到另一种方法来破解它。我能得到的更糟糕的是,他必须购买我的应用程序,并且肯定会给出 1 条差评。但老实说,我更喜欢黑客的 1 条差评,而不是每天 1000 份盗版。

于 2013-02-05T19:39:09.213 回答
2

我听说的唯一方法是进行服务器验证......让您的应用联系服务器并验证他们购买了您的应用。

这是关于通过 Google 进行应用内计费,为什么远程服务器上的签名验证比设备上更安全?

开发网站上的一些关于 Google Play 的一般信息和应用内计费的一些很好的信息这里

不幸的是,我没有找到太多其他东西......

于 2012-05-14T15:17:50.610 回答
1

作为一名专业的 IT 工程师和普通的高级用户(Linux、Windows、Android、OS X、iOS),我在命令行界面和图形界面中都感到很舒服,我使用我可以使用的工具来实现我的目标。我无法想象使用没有植根的 Android 设备,而且我通常会加载大量需要它的实用程序。至少,我可以自由地控制我最喜欢的设备通常附带的强制性过时软件,插入我自己的系统应用程序,并为美观、舒适和方便进行合法修改。

我被迫走一些狡猾的途径,只是为了在作者选择削弱根用户的应用程序中实现适当的功能。被(例如)Virgin TV Anywhere 告知我的设备有“未经授权的修改”让我热血沸腾,如果这是我追求预期功能的唯一选择,我会很乐意破坏他们的代码并违反一些许可协议。

在这方面,我同意您邀请很多用户,无论是出于愤慨还是仅仅出于效用,如果您选择上述媒体应用程序这样一条严厉的道路,就会挫败您的努力。当您的代码的“固定”版本作为种子比您的合法销售更普遍时,这甚至可能完全鼓励您的应用程序盗版。

就个人而言,我总是选择付费选项,即使我被迫吞下我的安全感并用我几乎不信任的工具打破它以使其发挥作用。但是,对于许多人来说,他们对您的产品的最初曝光是通过邪恶的渠道进行的,他们几乎不会为合法的和绝望的残缺版本付费。

我理解为什么一些编码人员被迫做出这些选择,并且很高兴看到关于保护知识产权的正确方法的明智问题。

从答案中看到意义就更令人放心了。

只是我的礼物。

于 2016-01-26T09:18:00.993 回答
0

如果他们有 root 设备,则可以隐藏 su 二进制文件以使用该应用程序,检查 root 是最好的方法,除非您可以使用非 root 版本的自由,然后您需要修复它。检查像游戏杀手这样的黑客工具会阻止懒惰的人,但不能阻止将字符串反编译为另一个的人。

于 2015-05-07T09:37:37.227 回答
-5

Lucky Patcher 在有根设备中工作。我检查手机是否已root。在我的第一个活动中,我检查手机是否为root,我的应用程序被锁定,否则我的应用程序打开。

使用以下方法检查是根:

    private static boolean isRooted() {
    return findBinary("su");
}



public static boolean findBinary(String binaryName) {
    boolean found = false;
    if (!found) {
        String[] places = {"/sbin/", "/system/bin/", "/system/xbin/", "/data/local/xbin/",
                "/data/local/bin/", "/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/"};
        for (String where : places) {
            if ( new File( where + binaryName ).exists() ) {
                found = true;
                break;
            }
        }
    }
    return found;
}
于 2015-01-12T16:14:21.760 回答