Skip to content
Open
4 changes: 4 additions & 0 deletions patches/api/patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public final class app/revanced/patches/all/misc/connectivity/telephony/sim/spoo
public static final fun getSpoofSimCountryPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimProviderPatchKt {
public static final fun getSpoofSimProviderPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

public final class app/revanced/patches/all/misc/connectivity/wifi/spoof/SpoofWifiPatchKt {
public static final fun getSpoofWifiPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,105 +1,9 @@
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof

import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.stringOption
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
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.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.*

@Deprecated("Patch was renamed", ReplaceWith("spoofSimProviderPatch"))
@Suppress("unused")
val spoofSimCountryPatch = bytecodePatch(
name = "Spoof SIM country",
description = "Spoofs country information returned by the SIM card provider.",
use = false,
) {
val countries = Locale.getISOCountries().associateBy { Locale("", it).displayCountry }

fun isoCountryPatchOption(
key: String,
title: String,
) = stringOption(
key,
null,
countries,
title,
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
false,
validator = { it: String? -> it == null || it.uppercase() in countries.values },
)

val networkCountryIso by isoCountryPatchOption(
"networkCountryIso",
"Network ISO country code",
)

val simCountryIso by isoCountryPatchOption(
"simCountryIso",
"SIM ISO country code",
)

dependsOn(
transformInstructionsPatch(
filterMap = { _, _, instruction, instructionIndex ->
if (instruction !is ReferenceInstruction) return@transformInstructionsPatch null

val reference = instruction.reference as? MethodReference ?: return@transformInstructionsPatch null

val match = MethodCall.entries.firstOrNull { search ->
MethodUtil.methodSignaturesMatch(reference, search.reference)
} ?: return@transformInstructionsPatch null

val iso = when (match) {
MethodCall.NetworkCountryIso -> networkCountryIso
MethodCall.SimCountryIso -> simCountryIso
}?.lowercase()

iso?.let { instructionIndex to it }
},
transform = { mutableMethod, entry: Pair<Int, String> ->
transformMethodCall(entry, mutableMethod)
},
),
)
}

private fun transformMethodCall(
entry: Pair<Int, String>,
mutableMethod: MutableMethod,
) {
val (instructionIndex, methodCallValue) = entry

val register = mutableMethod.getInstruction<OneRegisterInstruction>(instructionIndex + 1).registerA

mutableMethod.replaceInstruction(
instructionIndex + 1,
"const-string v$register, \"$methodCallValue\"",
)
}

private enum class MethodCall(
val reference: MethodReference,
) {
NetworkCountryIso(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getNetworkCountryIso",
emptyList(),
"Ljava/lang/String;",
),
),
SimCountryIso(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getSimCountryIso",
emptyList(),
"Ljava/lang/String;",
),
),
}
val spoofSimCountryPatch = bytecodePatch {
dependsOn(spoofSimProviderPatch)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof

import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.stringOption
import app.revanced.patcher.patch.intOption
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
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.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.Locale
import java.util.regex.Pattern

@Suppress("unused")
val spoofSimProviderPatch = bytecodePatch(
name = "Spoof SIM provider",
description = "Spoofs information about the SIM card provider.",
use = false,
) {
val countries = Locale.getISOCountries().associateBy { Locale("", it).displayCountry }

fun isoCountryPatchOption(
key: String,
title: String,
) = stringOption(
key,
null,
countries,
title,
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
false,
validator = { it: String? -> it == null || it.uppercase() in countries.values },
)

fun isMccMncValid(it: Int?): Boolean =
it == null || Pattern.matches("[0-9]{5,6}", it.toString())

val networkCountryIso by isoCountryPatchOption(
"networkCountryIso",
"Network ISO country code",
)

val networkOperator by intOption(
key = "networkOperator",
title = "MCC+MNC network operator code",
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the network operator.",
validator = { isMccMncValid(it) }
)

val networkOperatorName by stringOption(
key = "networkOperatorName",
title = "Network operator name",
description = "The full name of the network operator.",
)

val simCountryIso by isoCountryPatchOption(
"simCountryIso",
"SIM ISO country code",
)

val simOperator by intOption(
key = "simOperator",
title = "MCC+MNC SIM operator code",
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the SIM operator.",
validator = { isMccMncValid(it) }
)

val simOperatorName by stringOption(
key = "simOperatorName",
title = "SIM operator name",
description = "The full name of the SIM operator.",
)


dependsOn(
transformInstructionsPatch(
filterMap = { _, _, instruction, instructionIndex ->
if (instruction !is ReferenceInstruction) return@transformInstructionsPatch null

val reference = instruction.reference as? MethodReference ?: return@transformInstructionsPatch null

val match = MethodCall.entries.firstOrNull { search ->
MethodUtil.methodSignaturesMatch(reference, search.reference)
} ?: return@transformInstructionsPatch 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
}
replacement?.let { instructionIndex to it }
},
transform = ::transformMethodCall,
),
)
}

private fun transformMethodCall(
mutableMethod: MutableMethod,
entry: Pair<Int, String>,
) {
val (instructionIndex, methodCallValue) = entry

// Get the register which would have contained the return value
val register = mutableMethod.getInstruction<OneRegisterInstruction>(instructionIndex + 1).registerA

// Replace the move-result instruction with our fake value
mutableMethod.replaceInstruction(
instructionIndex + 1,
"const-string v$register, \"$methodCallValue\"",
)
}

private enum class MethodCall(
val reference: MethodReference,
) {
NetworkCountryIso(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getNetworkCountryIso",
emptyList(),
"Ljava/lang/String;",
),
),
NetworkOperator(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getNetworkOperator",
emptyList(),
"Ljava/lang/String;",
),
),
NetworkOperatorName(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getNetworkOperatorName",
emptyList(),
"Ljava/lang/String;",
),
),
SimCountryIso(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getSimCountryIso",
emptyList(),
"Ljava/lang/String;",
),
),
SimOperator(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getSimOperator",
emptyList(),
"Ljava/lang/String;",
),
),
SimOperatorName(
ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;",
"getSimOperatorName",
emptyList(),
"Ljava/lang/String;",
),
),
}
Loading