From 7fe0a5b912ae368f27b72695bc20111e5aa0cbb6 Mon Sep 17 00:00:00 2001 From: d4rkk3y <43563783+d4rkk3y@users.noreply.github.com> Date: Fri, 25 Nov 2022 17:20:04 +0700 Subject: [PATCH] feat(tiktok): `sim-spoof` patch (#1088) Co-authored-by: oSumAtrIX --- .../app/revanced/extensions/Extensions.kt | 25 ++-- .../sim/annotations/SpoofSimCompatibility.kt | 14 +++ .../misc/spoof/sim/patch/SpoofSimPatch.kt | 110 ++++++++++++++++++ .../general/bytecode/patch/GeneralAdsPatch.kt | 17 +-- 4 files changed, 137 insertions(+), 29 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt diff --git a/src/main/kotlin/app/revanced/extensions/Extensions.kt b/src/main/kotlin/app/revanced/extensions/Extensions.kt index 0095dc4c8..047b0309a 100644 --- a/src/main/kotlin/app/revanced/extensions/Extensions.kt +++ b/src/main/kotlin/app/revanced/extensions/Extensions.kt @@ -1,22 +1,21 @@ package app.revanced.extensions import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patcher.util.smali.toInstruction -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.MutableMethodImplementation -import org.jf.dexlib2.builder.instruction.BuilderInstruction11n -import org.jf.dexlib2.builder.instruction.BuilderInstruction11x -import org.jf.dexlib2.builder.instruction.BuilderInstruction21t -import org.jf.dexlib2.builder.instruction.BuilderInstruction35c -import org.jf.dexlib2.immutable.reference.ImmutableMethodReference +import org.jf.dexlib2.iface.Method +import org.jf.dexlib2.util.MethodUtil import org.w3c.dom.Node -import java.nio.file.Files + +/** + * Find the [MutableMethod] from a given [Method] in a [MutableClass]. + * + * @param method The [Method] to find. + * @return The [MutableMethod]. + */ +fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first { + MethodUtil.methodSignaturesMatch(it, method) +} /** * traverse the class hierarchy starting from the given root class diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt new file mode 100644 index 000000000..a775e5c13 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/annotations/SpoofSimCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.tiktok.misc.spoof.sim.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [ + Package("com.ss.android.ugc.trill"), + Package("com.zhiliaoapp.musically") + ] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class SpoofSimCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt new file mode 100644 index 000000000..1b6a5485d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/spoof/sim/patch/SpoofSimPatch.kt @@ -0,0 +1,110 @@ +package app.revanced.patches.tiktok.misc.spoof.sim.patch + +import app.revanced.extensions.findMutableMethodOf +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.instruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.tiktok.misc.integrations.patch.TikTokIntegrationsPatch +import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint +import app.revanced.patches.tiktok.misc.settings.patch.TikTokSettingsPatch +import app.revanced.patches.tiktok.misc.spoof.sim.annotations.SpoofSimCompatibility +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction +import org.jf.dexlib2.iface.instruction.formats.Instruction35c +import org.jf.dexlib2.iface.reference.MethodReference + +@Patch(false) +@DependsOn([TikTokIntegrationsPatch::class, TikTokSettingsPatch::class]) +@Name("sim-spoof") +@Description("Spoofs the information which is retrieved from the sim-card.") +@SpoofSimCompatibility +@Version("0.0.1") +class SpoofSimPatch : BytecodePatch() { + private companion object { + val replacements = hashMapOf( + "getSimCountryIso" to "getCountryIso", + "getNetworkCountryIso" to "getCountryIso", + "getSimOperator" to "getOperator", + "getNetworkOperator" to "getOperator", + "getSimOperatorName" to "getOperatorName", + "getNetworkOperatorName" to "getOperatorName" + ) + } + + override fun execute(context: BytecodeContext): PatchResult { + // Find all api call to check sim information + buildMap { + context.classes.forEach { classDef -> + classDef.methods.let { methods -> + buildMap methodList@{ + methods.forEach methods@{ method -> + with(method.implementation?.instructions ?: return@methods) { + ArrayDeque>().also { patchIndices -> + this.forEachIndexed { index, instruction -> + if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed + + val methodRef = + (instruction as Instruction35c).reference as MethodReference + if (methodRef.definingClass != "Landroid/telephony/TelephonyManager;") return@forEachIndexed + + replacements[methodRef.name]?.let { replacement -> + patchIndices.add(index to replacement) + } + } + }.also { if (it.isEmpty()) return@methods }.let { patches -> + put(method, patches) + } + } + } + } + }.also { if (it.isEmpty()) return@forEach }.let { methodPatches -> + put(classDef, methodPatches) + } + } + }.forEach { (classDef, methods) -> + with(context.proxy(classDef).mutableClass) { + methods.forEach { (method, patches) -> + with(findMutableMethodOf(method)) { + while (!patches.isEmpty()) { + val (index, replacement) = patches.removeLast() + replaceReference(index, replacement) + } + } + } + } + } + + // Enable patch in settings + with(SettingsStatusLoadFingerprint.result!!.mutableMethod) { + addInstruction( + 0, + "invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableSimSpoof()V" + ) + } + + return PatchResultSuccess() + } + + // Patch Android API and return fake sim information + private fun MutableMethod.replaceReference(index: Int, replacement: String) { + val resultReg = (instruction(index + 1) as OneRegisterInstruction).registerA + + addInstructions( + index + 2, + """ + invoke-static {v$resultReg}, Lapp/revanced/tiktok/spoof/sim/SpoofSimPatch;->$replacement(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$resultReg + """ + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt index cc9562bb7..343a31811 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralAdsPatch.kt @@ -1,28 +1,25 @@ package app.revanced.patches.youtube.ad.general.bytecode.patch +import app.revanced.extensions.findMutableMethodOf import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.extensions.softCompareTo import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility import app.revanced.patches.youtube.ad.general.bytecode.fingerprints.ReelConstructorFingerprint import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch -import org.jf.dexlib2.iface.Method import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction import org.jf.dexlib2.iface.instruction.formats.Instruction31i import org.jf.dexlib2.iface.instruction.formats.Instruction35c -import org.jf.dexlib2.immutable.reference.ImmutableMethodReference import java.util.* @@ -35,18 +32,6 @@ import java.util.* class GeneralAdsPatch : BytecodePatch( listOf(ReelConstructorFingerprint) ) { - internal companion object { - private fun MutableClass.findMutableMethodOf( - method: Method - ) = this.methods.first { - it.softCompareTo( - ImmutableMethodReference( - method.definingClass, method.name, method.parameters, method.returnType - ) - ) - } - } - override fun execute(context: BytecodeContext): PatchResult { fun String.buildHideCall(viewRegister: Int) = "invoke-static { v$viewRegister }, " + "Lapp/revanced/integrations/patches/GeneralAdsPatch;" +