fix(youtube): reliably resolve fingerprints

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
oSumAtrIX 2023-01-28 06:24:24 +01:00
parent c4c9e5bb37
commit 1598306eb5
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
7 changed files with 76 additions and 64 deletions

View file

@ -5,10 +5,7 @@ import org.jf.dexlib2.Opcode
object PivotBarCreateButtonViewFingerprint : MethodFingerprint( object PivotBarCreateButtonViewFingerprint : MethodFingerprint(
opcodes = listOf( opcodes = listOf(
Opcode.MOVE_OBJECT,
Opcode.INVOKE_DIRECT_RANGE, // unique instruction anchor Opcode.INVOKE_DIRECT_RANGE, // unique instruction anchor
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC
) )
) )

View file

@ -22,6 +22,7 @@ import app.revanced.patches.youtube.layout.pivotbar.utils.InjectionUtils.REGISTE
import app.revanced.patches.youtube.layout.pivotbar.utils.InjectionUtils.injectHook import app.revanced.patches.youtube.layout.pivotbar.utils.InjectionUtils.injectHook
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import org.jf.dexlib2.Opcode
@Patch @Patch
@DependsOn([IntegrationsPatch::class, ResourceMappingPatch::class, SettingsPatch::class, ResolvePivotBarFingerprintsPatch::class]) @DependsOn([IntegrationsPatch::class, ResourceMappingPatch::class, SettingsPatch::class, ResolvePivotBarFingerprintsPatch::class])
@ -54,17 +55,24 @@ class CreateButtonRemoverPatch : BytecodePatch() {
return PivotBarCreateButtonViewFingerprint.toErrorResult() return PivotBarCreateButtonViewFingerprint.toErrorResult()
} }
val createButtonResult = PivotBarCreateButtonViewFingerprint.result!! PivotBarCreateButtonViewFingerprint.result!!.apply {
val insertIndex = createButtonResult.scanResult.patternScanResult!!.endIndex val insertIndex = mutableMethod.implementation!!.instructions.let {
val scanStart = scanResult.patternScanResult!!.endIndex
/* scanStart + it.subList(scanStart, it.size - 1).indexOfFirst { instruction ->
* Inject hooks instruction.opcode == Opcode.INVOKE_STATIC
*/ }
}
val hook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " + /*
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideCreateButton(Landroid/view/View;)V" * Inject hooks
*/
val hook = "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, " +
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideCreateButton(Landroid/view/View;)V"
mutableMethod.injectHook(hook, insertIndex)
}
createButtonResult.mutableMethod.injectHook(hook, insertIndex)
return PatchResultSuccess() return PatchResultSuccess()
} }

View file

@ -4,33 +4,14 @@ import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(3) @FuzzyPatternScanMethod(3)
object EngagementPanelControllerFingerprint : MethodFingerprint( object EngagementPanelControllerFingerprint : MethodFingerprint(
"L", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("L", "L", "Z", "Z", "Z"), listOf( returnType = "L",
Opcode.MOVE_OBJECT_FROM16, access = AccessFlags.PRIVATE or AccessFlags.FINAL,
Opcode.MOVE_OBJECT_FROM16, strings = listOf(
Opcode.MOVE_FROM16, "EngagementPanelController: cannot show EngagementPanel before EngagementPanelController.init() has been called.",
Opcode.IGET_BOOLEAN, "[EngagementPanel] Cannot show EngagementPanel before EngagementPanelController.init() has been called."
Opcode.CONST_4,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.SGET_OBJECT,
Opcode.SGET_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.RETURN_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.CONST_4,
) )
) )

View file

