feat(tiktok): sim-spoof patch (#1088)

Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
d4rkk3y 2022-11-25 17:20:04 +07:00 committed by GitHub
parent b29459eb48
commit 7fe0a5b912
4 changed files with 137 additions and 29 deletions

View File

@ -1,22 +1,21 @@
package app.revanced.extensions package app.revanced.extensions
import app.revanced.patcher.data.BytecodeContext 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.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.toInstruction import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.util.MethodUtil
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.w3c.dom.Node 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 * traverse the class hierarchy starting from the given root class

View File

@ -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

View File

@ -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<Pair<Int, String>>().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
"""
)
}
}

View File

@ -1,28 +1,25 @@
package app.revanced.patches.youtube.ad.general.bytecode.patch 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.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instruction import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.extensions.softCompareTo
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch 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.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility 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.bytecode.fingerprints.ReelConstructorFingerprint
import app.revanced.patches.youtube.ad.general.resource.patch.GeneralAdsResourcePatch 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.TwoRegisterInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction31i import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.instruction.formats.Instruction35c import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
import java.util.* import java.util.*
@ -35,18 +32,6 @@ import java.util.*
class GeneralAdsPatch : BytecodePatch( class GeneralAdsPatch : BytecodePatch(
listOf(ReelConstructorFingerprint) 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 { override fun execute(context: BytecodeContext): PatchResult {
fun String.buildHideCall(viewRegister: Int) = "invoke-static { v$viewRegister }, " + fun String.buildHideCall(viewRegister: Int) = "invoke-static { v$viewRegister }, " +
"Lapp/revanced/integrations/patches/GeneralAdsPatch;" + "Lapp/revanced/integrations/patches/GeneralAdsPatch;" +