x1ongzhu 1 год назад
Родитель
Сommit
00e6098d4b

+ 0 - 93
app/src/main/java/com/example/modifier/Global.kt

@@ -1,93 +0,0 @@
-package com.example.modifier
-
-import android.Manifest
-import android.annotation.SuppressLint
-import android.app.AlarmManager
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build
-import android.telephony.SubscriptionManager
-import android.util.Log
-import androidx.core.content.ContextCompat
-import com.example.modifier.constants.CMD_MESSAGING_APP
-import com.example.modifier.constants.PACKAGE_GMS
-import com.example.modifier.constants.PACKAGE_GSF
-import com.example.modifier.constants.PACKAGE_MESSAGING
-import com.example.modifier.data.BackupItem
-import com.example.modifier.data.BackupItemDao
-import com.example.modifier.extension.disable
-import com.example.modifier.extension.enable
-import com.example.modifier.model.SpoofedSimInfo
-import com.example.modifier.serializer.Json
-import com.example.modifier.utils.clearConv
-import com.example.modifier.utils.hasPermission
-import com.example.modifier.utils.resumePackage
-import com.example.modifier.utils.shellRun
-import com.example.modifier.utils.suspendPackage
-import com.google.gson.Gson
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.withContext
-import kotlinx.serialization.encodeToString
-import org.apache.commons.io.FileUtils
-import org.apache.commons.io.IOUtils
-import org.apache.commons.lang3.RandomStringUtils
-import java.io.File
-import java.nio.file.Files
-import java.util.Date
-import java.util.Optional
-import kotlin.system.exitProcess
-
-
-object Global {
-
-    fun sqlite3path(): String {
-        val context = Utils.getContext()
-        val dataDir = ContextCompat.getDataDir(context)
-        val binDir = File(dataDir, "bin")
-        val dbDir = File(dataDir, "providerDB")
-        if (!binDir.exists()) {
-            Utils.copyAssetFolder(context.assets, "bin", binDir.path)
-            Utils.copyAssetFolder(context.assets, "providerDB", dbDir.path)
-            binDir.listFiles()?.forEach {
-                it.setExecutable(true)
-            }
-        }
-        Log.i("Modifier", "arch: " + Build.SUPPORTED_ABIS.joinToString(", "))
-        val file = File(dataDir, "bin/sqlite3.arm")
-        file.setExecutable(true)
-        return file.path
-    }
-
-    @JvmStatic
-    fun sendSmsIntent(sender: String, msg: String) {
-        val intent = Intent()
-        intent.setAction("com.example.modifier.sms")
-        intent.putExtra("sender", sender)
-        intent.putExtra(
-            "message",
-            msg
-        )
-        val context = Utils.getContext()
-        context.sendBroadcast(intent)
-    }
-
-
-
-    @JvmStatic
-    fun restartModifier() {
-        val context = Utils.getContext()
-        val mStartActivity: Intent = Intent(context, MainActivity::class.java)
-        val mPendingIntentId = 123456
-        val mPendingIntent = PendingIntent.getActivity(
-            context,
-            mPendingIntentId,
-            mStartActivity,
-            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
-        )
-        val mgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
-        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent)
-        exitProcess(0)
-    }
-}

+ 0 - 1
app/src/main/java/com/example/modifier/adapter/BackupAdapter.kt

@@ -10,7 +10,6 @@ import android.view.ViewGroup
 import android.widget.Toast
 import androidx.appcompat.content.res.AppCompatResources
 import androidx.recyclerview.widget.RecyclerView
-import com.example.modifier.Global
 import com.example.modifier.R
 import com.example.modifier.Utils
 import com.example.modifier.adapter.BackupAdapter.BackupViewHolder

+ 34 - 11
app/src/main/java/com/example/modifier/repo/SpoofedSimInfoRepository.kt

@@ -5,6 +5,7 @@ import android.annotation.SuppressLint
 import android.content.Context
 import android.telephony.SubscriptionManager
 import android.util.Log
+import androidx.core.content.ContextCompat
 import androidx.datastore.preferences.core.booleanPreferencesKey
 import androidx.datastore.preferences.core.edit
 import androidx.datastore.preferences.core.stringPreferencesKey
@@ -14,6 +15,7 @@ import com.example.modifier.Utils
 import com.example.modifier.constants.PACKAGE_GMS
 import com.example.modifier.constants.PACKAGE_MESSAGING
 import com.example.modifier.model.SpoofedSimInfo
