feat(Universal): Add IMEI option for Spoof SIM Provider

This commit is contained in:
secp192k1 2026-03-09 02:33:27 +00:00
parent ae7a150629
commit ecf67bdaec

View file

@ -6,7 +6,7 @@ import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.intOption import app.revanced.patcher.patch.intOption
import app.revanced.patcher.patch.stringOption import app.revanced.patcher.patch.stringOption
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch import app.revanced.util.forEachInstructionAsSequence
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@ -34,6 +34,7 @@ val spoofSIMProviderPatch = bytecodePatch(
) )
fun isMccMncValid(it: Int?): Boolean = it == null || (it >= 10000 && it <= 999999) fun isMccMncValid(it: Int?): Boolean = it == null || (it >= 10000 && it <= 999999)
fun isImeiValid(it: String?): Boolean = it.isNullOrBlank() || it.equals("random", ignoreCase = true) || it.length == 15
val networkCountryIso by isoCountryPatchOption("Network ISO country code") val networkCountryIso by isoCountryPatchOption("Network ISO country code")
@ -61,29 +62,62 @@ val spoofSIMProviderPatch = bytecodePatch(
description = "The full name of the SIM operator.", description = "The full name of the SIM operator.",
) )
val imei by stringOption(
name = "IMEI value",
description = "Enter a 15-digit IMEI to spoof, leave blank to skip, or type 'random' to generate a valid random IMEI.",
validator = { isImeiValid(it) }
)
dependsOn( dependsOn(
transformInstructionsPatch( bytecodePatch {
filterMap = { _, _, instruction, instructionIndex -> apply {
if (instruction !is ReferenceInstruction) return@transformInstructionsPatch null val computedImei = if (imei.isNullOrBlank()) {
null
val reference = instruction.reference as? MethodReference ?: return@transformInstructionsPatch null } else if (imei?.equals("random", ignoreCase = true) == true) {
val prefix = "86" + (1..12).map { ('0'..'9').random() }.joinToString("")
val match = MethodCall.entries.firstOrNull { search -> var sum = 0
MethodUtil.methodSignaturesMatch(reference, search.reference) for (i in prefix.indices) {
} ?: return@transformInstructionsPatch null var d = prefix[i] - '0'
if (i % 2 != 0) {
val replacement = when (match) { d *= 2
MethodCall.NetworkCountryIso -> networkCountryIso?.lowercase() if (d > 9) d -= 9
MethodCall.NetworkOperator -> networkOperator?.toString() }
MethodCall.NetworkOperatorName -> networkOperatorName sum += d
MethodCall.SimCountryIso -> simCountryIso?.lowercase() }
MethodCall.SimOperator -> simOperator?.toString() val checkDigit = (10 - (sum % 10)) % 10
MethodCall.SimOperatorName -> simOperatorName prefix + checkDigit
} else {
imei
} }
replacement?.let { instructionIndex to it }
}, forEachInstructionAsSequence(
transform = ::transformMethodCall, match = { _, _, instruction, instructionIndex ->
), if (instruction !is ReferenceInstruction) return@forEachInstructionAsSequence null
val reference = instruction.reference as? MethodReference ?: return@forEachInstructionAsSequence null
val match = MethodCall.entries.firstOrNull { search ->
MethodUtil.methodSignaturesMatch(reference, search.reference)
} ?: return@forEachInstructionAsSequence null
val replacement = when (match) {
MethodCall.NetworkCountryIso -> networkCountryIso?.lowercase()
MethodCall.NetworkOperator -> networkOperator?.toString()
MethodCall.NetworkOperatorName -> networkOperatorName
MethodCall.SimCountryIso -> simCountryIso?.lowercase()
MethodCall.SimOperator -> simOperator?.toString()
MethodCall.SimOperatorName -> simOperatorName
MethodCall.Imei,
MethodCall.ImeiWithSlot,
MethodCall.DeviceId,
MethodCall.DeviceIdWithSlot -> computedImei
}
replacement?.let { instructionIndex to it }
},
transform = ::transformMethodCall
)
}
},
) )
} }
@ -154,4 +188,36 @@ private enum class MethodCall(
"Ljava/lang/String;", "Ljava/lang/String;",
), ),
), ),
Imei(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getImei",
emptyList(),
"Ljava/lang/String;"
),
),
ImeiWithSlot(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getImei",
listOf("I"),
"Ljava/lang/String;"
),
),
DeviceId(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getDeviceId",
emptyList(),
"Ljava/lang/String;"
),
),
DeviceIdWithSlot(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getDeviceId",
listOf("I"),
"Ljava/lang/String;"
),
),
} }