From 65bb867bd23d9602048f7324575876b900f115f5 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Thu, 23 May 2024 01:10:09 +0900 Subject: [PATCH] feat(YouTube): remove `Spoof format stream data` patch --- .../SpoofFormatStreamDataPatch.kt | 234 ------------------ .../EndpointUrlBuilderFingerprint.kt | 35 --- ...FormatStreamModelConstructorFingerprint.kt | 30 --- .../PlaybackStartConstructorFingerprint.kt | 18 -- .../PlaybackStartParentFingerprint.kt | 13 - .../youtube/settings/host/values/strings.xml | 7 - .../youtube/settings/xml/revanced_prefs.xml | 4 - 7 files changed, 341 deletions(-) delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/SpoofFormatStreamDataPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/EndpointUrlBuilderFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/FormatStreamModelConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/PlaybackStartConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/PlaybackStartParentFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/SpoofFormatStreamDataPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/SpoofFormatStreamDataPatch.kt deleted file mode 100644 index 40e493de8..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/SpoofFormatStreamDataPatch.kt +++ /dev/null @@ -1,234 +0,0 @@ -package app.revanced.patches.youtube.utils.fix.formatstream - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.youtube.utils.compatibility.Constants -import app.revanced.patches.youtube.utils.fix.formatstream.fingerprints.EndpointUrlBuilderFingerprint -import app.revanced.patches.youtube.utils.fix.formatstream.fingerprints.FormatStreamModelConstructorFingerprint -import app.revanced.patches.youtube.utils.fix.formatstream.fingerprints.PlaybackStartConstructorFingerprint -import app.revanced.patches.youtube.utils.fix.formatstream.fingerprints.PlaybackStartParentFingerprint -import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH -import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.patches.youtube.video.information.VideoInformationPatch -import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndex -import app.revanced.util.getWalkerMethod -import app.revanced.util.indexOfFirstInstruction -import app.revanced.util.patch.BaseBytecodePatch -import app.revanced.util.resultOrThrow -import com.android.tools.smali.dexlib2.Opcode -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.TwoRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.FieldReference -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.iface.reference.Reference - -@Suppress("unused") -object SpoofFormatStreamDataPatch : BaseBytecodePatch( - name = "Spoof format stream data", - description = "Adds an option to spoof the format stream data to prevent playback issues.", - dependencies = setOf( - SettingsPatch::class, - VideoInformationPatch::class, - ), - compatiblePackages = Constants.COMPATIBLE_PACKAGE, - fingerprints = setOf( - EndpointUrlBuilderFingerprint, - FormatStreamModelConstructorFingerprint, - PlaybackStartParentFingerprint - ) -) { - private const val INTEGRATIONS_CLASS_DESCRIPTOR = - "$MISC_PATH/SpoofFormatStreamDataPatch;" - - private const val INTEGRATIONS_METHOD_DESCRIPTOR = - "hookStreamData" - - private const val INTEGRATIONS_METHOD_CALL = - INTEGRATIONS_CLASS_DESCRIPTOR + - "->" + - INTEGRATIONS_METHOD_DESCRIPTOR + - "(Ljava/lang/Object;)V" - - private const val STREAMING_DATA_OUTER_CLASS = - "Lcom/google/protos/youtube/api/innertube/StreamingDataOuterClass\$StreamingData;" - - private lateinit var hookMethod: MutableMethod - private lateinit var uriMethod: MutableMethod - - private fun MutableMethod.replaceFieldName( - index: Int, - replaceFieldString: String - ) { - val reference = getInstruction(index).reference - val fieldName = (reference as FieldReference).name - - hookMethod.apply { - val stringIndex = getStringInstructionIndex(replaceFieldString) - val stringRegister = getInstruction(stringIndex).registerA - - replaceInstruction( - stringIndex, - "const-string v$stringRegister, \"$fieldName\"" - ) - } - } - - override fun execute(context: BytecodeContext) { - - // region set field name - - hookMethod = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!! - .mutableClass.methods.find { method -> method.name == INTEGRATIONS_METHOD_DESCRIPTOR } - ?: throw PatchException("SpoofFormatStreamDataPatch not found") - - FormatStreamModelConstructorFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - // Find the field name that will be used for reflection. - val urlIndex = it.scanResult.patternScanResult!!.startIndex - val itagIndex = getTargetIndex(urlIndex + 1, Opcode.IGET) - - replaceFieldName(urlIndex, "replaceMeWithUrlFieldName") - replaceFieldName(itagIndex, "replaceMeWithITagFieldName") - } - - it.mutableClass.methods.find { method -> - method.parameters == listOf("Ljava/lang/String;") - && method.returnType == "Landroid/net/Uri;" - }?.apply { - val walkerIndex = indexOfFirstInstruction { - opcode == Opcode.INVOKE_VIRTUAL - && getReference()?.returnType == "Landroid/net/Uri;" - } - uriMethod = getWalkerMethod(context, walkerIndex) - } ?: throw PatchException("Uri method not found") - } - - // endregion - - // region set protobufList reference - - lateinit var nonDashProtobufListReference: Reference - lateinit var dashProtobufListReference: Reference - - val streamingDataOutClassConstructorMethod = context.findClass(STREAMING_DATA_OUTER_CLASS)!! - .mutableClass.methods.find { method -> method.name == "" } - ?: throw PatchException("StreamingDataOutClass not found") - - streamingDataOutClassConstructorMethod.apply { - val protobufListIndex = indexOfFirstInstruction { - opcode == Opcode.INVOKE_STATIC - && getReference()?.definingClass == STREAMING_DATA_OUTER_CLASS - && getReference()?.name == "emptyProtobufList" - } - if (protobufListIndex <= 0) - throw PatchException("ProtobufList index not found") - - val protobufListReference = getInstruction(protobufListIndex).reference - val protobufListClass = (protobufListReference as MethodReference).returnType - - val protobufListCalls = implementation!!.instructions.withIndex() - .filter { instruction -> - ((instruction.value as? ReferenceInstruction)?.reference as? FieldReference)?.type == protobufListClass - } - - nonDashProtobufListReference = - getInstruction(protobufListCalls.elementAt(0).index).reference - dashProtobufListReference = - getInstruction(protobufListCalls.elementAt(1).index).reference - } - - // endregion - - // region hook stream data - - PlaybackStartConstructorFingerprint.resolve( - context, - PlaybackStartParentFingerprint.resultOrThrow().classDef - ) - PlaybackStartConstructorFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val streamingDataOuterClassIndex = it.scanResult.patternScanResult!!.startIndex + 1 - val streamingDataOuterClassReference = getInstruction(streamingDataOuterClassIndex).reference - if (!streamingDataOuterClassReference.toString().endsWith(STREAMING_DATA_OUTER_CLASS)) - throw PatchException("Type does not match: $streamingDataOuterClassReference") - - val insertIndex = streamingDataOuterClassIndex + 1 - val streamingDataOuterClassRegister = getInstruction(streamingDataOuterClassIndex).registerA - val freeRegister = implementation!!.registerCount - parameters.size - 2 - - addInstructionsWithLabels( - insertIndex, - """ - if-eqz v$streamingDataOuterClassRegister, :ignore - iget-object v$freeRegister, v$streamingDataOuterClassRegister, $nonDashProtobufListReference - invoke-static { v$freeRegister }, $INTEGRATIONS_METHOD_CALL - iget-object v$freeRegister, v$streamingDataOuterClassRegister, $dashProtobufListReference - invoke-static { v$freeRegister }, $INTEGRATIONS_METHOD_CALL - """, ExternalLabel("ignore", getInstruction(insertIndex)) - ) - } - } - - uriMethod.apply { - val insertIndex = implementation!!.instructions.size - 1 - val insertRegister = getInstruction(insertIndex).registerA - - addInstructions( - insertIndex, """ - invoke-static { v$insertRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->hookUri(Landroid/net/Uri;)Landroid/net/Uri; - move-result-object v$insertRegister - """ - ) - } - - // endregion - - // region hook endpoint url - - EndpointUrlBuilderFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val uriIndex = indexOfFirstInstruction { - opcode == Opcode.INVOKE_VIRTUAL - && getReference()?.definingClass == "Landroid/net/Uri;" - && getReference()?.name == "toString" - } - val uriStringIndex = getTargetIndex(uriIndex, Opcode.IPUT_OBJECT) - val uriStringReference = getInstruction(uriStringIndex).reference - - it.mutableClass.methods.find { method -> - method.parameters == listOf("Lcom/google/protobuf/MessageLite;") - && method.returnType == "V" - }?.addInstructions( - 0, - """ - iget-object v0, p0, $uriStringReference - invoke-static { v0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->newEndpointUrlResponse(Ljava/lang/String;)V - """ - ) ?: throw PatchException("PlaybackStart method not found") - } - } - - // endregion - - /** - * Add settings - */ - SettingsPatch.addPreference( - arrayOf( - "PREFERENCE_CATEGORY: MISC_EXPERIMENTAL_FLAGS", - "SETTINGS: SPOOF_FORMAT_STREAM_DATA" - ) - ) - - SettingsPatch.updatePatchStatus(this) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/EndpointUrlBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/EndpointUrlBuilderFingerprint.kt deleted file mode 100644 index 476358f5b..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/EndpointUrlBuilderFingerprint.kt +++ /dev/null @@ -1,35 +0,0 @@ -package app.revanced.patches.youtube.utils.fix.formatstream.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patches.youtube.utils.fix.formatstream.fingerprints.EndpointUrlBuilderFingerprint.indexOfToStringInstruction -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -internal object EndpointUrlBuilderFingerprint : MethodFingerprint( - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.DECLARED_SYNCHRONIZED, - returnType = "Ljava/lang/String;", - parameters = emptyList(), - opcodes = listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, // Uri.toString() - Opcode.MOVE_RESULT_OBJECT, - ), - strings = listOf("asig"), - customFingerprint = { methodDef, _ -> - indexOfToStringInstruction(methodDef) >= 0 - } -) { - fun indexOfToStringInstruction(methodDef: Method) = - methodDef.indexOfFirstInstruction { - opcode == Opcode.INVOKE_VIRTUAL - && getReference()?.definingClass == "Landroid/net/Uri;" - && getReference()?.name == "toString" - } -} - diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/FormatStreamModelConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/FormatStreamModelConstructorFingerprint.kt deleted file mode 100644 index 732028a31..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/FormatStreamModelConstructorFingerprint.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.utils.fix.formatstream.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.patches.youtube.utils.fix.formatstream.fingerprints.FormatStreamModelConstructorFingerprint.indexOfParseInstruction -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -internal object FormatStreamModelConstructorFingerprint : MethodFingerprint( - accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - returnType = "V", - opcodes = listOf( - Opcode.IGET_OBJECT, // get formatStreamData - Opcode.INVOKE_STATIC // Uri.parse(String formatStreamData) - ), - customFingerprint = { methodDef, classDef -> - classDef.type == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;" && - indexOfParseInstruction(methodDef) >= 0 - } -) { - fun indexOfParseInstruction(methodDef: Method) = - methodDef.indexOfFirstInstruction { - opcode == Opcode.INVOKE_STATIC && getReference()?.name == "parse" - } -} - diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/PlaybackStartConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/PlaybackStartConstructorFingerprint.kt deleted file mode 100644 index 4a6191c43..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/PlaybackStartConstructorFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.utils.fix.formatstream.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -internal object PlaybackStartConstructorFingerprint : MethodFingerprint( - returnType = "V", - accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - parameters = listOf("L"), - opcodes = listOf( - Opcode.IPUT, - Opcode.IGET_OBJECT, // type: Lcom/google/protos/youtube/api/innertube/StreamingDataOuterClass$StreamingData; - Opcode.IF_NEZ - ), -) - diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/PlaybackStartParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/PlaybackStartParentFingerprint.kt deleted file mode 100644 index 63dbd1802..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/formatstream/fingerprints/PlaybackStartParentFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.utils.fix.formatstream.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -internal object PlaybackStartParentFingerprint : MethodFingerprint( - returnType = "Lcom/google/android/libraries/youtube/innertube/model/media/VideoStreamingData;", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = emptyList(), - strings = listOf("Invalid playback type; streaming data is not playable"), -) - diff --git a/src/main/resources/youtube/settings/host/values/strings.xml b/src/main/resources/youtube/settings/host/values/strings.xml index 4c7447ae4..39a0dc50d 100644 --- a/src/main/resources/youtube/settings/host/values/strings.xml +++ b/src/main/resources/youtube/settings/host/values/strings.xml @@ -1396,13 +1396,6 @@ Tap on the continue button and disable battery optimizations." Removes tracking query parameters from the URLs when sharing links. Disable QUIC protocol "Disable CronetEngine's QUIC protocol." - Spoof format stream data - "Spoofs the format stream data to prevent playback issues. - -Limitations: -• There may be about 5 seconds of buffering when videos start. -• If buffering takes too long, you may need to close and reopen the video. -• Since this is still under development, there may be other unknown issues." Spoof player parameter "Spoofs player parameters to prevent playback issues. diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml index 67d119516..d271b8ae8 100644 --- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -562,9 +562,6 @@ - - @@ -644,7 +641,6 @@ -