Compare commits

...

9 Commits

Author SHA1 Message Date
semantic-release-bot
928df2428d chore(release): 2.191.0-dev.23 [skip ci]
# [2.191.0-dev.23](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.22...v2.191.0-dev.23) (2023-09-30)

### Features

* **SPB Serviceportal Bund:** Add `Remove root detection` patch ([#3049](https://github.com/ReVanced/revanced-patches/issues/3049)) ([3e9e1e2](3e9e1e2577))
2023-09-30 17:25:56 +00:00
David Gnedt
3e9e1e2577 feat(SPB Serviceportal Bund): Add Remove root detection patch (#3049) 2023-09-30 19:22:03 +02:00
semantic-release-bot
5ebec9b424 chore(release): 2.191.0-dev.22 [skip ci]
# [2.191.0-dev.22](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.21...v2.191.0-dev.22) (2023-09-28)

### Bug Fixes

* **YouTube - Premium heading:** Correct inverted logic ([#3042](https://github.com/ReVanced/revanced-patches/issues/3042)) ([0204ff6](0204ff67a9))
2023-09-28 16:10:57 +00:00
aliernfrog
0204ff67a9 fix(YouTube - Premium heading): Correct inverted logic (#3042) 2023-09-28 18:07:55 +02:00
semantic-release-bot
7d2a707030 chore(release): 2.191.0-dev.21 [skip ci]
# [2.191.0-dev.21](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.20...v2.191.0-dev.21) (2023-09-28)

### Bug Fixes

* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#3041](https://github.com/ReVanced/revanced-patches/issues/3041)) ([26e0e4c](26e0e4cd1d))
2023-09-28 13:42:22 +00:00
LisoUseInAIKyrios
26e0e4cd1d fix(YouTube - ReturnYouTubeDislike): Revert support for 18.37.36 (#3041) 2023-09-28 17:39:29 +04:00
semantic-release-bot
40f0a8cd0d chore(release): 2.191.0-dev.20 [skip ci]
# [2.191.0-dev.20](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.19...v2.191.0-dev.20) (2023-09-28)

### Bug Fixes

* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#3038](https://github.com/ReVanced/revanced-patches/issues/3038)) ([47c858e](47c858ef4e))
2023-09-28 13:15:01 +00:00
LisoUseInAIKyrios
47c858ef4e fix(YouTube - Video Id): Fix video id not showing the currently playing video (#3038)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-09-28 15:11:58 +02:00
LisoUseInAIKyrios
b17cd14d7d chore: add missing version 2023-09-28 11:42:15 +04:00
16 changed files with 183 additions and 112 deletions

View File

@@ -1,3 +1,31 @@
# [2.191.0-dev.23](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.22...v2.191.0-dev.23) (2023-09-30)
### Features
* **SPB Serviceportal Bund:** Add `Remove root detection` patch ([#3049](https://github.com/ReVanced/revanced-patches/issues/3049)) ([481bf58](https://github.com/ReVanced/revanced-patches/commit/481bf583afbf954bef1c4e5349a62ea1c623115a))
# [2.191.0-dev.22](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.21...v2.191.0-dev.22) (2023-09-28)
### Bug Fixes
* **YouTube - Premium heading:** Correct inverted logic ([#3042](https://github.com/ReVanced/revanced-patches/issues/3042)) ([b33ed75](https://github.com/ReVanced/revanced-patches/commit/b33ed757370653b8eb0002b0977eedfbc73dbe5e))
# [2.191.0-dev.21](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.20...v2.191.0-dev.21) (2023-09-28)
### Bug Fixes
* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#3041](https://github.com/ReVanced/revanced-patches/issues/3041)) ([3761073](https://github.com/ReVanced/revanced-patches/commit/37610732da87549c22a430bb62d10793dfa2e696))
# [2.191.0-dev.20](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.19...v2.191.0-dev.20) (2023-09-28)
### Bug Fixes
* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#3038](https://github.com/ReVanced/revanced-patches/issues/3038)) ([f6f226b](https://github.com/ReVanced/revanced-patches/commit/f6f226ba281823cb5d2d468c32f6e48551971726))
# [2.191.0-dev.19](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.18...v2.191.0-dev.19) (2023-09-28)

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 2.191.0-dev.19
version = 2.191.0-dev.23

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.serviceportalbund.detection.root
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.serviceportalbund.detection.root.fingerprints.RootDetectionFingerprint
@Patch(
name = "Remove root detection",
description = "Removes the check for root permissions and unlocked bootloader.",
compatiblePackages = [CompatiblePackage("at.gv.bka.serviceportal")]
)
@Suppress("unused")
object RootDetectionPatch : BytecodePatch(
setOf(RootDetectionFingerprint)
) {
override fun execute(context: BytecodeContext) =
RootDetectionFingerprint.result!!.mutableMethod.addInstruction(0, "return-void")
}

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.serviceportalbund.detection.root.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
object RootDetectionFingerprint : MethodFingerprint(
"V",
accessFlags = AccessFlags.PUBLIC.value,
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
}
)

View File

@@ -32,9 +32,9 @@ object PremiumHeadingPatch : ResourcePatch() {
val resDirectory = context["res"]
val (original, replacement) = if (usePremiumHeading!!)
DEFAULT_HEADING_RES to PREMIUM_HEADING_RES
else
PREMIUM_HEADING_RES to DEFAULT_HEADING_RES
else
DEFAULT_HEADING_RES to PREMIUM_HEADING_RES
val variants = arrayOf("light", "dark")

View File

@@ -24,7 +24,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
])
]
)

View File

@@ -31,7 +31,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
PlayerTypeHookPatch::class,
],
compatiblePackages = [
CompatiblePackage("com.google.android.youtube", ["18.37.36"])
CompatiblePackage("com.google.android.youtube", ["18.32.39"])
]
)
@Suppress("unused")
@@ -51,9 +51,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
override fun execute(context: BytecodeContext) {
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.
// This patch needs a few adjustments and lots of testing before it can change to the new video id hook.
// There's a few corner cases and some weirdness when loading new videos (specifically with detecting shorts).
VideoIdPatch.legacyInjectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
VideoIdPatch.hookVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
// endregion
@@ -91,40 +89,49 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
throw TextComponentAtomicReferenceFingerprint.exception
}?.let { textComponentContextFingerprintResult ->
val conversionContextIndex = textComponentContextFingerprintResult
.scanResult.patternScanResult!!.endIndex
.scanResult.patternScanResult!!.startIndex
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
.scanResult.patternScanResult!!.startIndex
val insertIndex = atomicReferenceStartIndex + 9
val insertIndex = atomicReferenceStartIndex + 6
textComponentContextFingerprintResult.mutableMethod.apply {
// Get the conversion context obfuscated field name
// Get the conversion context obfuscated field name, and the registers for the AtomicReference and CharSequence
val conversionContextFieldReference =
getInstruction<ReferenceInstruction>(conversionContextIndex).reference
// Free register to hold the conversion context
// Reuse the free register to make room for the atomic reference register.
val freeRegister =
getInstruction<TwoRegisterInstruction>(atomicReferenceStartIndex).registerB
val atomicReferenceRegister =
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 6).registerC
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 1).registerC
// Instruction that is replaced, and also has the CharacterSequence register.
val moveCharSequenceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
val moveCharSequenceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex - 1)
val charSequenceSourceRegister = moveCharSequenceInstruction.registerB
val charSequenceTargetRegister = moveCharSequenceInstruction.registerA
// In order to preserve the atomic reference register, because it is overwritten,
// use another free register to store it.
replaceInstruction(
atomicReferenceStartIndex + 2,
"move-result-object v$freeRegister"
)
replaceInstruction(
atomicReferenceStartIndex + 3,
"move-object v$charSequenceSourceRegister, v$freeRegister"
)
// Move the current instance to the free register, and get the conversion context from it.
// Must replace the instruction to preserve the control flow label.
replaceInstruction(insertIndex, "move-object/from16 v$freeRegister, p0")
replaceInstruction(insertIndex - 1, "move-object/from16 v$freeRegister, p0")
addInstructions(
insertIndex + 1,
insertIndex,
"""
# Move context to free register
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
invoke-static {v$freeRegister, v$atomicReferenceRegister, v$charSequenceSourceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$freeRegister
# Replace the original instruction
# Replace the original char sequence with the modified one.
move-object v${charSequenceTargetRegister}, v${freeRegister}
"""
)
@@ -143,7 +150,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
val isDisLikesBooleanReference = getInstruction<ReferenceInstruction>(patternResult.endIndex).reference
val textViewFieldReference = // Like/Dislike button TextView field
getInstruction<ReferenceInstruction>(patternResult.endIndex - 1).reference
getInstruction<ReferenceInstruction>(patternResult.endIndex - 2).reference
// Check if the hooked TextView object is that of the dislike button.
// If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.

View File

@@ -27,6 +27,7 @@ object ShortsTextViewFingerprint : MethodFingerprint(
Opcode.IF_EQ,
Opcode.RETURN_VOID,
Opcode.IGET_OBJECT, // TextView field
Opcode.CHECK_CAST,
Opcode.IGET_BOOLEAN, // boolean field
)
)

View File

@@ -13,17 +13,13 @@ object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.MOVE_OBJECT, // Register B is free register
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT, // Register A and B is context, use B as context, reuse A as free register
Opcode.INVOKE_VIRTUAL, // Register C is atomic reference
Opcode.MOVE_RESULT_OBJECT, // Register A is char sequence
Opcode.MOVE_OBJECT,
Opcode.CHECK_CAST,
Opcode.MOVE_OBJECT, // Replace this instruction with patch code
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_OBJECT,
Opcode.INVOKE_INTERFACE, // Insert hook here
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,

View File

@@ -13,14 +13,12 @@ object TextComponentContextFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.INVOKE_STATIC_RANGE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT, // conversion context field name
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_BOOLEAN,
Opcode.IGET,
Opcode.IGET,
Opcode.IGET,
)
)

View File

@@ -96,11 +96,8 @@ object SponsorBlockBytecodePatch : BytecodePatch(
/*
* Set current video id.
*
* The new video id hook seems to work without issues,
* but it's easier to keep using this hook as it's well tested and has no known problems.
*/
VideoIdPatch.legacyInjectCallBackgroundPlay("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
VideoIdPatch.hookBackgroundPlayVideoId("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
/*
* Seekbar drawing

View File

@@ -88,7 +88,9 @@ object SpoofSignaturePatch : BytecodePatch(
)
// Hook the player parameters.
PlayerResponseMethodHookPatch.injectProtoBufferHook("$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;")
PlayerResponseMethodHookPatch + PlayerResponseMethodHookPatch.Hook.ProtoBufferParameter(
"$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;"
)
// Force the seekbar time and chapters to always show up.
// This is used only if the storyboard spec fetch fails, or when viewing paid videos.

View File

@@ -109,9 +109,13 @@ object VideoInformationPatch : BytecodePatch(
}
/*
* Inject call for video id
* Inject call for video ids
*/
VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V")
val videoIdMethodDescriptor = "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V"
VideoIdPatch.hookVideoId(videoIdMethodDescriptor)
VideoIdPatch.hookBackgroundPlayVideoId(videoIdMethodDescriptor)
VideoIdPatch.hookPlayerResponseVideoId(
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;)V")
/*
* Set the video time method

View File

@@ -7,66 +7,58 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.misc.fix.playback.SpoofSignaturePatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import java.io.Closeable
@Patch(
dependencies = [IntegrationsPatch::class],
)
object PlayerResponseMethodHookPatch : BytecodePatch(
setOf(
PlayerParameterBuilderFingerprint,
)
) {
private const val playerResponseVideoIdParameter = 1
private const val playerResponseProtoBufferParameter = 3
/**
* Insert index when adding a video id hook.
*/
private var playerResponseVideoIdInsertIndex = 0
/**
* Insert index when adding a proto buffer override.
* Must be after all video id hooks in the same method.
*/
private var playerResponseProtoBufferInsertIndex = 0
object PlayerResponseMethodHookPatch :
BytecodePatch(setOf(PlayerParameterBuilderFingerprint)),
Closeable,
MutableSet<PlayerResponseMethodHookPatch.Hook> by mutableSetOf() {
private const val VIDEO_ID_PARAMETER = 1
private const val PROTO_BUFFER_PARAMETER_PARAMETER = 3
private lateinit var playerResponseMethod: MutableMethod
override fun execute(context: BytecodeContext) {
// Hook player parameter.
PlayerParameterBuilderFingerprint.result?.let {
playerResponseMethod = it.mutableMethod
} ?: throw PlayerParameterBuilderFingerprint.exception
playerResponseMethod = PlayerParameterBuilderFingerprint.result?.mutableMethod
?: throw PlayerParameterBuilderFingerprint.exception
}
/**
* Modify the player parameter proto buffer value.
* Used exclusively by [SpoofSignaturePatch].
*/
fun injectProtoBufferHook(methodDescriptor: String) {
playerResponseMethod.addInstructions(
playerResponseProtoBufferInsertIndex,
override fun close() {
fun hookVideoId(hook: Hook) = playerResponseMethod.addInstruction(
0, "invoke-static {p$VIDEO_ID_PARAMETER}, $hook"
)
fun hookProtoBufferParameter(hook: Hook) = playerResponseMethod.addInstructions(
0,
"""
invoke-static {p$playerResponseProtoBufferParameter}, $methodDescriptor
move-result-object p$playerResponseProtoBufferParameter
invoke-static {p$PROTO_BUFFER_PARAMETER_PARAMETER}, $hook
move-result-object p$PROTO_BUFFER_PARAMETER_PARAMETER
"""
)
playerResponseProtoBufferInsertIndex += 2
// Reverse the order in order to preserve insertion order of the hooks.
val beforeVideoIdHooks = filterIsInstance<Hook.ProtoBufferParameterBeforeVideoId>().asReversed()
val videoIdHooks = filterIsInstance<Hook.VideoId>().asReversed()
val afterVideoIdHooks = filterIsInstance<Hook.ProtoBufferParameter>().asReversed()
// Add the hooks in this specific order as they insert instructions at the beginning of the method.
afterVideoIdHooks.forEach(::hookProtoBufferParameter)
videoIdHooks.forEach(::hookVideoId)
beforeVideoIdHooks.forEach(::hookProtoBufferParameter)
}
/**
* Used by [VideoIdPatch].
*/
internal fun injectVideoIdHook(methodDescriptor: String) {
playerResponseMethod.addInstruction(
// Keep injection calls in the order they're added,
// and all video id hooks run before proto buffer hooks.
playerResponseVideoIdInsertIndex++,
"invoke-static {p$playerResponseVideoIdParameter}, $methodDescriptor"
)
playerResponseProtoBufferInsertIndex++
internal abstract class Hook(private val methodDescriptor: String) {
internal class VideoId(methodDescriptor: String) : Hook(methodDescriptor)
internal class ProtoBufferParameter(methodDescriptor: String) : Hook(methodDescriptor)
internal class ProtoBufferParameterBeforeVideoId(methodDescriptor: String) : Hook(methodDescriptor)
override fun toString() = methodDescriptor
}
}

View File

@@ -26,8 +26,8 @@ object VideoIdPatch : BytecodePatch(
)
) {
private var videoIdRegister = 0
private var insertIndex = 0
private lateinit var insertMethod: MutableMethod
private var videoIdInsertIndex = 0
private lateinit var videoIdMethod: MutableMethod
private var backgroundPlaybackVideoIdRegister = 0
private var backgroundPlaybackInsertIndex = 0
@@ -52,8 +52,8 @@ object VideoIdPatch : BytecodePatch(
} ?: throw VideoIdFingerprint.exception
VideoIdFingerprint.setFields { method, index, register ->
insertMethod = method
insertIndex = index
videoIdMethod = method
videoIdInsertIndex = index
videoIdRegister = register
}
@@ -65,21 +65,7 @@ object VideoIdPatch : BytecodePatch(
}
/**
* Adds an invoke-static instruction, called with the new id when the video changes.
*
* Called as soon as the player response is parsed, and called before many other hooks are
* updated such as [PlayerTypeHookPatch].
*
* Supports all videos and functions in all situations.
*
* Be aware, this can be called multiple times for the same video id.
*
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
*/
fun injectCall(methodDescriptor: String) = PlayerResponseMethodHookPatch.injectVideoIdHook(methodDescriptor)
/**
* Adds an invoke-static instruction, called with the new id when the video changes.
* Hooks the new video id when the video changes.
*
* Supports all videos (regular videos and Shorts).
*
@@ -89,10 +75,10 @@ object VideoIdPatch : BytecodePatch(
*
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
*/
fun legacyInjectCall(
fun hookVideoId(
methodDescriptor: String
) = insertMethod.addInstruction(
insertIndex++,
) = videoIdMethod.addInstruction(
videoIdInsertIndex++,
"invoke-static {v$videoIdRegister}, $methodDescriptor"
)
@@ -106,11 +92,37 @@ object VideoIdPatch : BytecodePatch(
*
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
*/
fun legacyInjectCallBackgroundPlay(
fun hookBackgroundPlayVideoId(
methodDescriptor: String
) = backgroundPlaybackMethod.addInstruction(
backgroundPlaybackInsertIndex++, // move-result-object offset
"invoke-static {v$backgroundPlaybackVideoIdRegister}, $methodDescriptor"
)
/**
* Hooks the video id of every video when loaded.
* Supports all videos and functions in all situations.
*
* Hook is always called off the main thread.
*
* This hook is called as soon as the player response is parsed,
* and called before many other hooks are updated such as [PlayerTypeHookPatch].
*
* Note: The video id returned here may not be the current video that's being played.
* It's common for multiple Shorts to load at once in preparation
* for the user swiping to the next Short.
*
* For most use cases, you probably want to use
* [hookVideoId] or [hookBackgroundPlayVideoId] instead.
*
* Be aware, this can be called multiple times for the same video id.
*
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
*/
fun hookPlayerResponseVideoId(methodDescriptor: String) {
PlayerResponseMethodHookPatch + PlayerResponseMethodHookPatch.Hook.VideoId(
methodDescriptor
)
}
}