@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.playerpopuppanels.patch package app.revanced.patches.youtube.layout.playerpopuppanels.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
@ -10,12 +11,12 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.layout.playerpopuppanels.annotations.PlayerPopupPanelsCompatibility import app.revanced.patches.youtube.layout.playerpopuppanels.annotations.PlayerPopupPanelsCompatibility
import app.revanced.patches.youtube.layout.playerpopuppanels.fingerprints.EngagementPanelControllerFingerprint import app.revanced.patches.youtube.layout.playerpopuppanels.fingerprints.EngagementPanelControllerFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
@Patch @Patch
@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) @DependsOn([IntegrationsPatch::class, SettingsPatch::class])
@ -39,7 +40,8 @@ class PlayerPopupPanelsPatch : BytecodePatch(
) )
) )
val engagementPanelControllerMethod = EngagementPanelControllerFingerprint.result!!.mutableMethod val engagementPanelControllerMethod = EngagementPanelControllerFingerprint
.result?.mutableMethod ?: return EngagementPanelControllerFingerprint.toErrorResult()
engagementPanelControllerMethod.addInstructions( engagementPanelControllerMethod.addInstructions(
0, """ 0, """

View file

@ -0,0 +1,12 @@
package app.revanced.patches.youtube.misc.videobuffer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object InvokeMaxBufferFingerprint : MethodFingerprint(
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("J", "J", "F"),
listOf(Opcode.CONST_WIDE_16),
strings = listOf("scl.")
)

View file

@ -1,19 +1,8 @@
package app.revanced.patches.youtube.misc.videobuffer.fingerprints package app.revanced.patches.youtube.misc.videobuffer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
object MaxBufferFingerprint : MethodFingerprint( object MaxBufferFingerprint : MethodFingerprint(
"I", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), opcodes = listOf(Opcode.SGET_OBJECT, Opcode.IGET, Opcode.IF_EQZ, Opcode.RETURN),
listOf(Opcode.SGET_OBJECT, Opcode.IGET, Opcode.IF_EQZ, Opcode.RETURN),
customFingerprint = { methodDef ->
methodDef.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;"
&& methodDef.implementation!!.instructions.any {
((it as? NarrowLiteralInstruction)?.narrowLiteral == 120000)
&& methodDef.name == "r"
}
}
) )

View file

@ -1,12 +1,15 @@
package app.revanced.patches.youtube.misc.videobuffer.patch package app.revanced.patches.youtube.misc.videobuffer.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@ -19,6 +22,7 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.TextPreference import app.revanced.patches.shared.settings.preference.impl.TextPreference
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.InvokeMaxBufferFingerprint
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.MaxBufferFingerprint import app.revanced.patches.youtube.misc.videobuffer.fingerprints.MaxBufferFingerprint
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.PlaybackBufferFingerprint import app.revanced.patches.youtube.misc.videobuffer.fingerprints.PlaybackBufferFingerprint
import app.revanced.patches.youtube.misc.videobuffer.fingerprints.ReBufferFingerprint import app.revanced.patches.youtube.misc.videobuffer.fingerprints.ReBufferFingerprint
@ -32,7 +36,9 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Version("0.0.1") @Version("0.0.1")
class CustomVideoBufferPatch : BytecodePatch( class CustomVideoBufferPatch : BytecodePatch(
listOf( listOf(
MaxBufferFingerprint, PlaybackBufferFingerprint, ReBufferFingerprint InvokeMaxBufferFingerprint,
PlaybackBufferFingerprint,
ReBufferFingerprint,
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
@ -103,8 +109,26 @@ class CustomVideoBufferPatch : BytecodePatch(
MaxBufferFingerprint, MaxBufferFingerprint,
"getMaxBuffer", "getMaxBuffer",
PatchInfo.UnwrapInfo(true, -1) PatchInfo.UnwrapInfo(true, -1)
) ),
); preparation@{
InvokeMaxBufferFingerprint.result?.apply {
val maxBufferMethodCallOffset = 2
val maxBufferMethod = this@preparation.toMethodWalker(method)
.nextMethod(scanResult.patternScanResult!!.endIndex + maxBufferMethodCallOffset)
.getMethod()
if (!MaxBufferFingerprint.resolve(
this@preparation,
maxBufferMethod,
// This is inefficient because toMethodWalker technically already has context about this.
// Alternatively you can iterate manually over all classes
// instead of relying on toMethodWalker.
this@preparation.findClass(maxBufferMethod.definingClass)!!.immutableClass,
)
) throw MaxBufferFingerprint.toErrorResult()
} ?: throw InvokeMaxBufferFingerprint.toErrorResult()
});
/** /**
* Information about a patch. * Information about a patch.
@ -121,11 +145,11 @@ class CustomVideoBufferPatch : BytecodePatch(
/** /**
* Information on how to treat a [MethodFingerprint]. * Information on how to treat a [MethodFingerprint].
* *
* @param forEndIndex Whether to retrieve information from the [MethodFingerprint] * @param useEndIndex Whether to retrieve information of the [MethodFingerprint]
* from the end or start index of its pattern scan result. * from the end index of its pattern scan result.
* @param offset An additional offset to [forEndIndex]. * @param offset An additional offset to [useEndIndex].
*/ */
class UnwrapInfo(val forEndIndex: Boolean = false, val offset: Int = 0) class UnwrapInfo(val useEndIndex: Boolean = false, val offset: Int = 0)
} }
fun hook(context: BytecodeContext) { fun hook(context: BytecodeContext) {
@ -149,12 +173,11 @@ class CustomVideoBufferPatch : BytecodePatch(
val result = this.result!! val result = this.result!!
val method = result.mutableMethod val method = result.mutableMethod
val scanResult = result.scanResult.patternScanResult!! val scanResult = result.scanResult.patternScanResult!!
val index = ( val index =
if (unwrapInfo?.forEndIndex == true) if (unwrapInfo?.useEndIndex == true) scanResult.endIndex
scanResult.endIndex else {
else scanResult.startIndex
scanResult.startIndex } + (unwrapInfo?.offset ?: 0)
) + (unwrapInfo?.offset ?: 0)
val register = (method.instruction(index) as OneRegisterInstruction).registerA val register = (method.instruction(index) as OneRegisterInstruction).registerA