diff options
author | YuutaW <17158086+Trumeet@users.noreply.github.com> | 2019-02-28 20:32:26 -0800 |
---|---|---|
committer | YuutaW <17158086+Trumeet@users.noreply.github.com> | 2019-02-28 20:32:26 -0800 |
commit | 373bda9f0219ecd3f1069bf5fe0637c61dc87787 (patch) | |
tree | 9586d23d13cf1297c3b96cf846a36852f8568839 /app/src/main/java/moe | |
parent | 39de35e09424c573670d4c56742c17a3bdbe8108 (diff) | |
download | WorkMode-373bda9f0219ecd3f1069bf5fe0637c61dc87787.tar WorkMode-373bda9f0219ecd3f1069bf5fe0637c61dc87787.tar.gz WorkMode-373bda9f0219ecd3f1069bf5fe0637c61dc87787.tar.bz2 WorkMode-373bda9f0219ecd3f1069bf5fe0637c61dc87787.zip |
feat(app): hide and obfuscate license checking codes as much as we can
Signed-off-by: YuutaW <17158086+Trumeet@users.noreply.github.com>
Diffstat (limited to 'app/src/main/java/moe')
12 files changed, 119 insertions, 50 deletions
diff --git a/app/src/main/java/moe/yuuta/ext/ConnCallback.java b/app/src/main/java/moe/yuuta/ext/ConnCallback.java new file mode 100644 index 0000000..13af66d --- /dev/null +++ b/app/src/main/java/moe/yuuta/ext/ConnCallback.java @@ -0,0 +1,9 @@ +package moe.yuuta.ext; + +import android.content.ComponentName; +import android.os.IBinder; + +public interface ConnCallback { + void onServiceConnected(ComponentName name, IBinder service); + void onServiceDisconnected(ComponentName name); +} diff --git a/app/src/main/java/moe/yuuta/ext/IPCResultListener.java b/app/src/main/java/moe/yuuta/ext/IPCResultListener.java new file mode 100644 index 0000000..bf0045b --- /dev/null +++ b/app/src/main/java/moe/yuuta/ext/IPCResultListener.java @@ -0,0 +1,15 @@ +package moe.yuuta.ext; + +public class IPCResultListener extends IResultListener.Stub { + private final ResultCallback mCallback; + + public IPCResultListener(ResultCallback mCallback) { + this.mCallback = mCallback; + } + + @Override + public void exec(final int responseCode, final String signedData, + final String signature) { + mCallback.verifyLicense(responseCode, signedData, signature); + } +} diff --git a/app/src/main/java/moe/yuuta/gplicense/ipc/ILicenseResultListener.java b/app/src/main/java/moe/yuuta/ext/IResultListener.java index a7683b6..706b34a 100644 --- a/app/src/main/java/moe/yuuta/gplicense/ipc/ILicenseResultListener.java +++ b/app/src/main/java/moe/yuuta/ext/IResultListener.java @@ -1,4 +1,4 @@ -package moe.yuuta.gplicense.ipc; +package moe.yuuta.ext; import android.os.Binder; import android.os.IBinder; @@ -11,8 +11,8 @@ import androidx.annotation.NonNull; import moe.yuuta.gplicense.util.Base64; import moe.yuuta.gplicense.util.Base64DecoderException; -public interface ILicenseResultListener extends IInterface { - abstract class Stub extends Binder implements ILicenseResultListener { +public interface IResultListener extends IInterface { + abstract class Stub extends Binder implements IResultListener { private static final String DESCRIPTOR; static { @@ -30,13 +30,13 @@ public interface ILicenseResultListener extends IInterface { this.attachInterface(this, DESCRIPTOR); } - static ILicenseResultListener asInterface(IBinder obj) { + static IResultListener asInterface(IBinder obj) { if ((obj == null)) { return null; } IInterface iin = obj.queryLocalInterface(DESCRIPTOR); - if (iin instanceof ILicenseResultListener) { - return (ILicenseResultListener) iin; + if (iin instanceof IResultListener) { + return (IResultListener) iin; } return new Stub.Proxy(obj); } @@ -53,12 +53,12 @@ public interface ILicenseResultListener extends IInterface { reply.writeString(DESCRIPTOR); return true; } - case TRANSACTION_verifyLicense: { + case TRANSACTION: { data.enforceInterface(DESCRIPTOR); int responseCode = data.readInt(); String signedData = data.readString(); String signature = data.readString(); - this.verifyLicense(responseCode, signedData, signature); + this.exec(responseCode, signedData, signature); return true; } default: { @@ -67,7 +67,7 @@ public interface ILicenseResultListener extends IInterface { } } - private static class Proxy implements ILicenseResultListener { + private static class Proxy implements IResultListener { private IBinder mRemote; Proxy(IBinder remote) { @@ -80,22 +80,23 @@ public interface ILicenseResultListener extends IInterface { } @Override - public void verifyLicense(int responseCode, String signedData, String signature) throws RemoteException { + public void exec(int responseCode, String signedData, String signature) throws RemoteException { Parcel args = Parcel.obtain(); try { args.writeInterfaceToken(DESCRIPTOR); args.writeInt(responseCode); args.writeString(signedData); args.writeString(signature); - mRemote.transact(TRANSACTION_verifyLicense, args, null, IBinder.FLAG_ONEWAY); + mRemote.transact(TRANSACTION, args, null, IBinder.FLAG_ONEWAY); } finally { args.recycle(); } } } - static final int TRANSACTION_verifyLicense = IBinder.FIRST_CALL_TRANSACTION; + static final int TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; } - void verifyLicense(int responseCode, String signedData, String signature) throws RemoteException; + // verifyLicense + void exec(int responseCode, String signedData, String signature) throws RemoteException; }
\ No newline at end of file diff --git a/app/src/main/java/moe/yuuta/gplicense/ipc/ILicensingService.java b/app/src/main/java/moe/yuuta/ext/IService.java index 14e27f4..ea0b136 100644 --- a/app/src/main/java/moe/yuuta/gplicense/ipc/ILicensingService.java +++ b/app/src/main/java/moe/yuuta/ext/IService.java @@ -1,4 +1,4 @@ -package moe.yuuta.gplicense.ipc; +package moe.yuuta.ext; import android.os.Binder; import android.os.IBinder; @@ -11,8 +11,8 @@ import androidx.annotation.NonNull; import moe.yuuta.gplicense.util.Base64; import moe.yuuta.gplicense.util.Base64DecoderException; -public interface ILicensingService extends IInterface { - abstract class Stub extends Binder implements ILicensingService { +public interface IService extends IInterface { + abstract class Stub extends Binder implements IService { private static final String DESCRIPTOR; static { @@ -30,15 +30,15 @@ public interface ILicensingService extends IInterface { this.attachInterface(this, DESCRIPTOR); } - public static ILicensingService asInterface(IBinder obj) { + public static IService asInterface(IBinder obj) { if ((obj == null)) { return null; } IInterface iin = obj.queryLocalInterface(DESCRIPTOR); - if (iin instanceof ILicensingService) { - return (ILicensingService) iin; + if (iin instanceof IService) { + return (IService) iin; } - return new ILicensingService.Stub.Proxy(obj); + return new IService.Stub.Proxy(obj); } @Override @@ -57,8 +57,8 @@ public interface ILicensingService extends IInterface { data.enforceInterface(DESCRIPTOR); long nonce = data.readLong(); String packageName = data.readString(); - ILicenseResultListener listener = ILicenseResultListener.Stub.asInterface(data.readStrongBinder()); - this.checkLicense(nonce, packageName, listener); + IResultListener listener = IResultListener.Stub.asInterface(data.readStrongBinder()); + this.exec(nonce, packageName, listener); return true; } default: { @@ -67,7 +67,7 @@ public interface ILicensingService extends IInterface { } } - private static class Proxy implements ILicensingService { + private static class Proxy implements IService { private IBinder mRemote; Proxy(IBinder remote) { @@ -80,7 +80,7 @@ public interface ILicensingService extends IInterface { } @Override - public void checkLicense(long nonce, String packageName, ILicenseResultListener listener) throws RemoteException { + public void exec(long nonce, String packageName, IResultListener listener) throws RemoteException { Parcel args = Parcel.obtain(); try { args.writeInterfaceToken(DESCRIPTOR); @@ -97,5 +97,6 @@ public interface ILicensingService extends IInterface { static final int TRANSACTION_checkLicense = IBinder.FIRST_CALL_TRANSACTION; } - void checkLicense(long nonce, String packageName, ILicenseResultListener listener) throws RemoteException; + // checkLicense + void exec(long nonce, String packageName, IResultListener listener) throws RemoteException; }
\ No newline at end of file diff --git a/app/src/main/java/moe/yuuta/ext/LicServiceConn.java b/app/src/main/java/moe/yuuta/ext/LicServiceConn.java new file mode 100644 index 0000000..f0ad766 --- /dev/null +++ b/app/src/main/java/moe/yuuta/ext/LicServiceConn.java @@ -0,0 +1,23 @@ +package moe.yuuta.ext; + +import android.content.ComponentName; +import android.content.ServiceConnection; +import android.os.IBinder; + +public class LicServiceConn implements ServiceConnection { + private final ConnCallback mCallback; + + public LicServiceConn(ConnCallback mCallback) { + this.mCallback = mCallback; + } + + @Override + public synchronized void onServiceConnected(ComponentName name, IBinder service) { + mCallback.onServiceConnected(name, service); + } + + @Override + public synchronized void onServiceDisconnected(ComponentName name) { + mCallback.onServiceDisconnected(name); + } +} diff --git a/app/src/main/java/moe/yuuta/ext/ResultCallback.java b/app/src/main/java/moe/yuuta/ext/ResultCallback.java new file mode 100644 index 0000000..4feafba --- /dev/null +++ b/app/src/main/java/moe/yuuta/ext/ResultCallback.java @@ -0,0 +1,6 @@ +package moe.yuuta.ext; + +public interface ResultCallback { + void verifyLicense(final int responseCode, final String signedData, + final String signature); +} diff --git a/app/src/main/java/moe/yuuta/ext/package-info.java b/app/src/main/java/moe/yuuta/ext/package-info.java new file mode 100644 index 0000000..128e042 --- /dev/null +++ b/app/src/main/java/moe/yuuta/ext/package-info.java @@ -0,0 +1,4 @@ +/** + * Classes which cannot be processed by ProGuard are moved to here to keep LicenseChecker processed. + */ +package moe.yuuta.ext;
\ No newline at end of file diff --git a/app/src/main/java/moe/yuuta/gplicense/LicenseChecker.java b/app/src/main/java/moe/yuuta/gplicense/LicenseChecker.java index 92986b8..7d4cfa8 100644 --- a/app/src/main/java/moe/yuuta/gplicense/LicenseChecker.java +++ b/app/src/main/java/moe/yuuta/gplicense/LicenseChecker.java @@ -4,7 +4,6 @@ import android.annotation.SuppressLint; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.ServiceConnection; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Handler; import android.os.HandlerThread; @@ -27,8 +26,11 @@ import java.util.LinkedList; import java.util.Queue; import java.util.Set; -import moe.yuuta.gplicense.ipc.ILicenseResultListener; -import moe.yuuta.gplicense.ipc.ILicensingService; +import moe.yuuta.ext.ConnCallback; +import moe.yuuta.ext.IPCResultListener; +import moe.yuuta.ext.IService; +import moe.yuuta.ext.LicServiceConn; +import moe.yuuta.ext.ResultCallback; import moe.yuuta.gplicense.util.Base64; import moe.yuuta.gplicense.util.Base64DecoderException; import moe.yuuta.workmode.BuildConfig; @@ -44,7 +46,7 @@ import moe.yuuta.workmode.BuildConfig; * Must also provide the Base64-encoded RSA public key associated with your developer account. The * public key is obtainable from the publisher site. */ -public class LicenseChecker implements ServiceConnection { +public class LicenseChecker implements ConnCallback { private static final Logger logger = XLog.tag("LCK").build(); private static final String KEY_FACTORY_ALGORITHM = "RSA"; @@ -55,7 +57,7 @@ public class LicenseChecker implements ServiceConnection { private static final SecureRandom RANDOM = new SecureRandom(); private static final boolean DEBUG_LICENSE_ERROR = BuildConfig.DEBUG; - private ILicensingService mService; + private IService mService; private PublicKey mPublicKey; private final Context mContext; @@ -70,6 +72,8 @@ public class LicenseChecker implements ServiceConnection { private final Set<LicenseValidator> mChecksInProgress = new HashSet<LicenseValidator>(); private final Queue<LicenseValidator> mPendingChecks = new LinkedList<LicenseValidator>(); + private LicServiceConn mConn; + /** * @param context a Context * @param policy implementation of Policy @@ -118,7 +122,7 @@ public class LicenseChecker implements ServiceConnection { * recommend obfuscating the string that is passed into bindService using another method of your * own devising. * <p> - * source string: "com.android.vending.licensing.ILicensingService" + * source string: "com.android.vending.licensing.IService" * <p> * * @param callback @@ -127,7 +131,7 @@ public class LicenseChecker implements ServiceConnection { // If we have a valid recent LICENSED response, we can skip asking // Market. if (mPolicy.allowAccess()) { - logger.i("Using cached license response"); + logger.i("Using cached response"); callback.allow(Policy.LICENSED); } else { LicenseValidator validator = new LicenseValidator(mPolicy, new NullDeviceLimiter(), @@ -136,12 +140,13 @@ public class LicenseChecker implements ServiceConnection { if (mService == null) { logger.i("Binding to service."); try { + mConn = new LicServiceConn(this); boolean bindResult = mContext .bindService( new Intent( new String( // Base64 encoded - - // com.android.vending.licensing.ILicensingService + // com.android.vending.licensing.IService // Consider encoding this in another way in your // code to improve security Base64.decode( @@ -163,7 +168,7 @@ public class LicenseChecker implements ServiceConnection { // com.android.vending Base64.decode( "Y29tLmFuZHJvaWQudmVuZGluZw=="))), - this, // ServiceConnection. + mConn, // ServiceConnection. Context.BIND_AUTO_CREATE); if (bindResult) { mPendingChecks.offer(validator); @@ -188,12 +193,12 @@ public class LicenseChecker implements ServiceConnection { while ((validator = mPendingChecks.poll()) != null) { try { logger.i("Executing on service for " + validator.getPackageName()); - mService.checkLicense( + mService.exec( validator.getNonce(), validator.getPackageName(), - new ResultListener(validator)); + new IPCResultListener(new ResultListener(validator))); mChecksInProgress.add(validator); } catch (RemoteException e) { - logger.w("RemoteException in checkLicense call.", e); + logger.w("RemoteException in exec call.", e); handleServiceConnectionError(validator); } } @@ -206,7 +211,7 @@ public class LicenseChecker implements ServiceConnection { } } - private class ResultListener extends ILicenseResultListener.Stub { + private class ResultListener implements ResultCallback { private final LicenseValidator mValidator; private Runnable mOnTimeout; @@ -226,6 +231,7 @@ public class LicenseChecker implements ServiceConnection { // Runs in IPC thread pool. Post it to the Handler, so we can guarantee // either this or the timeout runs. + @Override public void verifyLicense(final int responseCode, final String signedData, final String signature) { mHandler.post(() -> { @@ -280,11 +286,13 @@ public class LicenseChecker implements ServiceConnection { } } + @Override public synchronized void onServiceConnected(ComponentName name, IBinder service) { - mService = ILicensingService.Stub.asInterface(service); + mService = IService.Stub.asInterface(service); runChecks(); } + @Override public synchronized void onServiceDisconnected(ComponentName name) { // Called when the connection with the service has been // unexpectedly disconnected. That is, Market crashed. @@ -311,7 +319,7 @@ public class LicenseChecker implements ServiceConnection { private void cleanupService() { if (mService != null) { try { - mContext.unbindService(this); + mContext.unbindService(mConn); } catch (IllegalArgumentException e) { // Somehow we've already been unbound. This is a non-fatal // error. diff --git a/app/src/main/java/moe/yuuta/gplicense/LicenseValidator.java b/app/src/main/java/moe/yuuta/gplicense/LicenseValidator.java index 142f350..d34d614 100644 --- a/app/src/main/java/moe/yuuta/gplicense/LicenseValidator.java +++ b/app/src/main/java/moe/yuuta/gplicense/LicenseValidator.java @@ -184,7 +184,7 @@ class LicenseValidator { handleApplicationError(LicenseCheckerCallback.ERROR_NOT_MARKET_MANAGED); break; default: - logger.e("Unknown response code for license check."); + logger.e("Unknown response code for checking."); handleInvalidResponse(); } } diff --git a/app/src/main/java/moe/yuuta/gplicense/ServerManagedPolicy.java b/app/src/main/java/moe/yuuta/gplicense/ServerManagedPolicy.java index 8355cb8..fcc3451 100644 --- a/app/src/main/java/moe/yuuta/gplicense/ServerManagedPolicy.java +++ b/app/src/main/java/moe/yuuta/gplicense/ServerManagedPolicy.java @@ -159,7 +159,7 @@ public class ServerManagedPolicy implements Policy { lValidityTimestamp = Long.parseLong(validityTimestamp); } catch (NumberFormatException e) { // No response or not parsable, expire in one minute. - logger.w("License validity timestamp (VT) missing, caching for a minute"); + logger.w("Validity timestamp (VT) missing, caching for a minute"); lValidityTimestamp = System.currentTimeMillis() + MILLIS_PER_MINUTE; validityTimestamp = Long.toString(lValidityTimestamp); } diff --git a/app/src/main/java/moe/yuuta/workmode/MainActivity.kt b/app/src/main/java/moe/yuuta/workmode/MainActivity.kt index b09e38e..792e948 100644 --- a/app/src/main/java/moe/yuuta/workmode/MainActivity.kt +++ b/app/src/main/java/moe/yuuta/workmode/MainActivity.kt @@ -29,7 +29,7 @@ import moe.yuuta.gplicense.LicenseCheckerCallback import moe.yuuta.gplicense.Policy import moe.yuuta.workmode.access.AccessorStarter import moe.yuuta.workmode.async.* -import moe.yuuta.workmode.gpl.GPLicenser +import moe.yuuta.workmode.gpl.GPL import moe.yuuta.workmode.suspend.AsyncSuspender import moe.yuuta.workmode.suspend.SuspendTile import moe.yuuta.workmode.suspend.data.ListMode @@ -78,7 +78,7 @@ class MainActivity : AppCompatActivity(), SwitchBar.OnSwitchChangeListener, View filter.addAction(AccessorStarter.ACTION_UPDATE_UI_PROGRESS) registerReceiver(mUIUpdateReceiver, filter) scheduleUpdateChecking() - lifecycle.addObserver(GPLicenser(this, lifecycle, this)) + lifecycle.addObserver(GPL(this, lifecycle, this)) setProgressUI(false) } diff --git a/app/src/main/java/moe/yuuta/workmode/gpl/GPLicenser.kt b/app/src/main/java/moe/yuuta/workmode/gpl/GPL.kt index fdcad9a..3824f19 100644 --- a/app/src/main/java/moe/yuuta/workmode/gpl/GPLicenser.kt +++ b/app/src/main/java/moe/yuuta/workmode/gpl/GPL.kt @@ -12,7 +12,9 @@ import moe.yuuta.gplicense.LicenseCheckerCallback import moe.yuuta.gplicense.ServerManagedPolicy import moe.yuuta.workmode.BuildConfig -class GPLicenser( +// #Anti-Crack +// Google Play Licenser +class GPL( private val context: Context, private val lifecycle: Lifecycle, private val callback: LicenseCheckerCallback @@ -22,24 +24,24 @@ class GPLicenser( -9, -5, -77, -71, -36, -79, -11, 37, -69, 88 ) - private lateinit var checker: LicenseChecker + private lateinit var instance: LicenseChecker @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun start() { @SuppressLint("HardwareIds") val android_id = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) - checker = LicenseChecker( + instance = LicenseChecker( context, ServerManagedPolicy(context, AESObfuscator(SALT, BuildConfig.APPLICATION_ID, android_id)), BuildConfig.GOOGLE_PLAY_LICENSING_KEY ) - checker.checkAccess(callback) + instance.checkAccess(callback) } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun destroy() { - if (::checker.isInitialized) { - checker.onDestroy() + if (::instance.isInitialized) { + instance.onDestroy() } } }
\ No newline at end of file |