From 69c1f16f7eb0d5759a44f7f7a09b1757ce8f61dd Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 28 Jul 2024 15:53:48 +0200 Subject: [PATCH] fix(YouTube - Spoof client): Fix tracking history on brand accounts (#3480) --- .../misc/fix/playback/SpoofClientPatch.kt | 35 ++++++++++++++++--- .../fingerprints/GetTrackingUriFingerprint.kt | 21 +++++++++++ .../resources/addresources/values/strings.xml | 2 +- 3 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/GetTrackingUriFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofClientPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofClientPatch.kt index de6994840..f188a0a43 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofClientPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/SpoofClientPatch.kt @@ -83,6 +83,9 @@ object SpoofClientPatch : BytecodePatch( // Player speed menu item. CreatePlaybackSpeedMenuItemFingerprint, + + // Watch history. + GetTrackingUriFingerprint, ), ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = @@ -153,7 +156,7 @@ object SpoofClientPatch : BytecodePatch( .getInstructions().find { instruction -> // requestMessage.clientInfo = clientInfoBuilder.build(); instruction.opcode == Opcode.IPUT_OBJECT && - instruction.getReference()?.type == CLIENT_INFO_CLASS_DESCRIPTOR + instruction.getReference()?.type == CLIENT_INFO_CLASS_DESCRIPTOR }?.getReference() ?: throw PatchException("Could not find clientInfoField") // Client info object's client type field. @@ -164,13 +167,15 @@ object SpoofClientPatch : BytecodePatch( // Client info object's client version field. val clientInfoClientVersionField = result.mutableMethod .getInstruction(result.scanResult.stringsScanResult!!.matches.first().index + 1) - .getReference() ?: throw PatchException("Could not find clientInfoClientVersionField") + .getReference() + ?: throw PatchException("Could not find clientInfoClientVersionField") Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField) } val clientInfoClientModelField = CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().let { - val getClientModelIndex = CreatePlayerRequestBodyWithModelFingerprint.indexOfBuildModelInstruction(it.method) + val getClientModelIndex = + CreatePlayerRequestBodyWithModelFingerprint.indexOfBuildModelInstruction(it.method) // The next IPUT_OBJECT instruction after getting the client model is setting the client model field. val index = it.mutableMethod.indexOfFirstInstructionOrThrow(getClientModelIndex) { @@ -198,7 +203,7 @@ object SpoofClientPatch : BytecodePatch( addInstruction( checkCastIndex + 1, "invoke-static { v$requestMessageInstanceRegister }," + - " ${result.classDef.type}->$setClientInfoMethodName($clientInfoContainerClassName)V", + " ${result.classDef.type}->$setClientInfoMethodName($clientInfoContainerClassName)V", ) } @@ -291,7 +296,8 @@ object SpoofClientPatch : BytecodePatch( it.mutableMethod.apply { // Find the conditional check if the playback speed menu item is not created. - val shouldCreateMenuIndex = indexOfFirstInstructionOrThrow(scanResult.endIndex) { opcode == Opcode.IF_EQZ } + val shouldCreateMenuIndex = + indexOfFirstInstructionOrThrow(scanResult.endIndex) { opcode == Opcode.IF_EQZ } val shouldCreateMenuRegister = getInstruction(shouldCreateMenuIndex).registerA addInstructions( @@ -305,5 +311,24 @@ object SpoofClientPatch : BytecodePatch( } // endregion + + // Fix watch history if spoofing to iOS. + + GetTrackingUriFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val returnUrlIndex = it.scanResult.patternScanResult!!.endIndex + val urlRegister = getInstruction(returnUrlIndex).registerA + + addInstructions( + returnUrlIndex, + """ + invoke-static { v$urlRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideTrackingUrl(Landroid/net/Uri;)Landroid/net/Uri; + move-result-object v$urlRegister + """ + ) + } + } + + // endregion } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/GetTrackingUriFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/GetTrackingUriFingerprint.kt new file mode 100644 index 000000000..328fb026f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/fingerprints/GetTrackingUriFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.youtube.misc.fix.playback.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 GetTrackingUriFingerprint : MethodFingerprint( + returnType = "Landroid/net/Uri;", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = emptyList(), + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.RETURN_OBJECT + ), + customFingerprint = { _, classDef -> + classDef.endsWith("TrackingUrlModel;") + } +) diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index 1ffd5736f..fc2924bdc 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -1132,7 +1132,7 @@ This is because Crowdin requires temporarily flattening this file and removing t Client is not spoofed\n\nVideo playback may not work Turning off this setting may cause video playback issues. Spoof client to iOS - Client is currently spoofed to iOS\n\nSide effects include:\n• No HDR video\n• Watch history may not work\n• Higher video qualities may be missing\n• Live streams cannot play as audio only\n• Live streams not available on Android 8.0 + Client is currently spoofed to iOS\n\nSide effects include:\n• No HDR video\n• Higher video qualities may be missing\n• Live streams cannot play as audio only\n• Live streams not available on Android 8.0 Client is currently spoofed to Android VR\n\nSide effects include:\n• No HDR video\n• Kids videos do not playback\n• Paused videos can randomly resume\n• Low quality Shorts seekbar thumbnails\n• Download action button is always hidden\n• End screen cards are always hidden Spoof client thumbnails not available (API timed out) Spoof client thumbnails temporarily not available: %s