Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
214 views
in Technique[技术] by (71.8m points)

android - Protecting in-app purchases from Freedom Hack

I've throughtoutly searched this site as well as others for answers and found no actual one.

My question is what exactly does the Freedom Hack (which allows users to get in-app purchases without paying) do. That is, what part of the process is altered. I've found this list of applications for which the hack works, and some of the entries there are dated to this month, meaning that it hasn't been completely fixed yet. The responses I've seen were "verify the application in your server", but if the hack, for example, alters the Java.Security's signature verification function, so it always returns true, then adding my own signature in the server wouldn't help much.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I don't know if the author still follow this topic or not. But I spent sometime to find out (googling) the way how freedom work and how to prevent it (until they update the way freedom work) in my project and it works. My implementation is really simple and you don't need to verify by sending request to server (which affect the performance and take more effort to implement it).

The current implementation of freedom is that it will replace (redirect) all the method calls of java.security.Signature.verify(byte[]) to a freedom's jni method which in turn just simply always return true (or 1).

Take a look at 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);
    }

Here the engineVerify method is an abstract protected method which is first defined in java.security.SignatureSpi(Signature extends SignatureSpi). OK, that enough, because I can't believe java.security.Signature.verify(byte[]) method anymore, I would use engineVerify method directly. To do that, we need to use reflection. Modify the verify method of IABUtil/Security from:

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;
    }

To:

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;
    }

That is simple but it works with the current implementation of freedom until they update its algorithm in the future.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...