问题
This question already has an answer here:
- Way to protect from Lucky Patcher / play licensing [closed] 8 answers
I know this topic has been opened multiple times and I learnt a lot but I stumbled across a problem I really need advice on.
I'm using LVL with Obfuscation. I changed the default LVL ALOT so that anti-LVL does not break it. However, Lucky Patcher with one click breaks it! I tried to see the new broken APK. Yes it simply called my "allow method".
My question is if someone can recommend a way to prevent Lucky Patcher from breaking it? I know I can't make it bullet-proof, but I want it at least to be not so easy for one-click software.
回答1:
Code to check your certificate
public void checkSignature(final Context context)
{
try
{
Signature[] signatures = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
if (signatures[0].toCharsString() != <YOUR CERTIFICATE STRING GOES HERE>)
{
// Kill the process without warning. If someone changed the certificate
// is better not to give a hint about why the app stopped working
android.os.Process.killProcess(android.os.Process.myPid());
}
}
catch (NameNotFoundException ex)
{
// Must never fail, so if it does, means someone played with the apk, so kill the process
android.os.Process.killProcess(android.os.Process.myPid());
}
}
And how to find which one is your certificate, simple too. You must produce an APK, in release mode, as the debug certificate is different from the release one always. Output your certificate string to a temporary textview to copy it, or to a text file with the next call, IMPORTANT: DO NOT output it the logcat, as the string is too large and the logcat will not show it all and cut the last char characters:
signatures[0].toCharsString();
example: YourTextView.setText(signatures[0].toCharsString());
Now, remember that when you are back to debug mode, the certificate is different again, and might be different sometimes on each build, so you will get a debug hell. Then it is better to use next line to have it easier when developing, and place it right before calling the certificate testing:
if ((context.getApplicationContext().getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0)
{
return;
}
So avoid calling this certification code if in debug mode
And now the lucky patcher checker
This code will check its existence. I decompiled all versions of Lucky Patcher, and i've found out that its creator used 2 package names between all realeases. So you only need to keep track of new versions and keep adding future lucky patcher package names to the checking functions.
Also a recommendation, encrypt the package names strings instead of just harcoding them as in the example, so lucky patcher does not come out with a new version which just replaces the strings patching them. Lets make it difficult for crackers.
private boolean checkLuckyPatcher()
{
if (packageExists("com.dimonvideo.luckypatcher"))
{
return true;
}
if (packageExists("com.chelpus.lackypatch"))
{
return true;
}
if (packageExists("com.android.vending.billing.InAppBillingService.LACK"))
{
return true;
}
return false;
}
private boolean packageExists(final String packageName)
{
try
{
ApplicationInfo info = this.getPackageManager().getApplicationInfo(packageName, 0);
if (info == null)
{
// No need really to test for null, if the package does not
// exist it will really rise an exception. but in case Google
// changes the API in the future lets be safe and test it
return false;
}
return true;
}
catch (Exception ex)
{
// If we get here only means the Package does not exist
}
return false;
}
回答2:
As of current version (6.4.6), Lucky Patcher generates very short token. For example, real purchase token:
felihnbdiljiajicjhdpcgbb.AO-J1OyQgD6gEBTUHhduDpATg3hLkTYSWyVZUvFwe4KzT3r-O7o5kdt_PbG7sSUuoC1l6dtqsYZW0ZuoEkVUOq5TMi8LO1MvDwdx5Kr7vIHCVBDcjCl3CKP4UigtKmXotCUd6znJ0KfW
And that is Lucky Token:
kvfmqjhewuojbsfiwqngqqmc
Pretty straight forward solution is to check string length of token
@Override public void onIabPurchaseFinished(IabResult result, Purchase info) {
if (info.getToken().length < 25) {
Log.wtf("PIRATE", "PIRATE DETECTED");
return;
}
}
回答3:
Whenever Lucky Patcher creates a modded APK file, it always ends up with a different package name, as you can't run two apps under the same package name.
Here's a simple solution that checks if your code is running under the wrong package name:
PackageManager pm = getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo("YOUR_PACKAGE_NAME",PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException e){
finish();
//If you get here, your code is running under a different package name... Kill the process!
}
I just call finish();
on my app and I can't break it, but it might be best to use android.os.Process.killProcess(android.os.Process.myPid());
as @PerracoLabs suggested.
回答4:
Implement a function that gets called under certain actions, and which checks whether the LuckyPatcher package is installed in the device.
If found, then exit your app. Don’t allow to use it regardless if is paid or not, better bad reviews than thousands of illegal copies. Alternatively you could show a message stating that LuckyPatcher has been found and the app can't run.
If your app gets patched by LuckyPatcher, meaning that it has hacked your LVL implementation, then at least your app will not execute due to the LuckyPatcher package detection.
回答5:
A way, is to check if lucky patcher is installed and if so, then show a message to the user, and kill your process afterwards. If a user has it, means he is trying to crack your software or other developer's one. So better not to allow to use your app in a phone that has it installed. Fight piracy.
来源:https://stackoverflow.com/questions/13445598/lucky-patcher-how-can-i-protect-from-it