From 79897a163f08227582a2342e4806724cc16227b3 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:16:54 +0900 Subject: [PATCH] fix(YouTube/Spoof player parameters): fix player tracking such as history or video watchtime --- .../parameter/SpoofPlayerParameterPatch.kt | 37 +++++++++++++++++++ .../fingerprints/ParamsMapPutFingerprint.kt | 24 ++++++++++++ .../StatsQueryParameterFingerprint.kt | 7 ++++ 3 files changed, 68 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/ParamsMapPutFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StatsQueryParameterFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/SpoofPlayerParameterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/SpoofPlayerParameterPatch.kt index f3818291c..a8f1aa93b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/SpoofPlayerParameterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/SpoofPlayerParameterPatch.kt @@ -5,13 +5,16 @@ 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.removeInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel +import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.ParamsMapPutFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerResponseModelGeneralStoryboardRendererFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerResponseModelLiveStreamStoryboardRendererFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerResponseModelStoryboardRecommendedLevelFingerprint +import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StatsQueryParameterFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardRendererDecoderRecommendedLevelFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardRendererDecoderSpecFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardRendererSpecFingerprint @@ -24,6 +27,7 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @Patch( name = "Spoof player parameters", @@ -68,9 +72,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction ) object SpoofPlayerParameterPatch : BytecodePatch( setOf( + ParamsMapPutFingerprint, PlayerResponseModelGeneralStoryboardRendererFingerprint, PlayerResponseModelLiveStreamStoryboardRendererFingerprint, PlayerResponseModelStoryboardRecommendedLevelFingerprint, + StatsQueryParameterFingerprint, StoryboardRendererDecoderRecommendedLevelFingerprint, StoryboardRendererDecoderSpecFingerprint, StoryboardRendererSpecFingerprint, @@ -198,6 +204,37 @@ object SpoofPlayerParameterPatch : BytecodePatch( ) } ?: throw StoryboardRendererDecoderSpecFingerprint.exception + // Fix stats not being tracked. + // Due to signature spoofing "adformat" is present in query parameters made for /stats requests, + // even though, for regular videos, it should not be. + // This breaks stats tracking. + // Replace the ad parameter with the video parameter in the query parameters. + StatsQueryParameterFingerprint.result?.let { + val putMethod = ParamsMapPutFingerprint.result?.method?.toString() + ?: throw ParamsMapPutFingerprint.exception + + it.mutableMethod.apply { + val adParamIndex = it.scanResult.stringsScanResult!!.matches.first().index + val videoParamIndex = adParamIndex + 3 + + // Replace the ad parameter with the video parameter. + replaceInstruction(adParamIndex, getInstruction(videoParamIndex)) + + // Call paramsMap.put instead of paramsMap.putIfNotExist + // because the key is already present in the map. + val putAdParamIndex = adParamIndex + 1 + val putIfKeyNotExistsInstruction = getInstruction(putAdParamIndex) + replaceInstruction( + putAdParamIndex, + "invoke-virtual { " + + "v${putIfKeyNotExistsInstruction.registerC}, " + + "v${putIfKeyNotExistsInstruction.registerD}, " + + "v${putIfKeyNotExistsInstruction.registerE} }, " + + putMethod, + ) + } + } ?: throw StatsQueryParameterFingerprint.exception + /** * Add settings */ diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/ParamsMapPutFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/ParamsMapPutFingerprint.kt new file mode 100644 index 000000000..8c8e0711a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/ParamsMapPutFingerprint.kt @@ -0,0 +1,24 @@ +package app.revanced.patches.youtube.utils.fix.parameter.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 ParamsMapPutFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf( + "Ljava/lang/String;", + "Ljava/lang/String;", + ), + opcodes = listOf( + Opcode.CONST_4, + Opcode.CONST_4, + Opcode.CONST_4, + Opcode.MOVE_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.INVOKE_DIRECT_RANGE, + ), +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StatsQueryParameterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StatsQueryParameterFingerprint.kt new file mode 100644 index 000000000..08a05e6a9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/parameter/fingerprints/StatsQueryParameterFingerprint.kt @@ -0,0 +1,7 @@ +package app.revanced.patches.youtube.utils.fix.parameter.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +internal object StatsQueryParameterFingerprint : MethodFingerprint( + strings = listOf("adunit"), +) \ No newline at end of file