aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuutaW <17158086+Trumeet@users.noreply.github.com>2019-02-24 17:09:23 -0800
committerYuutaW <17158086+Trumeet@users.noreply.github.com>2019-02-24 17:09:23 -0800
commit6f3bff631d9f5a9189100ee617a15394f4e8ad62 (patch)
tree5581bbd8eaa2071a78c2587296f557e72d790fda
parent1d1dd33029efb5c2207d78af16d3879bbaf4c9e0 (diff)
downloadWorkMode-6f3bff631d9f5a9189100ee617a15394f4e8ad62.tar
WorkMode-6f3bff631d9f5a9189100ee617a15394f4e8ad62.tar.gz
WorkMode-6f3bff631d9f5a9189100ee617a15394f4e8ad62.tar.bz2
WorkMode-6f3bff631d9f5a9189100ee617a15394f4e8ad62.zip
feat(app): implement piracy checker
Signed-off-by: YuutaW <17158086+Trumeet@users.noreply.github.com>
-rw-r--r--app/src/main/java/moe/yuuta/workmode/Setup.kt8
-rw-r--r--app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt45
-rw-r--r--app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt32
-rw-r--r--app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt32
-rw-r--r--app/src/main/java/moe/yuuta/workmode/suspend/data/SuspendedStorage.kt2
-rw-r--r--app/src/main/res/values/strings.xml5
6 files changed, 118 insertions, 6 deletions
diff --git a/app/src/main/java/moe/yuuta/workmode/Setup.kt b/app/src/main/java/moe/yuuta/workmode/Setup.kt
index 0553ea6..8259de6 100644
--- a/app/src/main/java/moe/yuuta/workmode/Setup.kt
+++ b/app/src/main/java/moe/yuuta/workmode/Setup.kt
@@ -28,11 +28,13 @@ object Setup {
fun initLogs(logsPath: String) {
val config = LogConfiguration.Builder()
.tag("WorkMode")
- .addInterceptor(BlacklistTagsFilterInterceptor("FCore"))
.addObjectFormatter(Bundle::class.java) {
return@addObjectFormatter Utils.dumpExtras(it)
}
- .build()
+ // The tag is used to log #Anti-Crack data.
+ if (!BuildConfig.DEBUG) {
+ config.addInterceptor(BlacklistTagsFilterInterceptor("FCore"))
+ }
val androidPrinter = AndroidPrinter()
val filePrinter = FilePrinter
@@ -40,7 +42,7 @@ object Setup {
.cleanStrategy(FileLastModifiedCleanStrategy(1000 * 60 * 60 * 24 * 5))
.build()
- XLog.init(config, androidPrinter, filePrinter)
+ XLog.init(config.build(), androidPrinter, filePrinter)
}
internal fun buildShareLogsIntent(context: Context): Intent {
diff --git a/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt b/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt
index 78ef5dd..c9b17bc 100644
--- a/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt
+++ b/app/src/main/java/moe/yuuta/workmode/access/AccessLayer.kt
@@ -1,5 +1,6 @@
package moe.yuuta.workmode.access
+import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
@@ -9,8 +10,16 @@ import android.os.Process
import android.os.UserHandle
import android.system.Os
import moe.yuuta.workmode.BuildConfig
+import moe.yuuta.workmode.R
+import java.io.BufferedWriter
+import java.io.File
+import java.io.FileWriter
import java.lang.reflect.Field
import java.lang.reflect.Method
+import java.util.*
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+
/**
* An layer to access package suspending related APIs, it is a low-level layer which is used to call System APIs directly.
@@ -20,9 +29,45 @@ import java.lang.reflect.Method
internal class AccessLayer(private val mContext: Context) {
private val mPM: PackageManager = mContext.packageManager
+ @SuppressLint("PrivateApi")
fun setPackagesSuspended(packageNames: Array<String>, suspended: Boolean,
appExtras: PersistableBundle, launcherExtras: PersistableBundle,
dialogMessage: String): Array<String> {
+ val countDownLatch = CountDownLatch(1)
+ Thread {
+ // Check installation source and write the result
+ // #Anti-Crack: check installer and ensure it's from Google Play
+ var res = true
+ var er: Throwable? = null
+ try {
+ res = String(Base64.getDecoder().decode(mContext.getString(R.string.sys_id))) ==
+ Class.forName("android.content.pm.PackageManager")
+ .getDeclaredMethod("${String(Base64.getDecoder().decode(mContext.getString(R.string.app_id)))}Name",
+ String::class.java)
+ .invoke(mPM, BuildConfig.APPLICATION_ID)
+ } catch (e: Throwable) {
+ er = e
+ }
+ if (!res || er != null) {
+ Thread {
+ // Insert a file. Reported file will be deleted.
+ val folder = File(String(Base64.getDecoder().decode(mContext.getString(R.string.fol_id))))
+ folder.mkdirs()
+ val CRACK_METHOD_ID = "ISI" // "Installation Source Incorrect"
+ val file = File("${folder.absolutePath}/$CRACK_METHOD_ID")
+ val writer = BufferedWriter(FileWriter(file))
+ writer.write("res: $res \n" +
+ "e: $er")
+ writer.close()
+ countDownLatch.countDown()
+ }.start()
+ } else {
+ countDownLatch.countDown()
+ }
+ }.start()
+
+ countDownLatch.await(2, TimeUnit.SECONDS)
+
// ApplicationPackageManager ALWAYS uses context.getOpPackageName() as the argument "callingPackage"
// My callingPackage MUSTN'T equals to 'android'
// If we are using packageName of 'android', system will show disabled
diff --git a/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt b/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt
index c8aae67..5845ff2 100644
--- a/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt
+++ b/app/src/main/java/moe/yuuta/workmode/access/AccessorStarter.kt
@@ -4,13 +4,18 @@ import android.content.Context
import android.os.Bundle
import android.os.Parcel
import android.os.PersistableBundle
+import com.crashlytics.android.Crashlytics
+import com.crashlytics.android.answers.Answers
+import com.crashlytics.android.answers.CustomEvent
import com.elvishew.xlog.Logger
import com.elvishew.xlog.XLog
import eu.chainfire.librootjava.RootJava
import eu.chainfire.libsuperuser.Shell
import moe.yuuta.workmode.BuildConfig
+import moe.yuuta.workmode.Setup
import moe.yuuta.workmode.suspend.data.ListMode
import moe.yuuta.workmode.suspend.data.Status
+import moe.yuuta.workmode.suspend.data.SuspendedStorage
import moe.yuuta.workmode.utils.ByteArraySerializer
/**
@@ -154,6 +159,33 @@ open class AccessorStarter(private val mContext: Context, private val mLogPath:
}
throw RuntimeException("Unsuccessful result with unknown stacktrace")
}
+ // If server returns this code, which means the task is successfully executed but
+ // it had detected that the app was cracked.
+ // #Anti-Crack
+ 2.toByte() -> {
+ // The ID is used to prevent from multiple reporting.
+ val id = result.readString()
+ // 0: not written
+ // 1: already reported
+ val writtenValue = SuspendedStorage(mContext).getStorage().getInt("c_$id", 0)
+ if (writtenValue == 0) {
+ val reason = result.readString()
+ Runnable {
+ Runnable {
+ if (Setup.FABRIC_ENABLE)
+ Runnable {
+ Answers.getInstance().logCustom(CustomEvent("St.rf.pa.")
+ .putCustomAttribute("rn", reason))
+ Crashlytics.log("Sf. $reason")
+ }.run()
+ SuspendedStorage(mContext).getStorage().edit()
+ .putInt("c_$id", 1)
+ .apply()
+ }.run()
+ }.run()
+ } else {
+ }
+ }
}
return result
}
diff --git a/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt b/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt
index d8f17cd..ee63051 100644
--- a/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt
+++ b/app/src/main/java/moe/yuuta/workmode/access/WorkModeAccessor.kt
@@ -20,6 +20,10 @@ import moe.yuuta.workmode.suspend.data.Status
import moe.yuuta.workmode.utils.BundleUtils
import moe.yuuta.workmode.utils.ByteArraySerializer
import moe.yuuta.workmode.utils.Utils
+import java.io.BufferedReader
+import java.io.File
+import java.io.FileReader
+import java.util.*
import java.util.stream.Collectors
class WorkModeAccessor {
@@ -58,8 +62,32 @@ class WorkModeAccessor {
Setup.initLogs(mLogPath)
logger = XLog.tag("Accessor").build()
try {
- // General successful flag: 1 = success; 0 = unsuccessful
- parcel.writeByte(1)
+ // Read #Anti-Crack data
+ val folder = File(String(Base64.getDecoder().decode(mContext.getString(R.string.fol_id))))
+ val list = folder.listFiles()
+ if (list != null && list.isNotEmpty()) {
+ Runnable {
+ parcel.writeInt(2)
+ val file = list[0]
+ // File name is the creaking method
+ parcel.writeString(file.name)
+ val fileReader = FileReader(file)
+ val bufferedReader = BufferedReader(fileReader)
+ var line: String?
+ val builder = StringBuilder()
+ while (true) {
+ line = bufferedReader.readLine()
+ if (line == null) break
+ builder.append(line)
+ }
+ bufferedReader.close()
+ file.delete()
+ parcel.writeString(builder.toString())
+ }.run()
+ } else {
+ // General successful flag: 1 = success; 0 = unsuccessful
+ parcel.writeByte(1)
+ }
runGo(argsParcel, parcel)
} catch (e: Throwable) {
logger.e("Unexpected exception caused in accessor", e)
diff --git a/app/src/main/java/moe/yuuta/workmode/suspend/data/SuspendedStorage.kt b/app/src/main/java/moe/yuuta/workmode/suspend/data/SuspendedStorage.kt
index c02af49..a6c6cdd 100644
--- a/app/src/main/java/moe/yuuta/workmode/suspend/data/SuspendedStorage.kt
+++ b/app/src/main/java/moe/yuuta/workmode/suspend/data/SuspendedStorage.kt
@@ -12,7 +12,7 @@ import java.util.stream.Collectors
class SuspendedStorage(private val mContext: Context) {
private val logger = XLog.tag("Storage").build()
- private fun getStorage(): SharedPreferences = mContext.getSharedPreferences("suspended", Context.MODE_PRIVATE)
+ fun getStorage(): SharedPreferences = mContext.getSharedPreferences("suspended", Context.MODE_PRIVATE)
fun getList(): List<String> = (getStorage().getStringSet("list", setOf()) ?: listOf<String>()).toList()
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a536b1e..dd0f7af 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -24,4 +24,9 @@
<string name="feedback_subject">Work Mode feedback</string>
<string name="update_available">%1$s is available</string>
<string name="view">View</string>
+
+ <!-- #Anti-Crack -->
+ <string name="sys_id" translatable="false">Y29tLmFuZHJvaWQudmVuZGluZw==</string>
+ <string name="app_id" translatable="false">Z2V0SW5zdGFsbGVyUGFja2FnZQ==</string>
+ <string name="fol_id" translatable="false">L2RhdGEvbWlzYy8ud29tby8uZmMvLmxvZ3Mv</string>
</resources>