From 8fd929e9911d70e56cca28ebd7dd033545af9627 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Sat, 30 Sep 2023 01:36:12 +0900 Subject: [PATCH] fix(youtube/spoof-player-parameters): fix some side effects --- ...yerResponseModelImplGeneralFingerprint.kt} | 2 +- ...rResponseModelImplLiveStreamFingerprint.kt | 23 +++++ .../StoryboardRendererSpecFingerprint.kt | 2 + ...RendererSpecRecommendedLevelFingerprint.kt | 15 ++++ .../patch/SpoofPlayerParameterPatch.kt | 87 +++++++++++++------ .../youtube/settings/host/values/strings.xml | 4 +- 6 files changed, 103 insertions(+), 30 deletions(-) rename src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/{PlayerResponseModelImplFingerprint.kt => PlayerResponseModelImplGeneralFingerprint.kt} (91%) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplLiveStreamFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StoryboardRendererSpecRecommendedLevelFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplGeneralFingerprint.kt similarity index 91% rename from src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplGeneralFingerprint.kt index 7f9bd3a90..7f07676ca 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplGeneralFingerprint.kt @@ -6,7 +6,7 @@ import app.revanced.util.bytecode.isWideLiteralExists import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -object PlayerResponseModelImplFingerprint : MethodFingerprint( +object PlayerResponseModelImplGeneralFingerprint : MethodFingerprint( returnType = "Ljava/lang/String;", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = emptyList(), diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplLiveStreamFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplLiveStreamFingerprint.kt new file mode 100644 index 000000000..d2f67cecc --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/PlayerResponseModelImplLiveStreamFingerprint.kt @@ -0,0 +1,23 @@ +package app.revanced.patches.youtube.utils.fix.parameter.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.util.bytecode.isWideLiteralExists +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +object PlayerResponseModelImplLiveStreamFingerprint : MethodFingerprint( + returnType = "Ljava/lang/String;", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = emptyList(), + opcodes = listOf( + Opcode.RETURN_OBJECT, + Opcode.CONST_4, + Opcode.RETURN_OBJECT + ), + customFingerprint = { methodDef, _ -> + methodDef.definingClass.endsWith("/PlayerResponseModelImpl;") && methodDef.isWideLiteralExists( + 70276274 + ) + } +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StoryboardRendererSpecFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StoryboardRendererSpecFingerprint.kt index 22f944c31..8a582810c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StoryboardRendererSpecFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StoryboardRendererSpecFingerprint.kt @@ -3,10 +3,12 @@ package app.revanced.patches.youtube.utils.fix.parameter.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode object StoryboardRendererSpecFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, returnType = "L", parameters = listOf("Ljava/lang/String;", "J"), + opcodes = listOf(Opcode.IF_EQZ), strings = listOf("\\|"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StoryboardRendererSpecRecommendedLevelFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StoryboardRendererSpecRecommendedLevelFingerprint.kt new file mode 100644 index 000000000..68e858f5a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StoryboardRendererSpecRecommendedLevelFingerprint.kt @@ -0,0 +1,15 @@ +package app.revanced.patches.youtube.utils.fix.parameter.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +object StoryboardRendererSpecRecommendedLevelFingerprint : MethodFingerprint( + strings = listOf("#-1#"), + opcodes = listOf( + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT + ) +) diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/patch/SpoofPlayerParameterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/patch/SpoofPlayerParameterPatch.kt index 7e991cc54..d4276d4fd 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/patch/SpoofPlayerParameterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/patch/SpoofPlayerParameterPatch.kt @@ -15,25 +15,35 @@ import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerParameterBuilderFingerprint -import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerResponseModelImplFingerprint +import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerResponseModelImplGeneralFingerprint +import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerResponseModelImplLiveStreamFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardRendererSpecFingerprint +import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardRendererSpecRecommendedLevelFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailParentFingerprint import app.revanced.patches.youtube.utils.playertype.patch.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch import app.revanced.util.integrations.Constants.MISC_PATH +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch @Name("Spoof player parameters") @Description("Spoofs player parameters to prevent playback issues.") -@DependsOn([PlayerTypeHookPatch::class]) +@DependsOn( + [ + PlayerTypeHookPatch::class, + SettingsPatch::class + ] +) @YouTubeCompatibility class SpoofPlayerParameterPatch : BytecodePatch( listOf( PlayerParameterBuilderFingerprint, - PlayerResponseModelImplFingerprint, + PlayerResponseModelImplGeneralFingerprint, + PlayerResponseModelImplLiveStreamFingerprint, StoryboardRendererSpecFingerprint, + StoryboardRendererSpecRecommendedLevelFingerprint, StoryboardThumbnailParentFingerprint ) ) { @@ -88,37 +98,60 @@ class SpoofPlayerParameterPatch : BytecodePatch( /** * Hook StoryBoard Renderer URL - * TODO: Find a way to increase the quality of SeekBar thumbnail previews */ - PlayerResponseModelImplFingerprint.result?.let { + arrayOf( + PlayerResponseModelImplGeneralFingerprint, + PlayerResponseModelImplLiveStreamFingerprint, + StoryboardRendererSpecFingerprint + ).forEach { fingerprint -> + fingerprint.result?.let { + it.mutableMethod.apply { + val getStoryBoardIndex = it.scanResult.patternScanResult!!.endIndex + val getStoryBoardRegister = + getInstruction(getStoryBoardIndex).registerA + + addInstructionsWithLabels( + getStoryBoardIndex, """ + if-nez v$getStoryBoardRegister, :ignore + invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec()Ljava/lang/String; + move-result-object v$getStoryBoardRegister + """, ExternalLabel("ignore", getInstruction(getStoryBoardIndex)) + ) + } + } ?: throw fingerprint.exception + } + + /** + * Hook recommended value and StoryBoard Renderer for live stream + */ + StoryboardRendererSpecRecommendedLevelFingerprint.result?.let { it.mutableMethod.apply { - val getStoryBoardIndex = it.scanResult.patternScanResult!!.endIndex - val getStoryBoardRegister = - getInstruction(getStoryBoardIndex).registerA + val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex + val originalValueRegister = + getInstruction(moveOriginalRecommendedValueIndex).registerA + + val liveStreamStoryBoardUrlIndex = + implementation!!.instructions.indexOfFirst { instruction -> + instruction.opcode == Opcode.INVOKE_INTERFACE + } + 1 + val liveStreamStoryBoardUrlRegister = + getInstruction(liveStreamStoryBoardUrlIndex).registerA addInstructions( - getStoryBoardIndex, """ - invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec()Ljava/lang/String; - move-result-object v$getStoryBoardRegister + moveOriginalRecommendedValueIndex + 1, """ + invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I + move-result v$originalValueRegister + """ + ) + + addInstructions( + liveStreamStoryBoardUrlIndex + 1, """ + invoke-static { v$liveStreamStoryBoardUrlRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$liveStreamStoryBoardUrlRegister """ ) } - } ?: throw PlayerResponseModelImplFingerprint.exception - - StoryboardRendererSpecFingerprint.result?.let { - it.mutableMethod.apply { - val storyBoardUrlParams = 0 - - addInstructionsWithLabels( - 0, """ - if-nez p$storyBoardUrlParams, :ignore - invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec()Ljava/lang/String; - move-result-object p$storyBoardUrlParams - """, ExternalLabel("ignore", getInstruction(0)) - ) - } - } ?: throw StoryboardRendererSpecFingerprint.exception - + } ?: throw StoryboardRendererSpecRecommendedLevelFingerprint.exception /** * Add settings diff --git a/src/main/resources/youtube/settings/host/values/strings.xml b/src/main/resources/youtube/settings/host/values/strings.xml index adc359817..5ed6707d6 100644 --- a/src/main/resources/youtube/settings/host/values/strings.xml +++ b/src/main/resources/youtube/settings/host/values/strings.xml @@ -639,8 +639,8 @@ If later turned off, the old UI may remain until clear the app data" Known issues • Enhanced bitrate is not available -• Offline downloads may not work -• SeekBar thumbnail preview quality is very low" +• No seekbar thumbnails for paid videos +• Offline downloads may not work" Spoof player parameter Swipe controls The amount of threshold for swipe to occur