aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuutaW <17158086+Trumeet@users.noreply.github.com>2019-02-28 20:32:26 -0800
committerYuutaW <17158086+Trumeet@users.noreply.github.com>2019-02-28 20:32:26 -0800
commit373bda9f0219ecd3f1069bf5fe0637c61dc87787 (patch)
tree9586d23d13cf1297c3b96cf846a36852f8568839
parent39de35e09424c573670d4c56742c17a3bdbe8108 (diff)
downloadWorkMode-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>
-rw-r--r--app/src/main/java/moe/yuuta/ext/ConnCallback.java9
-rw-r--r--app/src/main/java/moe/yuuta/ext/IPCResultListener.java15
-rw-r--r--app/src/main/java/moe/yuuta/ext/IResultListener.java (renamed from app/src/main/java/moe/yuuta/gplicense/ipc/ILicenseResultListener.java)27
-rw-r--r--app/src/main/java/moe/yuuta/ext/IService.java (renamed from app/src/main/java/moe/yuuta/gplicense/ipc/ILicensingService.java)25
-rw-r--r--app/src/main/java/moe/yuuta/ext/LicServiceConn.java23
-rw-r--r--app/src/main/java/moe/yuuta/ext/ResultCallback.java6
-rw-r--r--app/src/main/java/moe/yuuta/ext/package-info.java4
-rw-r--r--app/src/main/java/moe/yuuta/gplicense/LicenseChecker.java38
-rw-r--r--app/src/main/java/moe/yuuta/gplicense/LicenseValidator.java2
-rw-r--r--app/src/main/java/moe/yuuta/gplicense/ServerManagedPolicy.java2
-rw-r--r--app/src/main/java/moe/yuuta/workmode/MainActivity.kt4
-rw-r--r--app/src/main/java/moe/yuuta/workmode/gpl/GPL.kt (renamed from app/src/main/java/moe/yuuta/workmode/gpl/GPLicenser.kt)14
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