Reputation: 3301
i developed an app that's become very popular and someone cracked it. I would like to know if someone know, first of all: how?, if someone know any workaround to avoid this. The app is using the in-app purchase as per google example to unlock some premium features in this way:
private IabHelper mHelper;
if (!isPro(getActivity())) {
mHelper = new IabHelper(getActivity(), KKK);
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
return;
}
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// IAB is fully set up. Now, let's get an inventory of stuff we own.
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
}
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// Is it a failure?
if (result.isFailure()) {
return;
}
Purchase pro = inventory.getPurchase(PRO_STRING);
SettingsProvider.putSecBoolean(getActivity(), "pro", pro != null && verifyDeveloperPayload(pro));
}
};
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
if (mHelper == null) return;
if (result.isFailure()) {
return;
}
if (purchase.getSku().equals(PRO_STRING)) {
SettingsProvider.putSecBoolean(getActivity(), "pro", true);
}
}
};
boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
return true;
}
@Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null) {
mHelper.dispose();
mHelper = null;
}
}
and for the purchase process:
mPro.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RandomString randomString = new RandomString(36);
String payload = randomString.nextString();
if (mHelper != null) mHelper.flagEndAsync();
mHelper.launchPurchaseFlow(getActivity(), PRO_STRING,
IabHelper.ITEM_TYPE_INAPP, RC_REQUEST,
mPurchaseFinishedListener, payload);
}
});
Ok, someone in someway cracked it. This means the content available in the pro version are free without paid. Maybe someone can share his experience and suggest some way to avoid this?
And also, does anyone know how can that be done? Thanks
Upvotes: 4
Views: 6898
Reputation: 22183
Your code is really simple to crack, you just need to replace
SettingsProvider.putSecBoolean(getActivity(), "pro", pro != null && verifyDeveloperPayload(pro));
with:
SettingsProvider.putSecBoolean(getActivity(), "pro", true);
It can be done in several ways as antilvl does for example. You need to increase your protection a lot maybe with cross-check of your own server.
Upvotes: 0
Reputation: 12339
Brief explanation
Android applications are quite easy to crack. First of all, if you are not using any obfuscation on your code (ProGuard, DexGuard, ..), the code can be easily read and understood by using some tools like JD-GUI. In some cases, the smali
code is pretty easy to understand as well.
The obfuscation itself won't save you from cracking. There are de-obfuscators available on the market, but someone with a high pitched reverse engineering skill will still be able to figure out how to bypass your (or Google's) protection.
Finally, there is LuckyPatcher. This is perhaps the most famous tool for cracking Android apps' protection. It targets specifically certain types of protections (Google's LVL
, IAP
s, advertising networks, ..) and tries to remove them on a statistical basis. In fact, it is not guaranteed 100%, but in the vast majority of cases it will work just fine.
How to be secure, then?
You simply can't
. There is no perfect 100% security, especially in a mobile environment. What you can do, however, is trying to make a cracker's work as difficult as possible.
A few ideas:
There are a few more, I will add them as soon as I recall them all.
Upvotes: 4