androidandroid-lvl

Lucky patcher, how can I protect from it?


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.


Solution

  • 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());
        }
    }
    

    Next how to find which one is your certificate. You must produce an APK, in release mode, as the debug certificate is different from the release one. Output your certificate into your Logcat:

    signatures[0].toCharsString();
    

    Remember that when you are back to debug mode, the certificate is different again. To avoid debug issues use next line to skip the verification:

    if ((context.getApplicationContext().getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0)
        return;
    

    Next the lucky patcher checker. I decompiled all versions of Lucky Patcher, and I've found that its creator used 2 package names between all realeases. So you only need to keep track of new versions and keep adding future package names.

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