保护Freedom Hack中的应用内购买

Asa*_*saf 26 android

我一直在搜索这个网站以及其他人的答案,但没有找到真正的答案.

我的问题是Freedom Hack究竟是什么(允许用户在不付费的情况下进行应用内购买).也就是说,该过程的哪个部分被改变了.我已经找到了这个黑客工作的应用程序列表,其中一些条目的日期是本月,这意味着它还没有完全修复.我看到的响应是"验证服务器中的应用程序",但是如果hack例如改变了Java.Security的签名验证功能,那么它总是返回true,那么在服务器中添加我自己的签名就不会帮助很多.

lem*_*anh 14

我不知道作者是否仍然关注这个话题.但是我花了一些时间来找出(谷歌搜索)自由工作的方式以及如何防止它(直到他们更新自由工作的方式)在我的项目中并且它有效.我的实现非常简单,您无需通过向服务器发送请求来进行验证(这会影响性能并需要花费更多精力来实现它).

当前自由的实现是它将所有方法调用替换(重定向)java.security.Signature.verify(byte[])到自由的jni方法,而自由的jni方法反过来只是总是返回true (or 1).

看看java.security.Signature.verify(byte[]):

 public final boolean verify(byte[] signature) throws SignatureException {
        if (state != VERIFY) {
            throw new SignatureException("Signature object is not initialized properly");
        }
        return engineVerify(signature);
    }
Run Code Online (Sandbox Code Playgroud)

这里的engineVerify方法是abstract protected首先在java.security.SignatureSpi(Signature extends SignatureSpi)中定义的方法.好吧,那就够了,因为我不能再相信java.security.Signature.verify(byte[])方法,我会engineVerify直接使用方法.要做到这一点,我们需要使用反射.修改from 的verify方法IABUtil/Security:

public static boolean verify(PublicKey publicKey, String signedData, String signature) {
        Signature sig;
        try {
            sig = Signature.getInstance(SIGNATURE_ALGORITHM);
            sig.initVerify(publicKey);
            sig.update(signedData.getBytes());
            if (!sig.verify(Base64.decode(signature))) {
                Log.e(TAG, "Signature verification failed.");
                return false;
            }
            return true;
        } catch (...) {
            ...
        }
        return false;
    }
Run Code Online (Sandbox Code Playgroud)

至:

public static boolean verify(PublicKey publicKey, String signedData, String signature) {
        Signature sig;
        try {
            sig = Signature.getInstance(SIGNATURE_ALGORITHM);
            sig.initVerify(publicKey);
            sig.update(signedData.getBytes());
            Method verify = java.security.SignatureSpi.class.getDeclaredMethod("engineVerify", byte[].class);
            verify.setAccessible(true);
            Object returnValue = verify.invoke(sig, Base64.decode(signature));
            if (!(Boolean)returnValue) {
                Log.e(TAG, "Signature verification failed.");
                return false;
            }
            return true;
        } catch (...) {
            ...
        }
        return false;
    }
Run Code Online (Sandbox Code Playgroud)

这很简单,但它适用于当前的自由实现,直到他们将来更新其算法.


She*_*ouk 9

然后在服务器中添加我自己的签名将无济于事.

这是不正确的,"Freedom"使用的签名无效,订单ID也无效.

我为确保我的应用程序安全所做的是:

  1. 发送isPurchaseValid(myPurchase.getSignature(), myPurchase.getOriginalJson())到我的服务器以验证那里,它适用于真正的购买,但每次自由失败.

  2. 在服务器上,我检查签名是否匹配

  3. 如果匹配,请联系"Google API Google Play Android Developer API> androidpublisher.inapppurchases.get"以验证购买是否存在并返回我的开发人员有效负载.

  4. 然后,我使用开发人员有效负载来确保此购买是针对此特定用户而不是其他用户,并且此用户正在向我发送他的数据.

PS开发者有效负载是String您在从Android应用程序购买之前设置的,它应该是您的用户独有的东西.

这可能是很多工作但它确保没有人会以自由和成功的方式购买你的东西.

我唯一不能做的就是不要让自由对我的申请产生影响,例如Path中的人做了一些我不知道是什么让自由变得没有任何影响!!!!