+import com.example.modifier.serializer.Json
 import com.example.modifier.utils.genICCID
 import com.example.modifier.utils.genIMEI
 import com.example.modifier.utils.genIMSI
@@ -22,9 +24,13 @@ import com.example.modifier.utils.isOldVersion
 import com.example.modifier.utils.resumePackage
 import com.example.modifier.utils.shellRun
 import com.example.modifier.utils.suspendPackage
+import com.google.gson.Gson
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
+import kotlinx.serialization.decodeFromString
+import org.apache.commons.io.FileUtils
+import java.io.File
 import kotlin.coroutines.coroutineContext
 
 val Context.simInfoDataStore by preferencesDataStore(name = "${BuildConfig.APPLICATION_ID}.simInfo")
@@ -46,17 +52,34 @@ class SpoofedSimInfoRepository(private val context: Context) {
     }
 
     val simInfoFlow = context.simInfoDataStore.data.map {
-        val number = it[PreferencesKeys.NUMBER] ?: ""
-        val mcc = it[PreferencesKeys.MCC] ?: ""
-        val mnc = it[PreferencesKeys.MNC] ?: ""
-        val iccid = it[PreferencesKeys.ICCID] ?: ""
-        val imsi = it[PreferencesKeys.IMSI] ?: ""
-        val imei = it[PreferencesKeys.IMEI] ?: ""
-        val country = it[PreferencesKeys.COUNTRY] ?: ""
-        val areaCode = it[PreferencesKeys.AREA_CODE] ?: ""
-        val available = it[PreferencesKeys.AVAILABLE] ?: false
-        val carrierId = it[PreferencesKeys.CARRIER_ID] ?: ""
-        val carrierName = it[PreferencesKeys.CARRIER_NAME] ?: ""
+        val file = File(ContextCompat.getDataDir(context), "config.json")
+        val old = file.exists().let {
+            if (it) {
+                try {
+                    return@let Json.decodeFromString<SpoofedSimInfo>(
+                        FileUtils.readFileToString(
+                            file,
+                            "UTF-8"
+                        )
+                    )
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                }
+            }
+            null
+        }
+
+        val number = it[PreferencesKeys.NUMBER] ?: old?.number ?: ""
+        val mcc = it[PreferencesKeys.MCC] ?: old?.mcc ?: ""
+        val mnc = it[PreferencesKeys.MNC] ?: old?.mnc ?: ""
+        val iccid = it[PreferencesKeys.ICCID] ?: old?.iccid ?: ""
+        val imsi = it[PreferencesKeys.IMSI] ?: old?.imsi ?: ""
+        val imei = it[PreferencesKeys.IMEI] ?: old?.imei ?: ""
+        val country = it[PreferencesKeys.COUNTRY] ?: old?.country ?: ""
+        val areaCode = it[PreferencesKeys.AREA_CODE] ?: old?.areaCode ?: ""
+        val available = it[PreferencesKeys.AVAILABLE] ?: old?.available ?: false
+        val carrierId = it[PreferencesKeys.CARRIER_ID] ?: old?.carrierId ?: ""
+        val carrierName = it[PreferencesKeys.CARRIER_NAME] ?: old?.carrierName ?: ""
         SpoofedSimInfo(
             number = number,
             mcc = mcc,

+ 4 - 7
app/src/main/java/com/example/modifier/service/ModifierService.kt

@@ -26,11 +26,8 @@ import androidx.annotation.MenuRes
 import androidx.appcompat.widget.PopupMenu
 import androidx.core.content.ContextCompat
 import com.example.modifier.BuildConfig
-import com.example.modifier.Global
-import com.example.modifier.Global.restartModifier
 import com.example.modifier.R
 import com.example.modifier.TraverseResult
-import com.example.modifier.Utils
 import com.example.modifier.constants.CMD_BACK
 import com.example.modifier.constants.CMD_CONVERSATION_LIST_ACTIVITY
 import com.example.modifier.constants.CMD_MESSAGING_APP
@@ -42,7 +39,6 @@ import com.example.modifier.data.AppPreferences
 import com.example.modifier.repo.AppPreferencesRepository
 import com.example.modifier.data.AppState
 import com.example.modifier.repo.AppStateRepository
-import com.example.modifier.data.BackupItemDao
 import com.example.modifier.repo.GoogleMessageStateRepository
 import com.example.modifier.databinding.FloatingWindowBinding
 import com.example.modifier.enums.RcsConfigureState
@@ -77,9 +73,11 @@ import com.example.modifier.utils.isRebooted
 import com.example.modifier.utils.killPhoneProcess
 import com.example.modifier.utils.optimize
 import com.example.modifier.utils.resetAll
+import com.example.modifier.utils.restartSelf
 import com.example.modifier.utils.setBatteryLevel
 import com.example.modifier.utils.shellRun
 import com.example.modifier.utils.smsIntent
+import com.example.modifier.utils.spoofSmsIntent
 import com.example.modifier.utils.stopClash
 import com.example.modifier.utils.syncTime
 import com.example.modifier.utils.uniqueId
@@ -112,7 +110,6 @@ import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withTimeout
 import kotlinx.coroutines.withTimeoutOrNull
 import kotlinx.serialization.encodeToString
-import org.apache.commons.lang3.RandomStringUtils
 import org.json.JSONException
 import org.json.JSONObject
 import java.io.File
@@ -721,7 +718,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                     }
 
                     R.id.restart_modifier -> {
-                        restartModifier()
+                        restartSelf()
                     }
 
                     R.id.reset_counter -> {
@@ -1129,7 +1126,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
 
                         val configured = run configuring@{
                             repeat(2) {
-                                Global.sendSmsIntent(sender, msg)
+                                spoofSmsIntent(sender, msg)
                                 val state =
                                     googleMessageStateRepository.waitForRcsState(
                                         arrayOf(

+ 0 - 1
app/src/main/java/com/example/modifier/ui/backup/BackupViewModel.kt

@@ -3,7 +3,6 @@ package com.example.modifier.ui.backup
 import androidx.lifecycle.SavedStateHandle
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
-import com.example.modifier.Global
 import com.example.modifier.data.BackupItem
 import com.example.modifier.data.BackupItemDao
 import kotlinx.coroutines.flow.MutableStateFlow

+ 0 - 1
app/src/main/java/com/example/modifier/ui/login/LoginActivity.kt

@@ -9,7 +9,6 @@ import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
 import androidx.lifecycle.viewModelScope
-import com.example.modifier.Global
 import com.example.modifier.R
 import com.example.modifier.Utils
 import com.example.modifier.constants.servers

+ 1 - 2
app/src/main/java/com/example/modifier/ui/settings/SettingsFragment.kt

@@ -21,7 +21,6 @@ import androidx.core.app.ActivityCompat
 import androidx.core.content.ContextCompat
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.lifecycleScope
-import com.example.modifier.Global
 import com.example.modifier.R
 import com.example.modifier.Utils
 import com.example.modifier.constants.servers
@@ -142,6 +141,7 @@ class SettingsFragment : Fragment() {
             onSave()
         }
         binding.etServer.threshold = 1000
+        binding.etServer.setSimpleItems(servers)
         binding.btnServer.setOnClickListener { v: View? ->
             val server = binding.etServer.text.toString()
             if (StringUtils.isEmpty(server)) {
@@ -152,7 +152,6 @@ class SettingsFragment : Fragment() {
                 Toast.makeText(context, "Invalid server URL", Toast.LENGTH_SHORT).show()
                 return@setOnClickListener
             }
-            binding.etServer.setSimpleItems(servers)
             lifecycleScope.launch {
                 appPreferencesRepository.updateServer(server)
                 appPreferencesRepository.updateName(binding.etDeviceLabel.text.toString())

+ 2 - 2
app/src/main/java/com/example/modifier/ui/utils/UtilsFragment.kt

@@ -10,7 +10,6 @@ import androidx.appcompat.app.AlertDialog
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.lifecycleScope
 import com.example.modifier.Frida
-import com.example.modifier.Global
 import com.example.modifier.R
 import com.example.modifier.Utils
 import com.example.modifier.constants.CMD_BACK_APP
@@ -32,6 +31,7 @@ import com.example.modifier.utils.killPhoneProcess
 import com.example.modifier.utils.resetAll
 import com.example.modifier.utils.resumePackage
 import com.example.modifier.utils.shellRun
+import com.example.modifier.utils.spoofSmsIntent
 import com.example.modifier.utils.suspendPackage
 import com.example.modifier.utils.syncTime
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -86,7 +86,7 @@ class UtilsFragment : Fragment() {
 
                 val otp = binding.etOtp.text.toString()
                 withContext(Dispatchers.IO) {
-                    Global.sendSmsIntent("3538", "Your Messenger verification code is G-$otp")
+                    spoofSmsIntent("3538", "Your Messenger verification code is G-$otp")
                 }
 
                 binding.btnSend.setIconResource(R.drawable.ic_done)

+ 13 - 2
app/src/main/java/com/example/modifier/utils/GoogleMessage.kt

@@ -6,12 +6,23 @@ import android.content.Intent
 import android.net.Uri
 import android.os.Build
 import androidx.core.content.ContextCompat
-import com.example.modifier.Global.sqlite3path
 import com.example.modifier.Utils
 import com.example.modifier.constants.PACKAGE_MESSAGING
 import com.example.modifier.constants.PACKAGE_TELEPHONY
 import java.io.File
 
+fun spoofSmsIntent(sender: String, msg: String) {
+    val intent = Intent()
+    intent.setAction("com.example.modifier.sms")
+    intent.putExtra("sender", sender)
+    intent.putExtra(
+        "message",
+        msg
+    )
+    val context = Utils.getContext()
+    context.sendBroadcast(intent)
+}
+
 fun smsIntent(to: String, body: String): Intent {
     val intent = Intent(Intent.ACTION_SENDTO)
     intent.data = Uri.parse("sms:$to")
@@ -69,7 +80,7 @@ suspend fun clearConv() {
         }
         copyToData(providerDir)
         shellRun(
-            "$sqlite3 /data/data/$PACKAGE_MESSAGING/bugle_db \"DELETE FROM conversations;\"",
+            "$sqlite3 /data/data/$PACKAGE_MESSAGING/databases/bugle_db \"DELETE FROM conversations;\"",
             "$sqlite3 /data/data/$PACKAGE_MESSAGING/databases/bugle_db \"DELETE FROM messages;\"",
             *cmds.toTypedArray(),
         )

+ 31 - 12
app/src/main/java/com/example/modifier/utils/SimInfo.kt

@@ -1,25 +1,20 @@
 package com.example.modifier.utils
 
 import org.apache.commons.lang3.RandomStringUtils
-import java.util.Arrays
 import java.util.Locale
 import kotlin.math.floor
 
 fun genIMEI(): String {
-    val str = Arrays.stream(
-        ("35684610" + RandomStringUtils.randomNumeric(7)).split("".toRegex())
-            .dropLastWhile { it.isEmpty() }
-            .toTypedArray()).mapToInt { s: String -> s.toInt() }.toArray()
+    val str = ("35684610" + RandomStringUtils.randomNumeric(7)).map { it.toString().toInt() }
+        .toIntArray()
     var sum = 0
     var t: Int
-    val len_offset: Int
     val len = 15
     var imei = ""
 
-    len_offset = (len + 1) % 2
     var pos = 0
     while (pos < len - 1) {
-        if ((pos + len_offset) % 2 != 0) {
+        if ((pos % 2) != 0) {
             t = str[pos] * 2
             if (t > 9) {
                 t -= 9
@@ -31,8 +26,8 @@ fun genIMEI(): String {
         pos++
     }
 
-    val final_digit = (10 - (sum % 10)) % 10
-    str[len - 1] = final_digit
+    val finalDigit = (10 - (sum % 10)) % 10
+    str[len - 1] = finalDigit
 
     for (d in str) {
         imei += d.toString()
@@ -105,9 +100,33 @@ fun generateIMEI1(): String {
 
 fun genICCID(mnc: String, areaCode: String): String {
     val prefix = String.format(Locale.US, "89%02d%s", areaCode.toInt(), mnc)
-    return prefix + RandomStringUtils.randomNumeric(20 - prefix.length)
+    return luhn(prefix + RandomStringUtils.randomNumeric(20 - prefix.length))
 }
 
 fun genIMSI(mccmnc: String): String {
-    return "310240" + RandomStringUtils.randomNumeric(15 - mccmnc.length)
+    return luhn(mccmnc + RandomStringUtils.randomNumeric(15 - mccmnc.length))
+}
+
+fun luhn(number: String): String {
+    if (!number.matches(Regex("[0-9]+"))) {
+        throw IllegalArgumentException("Invalid number: $number")
+    }
+    val checks = "0987654321".toCharArray()
+    val chs = number.toCharArray()
+    var count = 0
+
+    var i = chs.size - 2
+    var k = 1
+    while (i >= 0) {
+        // 偶位数字 * 2,奇位不乘
+        val num = (chs[i].code - '0'.code) shl (k and 1)
+
+        // 累加
+        count += num % 10 + num / 10
+        i--
+        k++
+    }
+
+    chs[chs.size - 1] = checks[count % 10]
+    return String(chs)
 }

+ 41 - 0
app/src/main/java/com/example/modifier/utils/System.kt

@@ -2,26 +2,34 @@ package com.example.modifier.utils
 
 import android.accessibilityservice.AccessibilityServiceInfo
 import android.annotation.SuppressLint
+import android.app.AlarmManager
+import android.app.PendingIntent
 import android.content.Context
+import android.content.Intent
 import android.content.pm.PackageManager
+import android.os.Build
 import android.provider.Settings
 import android.text.TextUtils
 import android.util.Log
 import android.view.accessibility.AccessibilityManager
 import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
 import com.example.modifier.BuildConfig
+import com.example.modifier.MainActivity
 import com.example.modifier.Utils
 import com.example.modifier.http.ktorClient
 import com.example.modifier.service.ModifierService
 import io.ktor.client.request.head
 import kotlinx.coroutines.delay
 import org.apache.commons.lang3.StringUtils
+import java.io.File
 import java.time.ZoneId
 import java.time.ZonedDateTime
 import java.time.format.DateTimeFormatter
 import java.util.Locale
 import java.util.Objects
 import java.util.UUID
+import kotlin.system.exitProcess
 
 val uniqueId: String
     @SuppressLint("HardwareIds")
@@ -229,4 +237,37 @@ suspend fun currentActivity(): String? {
     val activity = Regex("topResumedActivity=ActivityRecord\\{.*/\\.(\\S*)\\}")
         .find(out)?.groups?.get(1)?.value
     return activity
+}
+
+fun sqlite3path(): String {
+    val context = Utils.getContext()
+    val dataDir = ContextCompat.getDataDir(context)
+    val binDir = File(dataDir, "bin")
+    val dbDir = File(dataDir, "providerDB")
+    if (!binDir.exists()) {
+        Utils.copyAssetFolder(context.assets, "bin", binDir.path)
+        Utils.copyAssetFolder(context.assets, "providerDB", dbDir.path)
+        binDir.listFiles()?.forEach {
+            it.setExecutable(true)
+        }
+    }
+    Log.i("Modifier", "arch: " + Build.SUPPORTED_ABIS.joinToString(", "))
+    val file = File(dataDir, "bin/sqlite3.arm")
+    file.setExecutable(true)
+    return file.path
+}
+
+fun restartSelf() {
+    val context = Utils.getContext()
+    val mStartActivity = Intent(context, MainActivity::class.java)
+    val mPendingIntentId = 123456
+    val mPendingIntent = PendingIntent.getActivity(
+        context,
+        mPendingIntentId,
+        mStartActivity,
+        PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
+    )
+    val mgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent)
+    exitProcess(0)
 }

+ 6 - 6
app/src/test/java/com/example/modifier/ExampleUnitTest.kt

@@ -1,7 +1,9 @@
 package com.example.asdfasdfawf
 
-import com.example.modifier.Global
 import com.example.modifier.Utils
+import com.example.modifier.utils.genICCID
+import com.example.modifier.utils.genIMEI
+import com.example.modifier.utils.genIMSI
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.coroutineScope
@@ -25,10 +27,8 @@ import java.time.format.DateTimeFormatter
 class ExampleUnitTest {
     @Test
     fun test1() {
-        println(
-            Regex("topResumedActivity=ActivityRecord\\{.*/\\.(\\S*)\\}")
-                .find("    topResumedActivity=ActivityRecord{bebbd0d u0 com.google.android.apps.messaging/.ui.appsettings.RcsSettingsActivity} t2447}\n")
-                ?.groups?.get(1)?.value
-        )
+        println(genIMEI())
+        println(genICCID("240", "1"))
+        println(genIMSI("310240"))
     }
 }

+ 1 - 1
app/src/test/java/com/example/modifier/Luhn.java

@@ -38,7 +38,7 @@ public class Luhn {
 
     @Test
     public void test() {
-        assert isValidLuhn("89660166219355995276");
+        assert isValidLuhn("8901310240753595246");
 
     }
 }